xref: /reactos/ntoskrnl/fstub/disksup.c (revision c2c66aff)
1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * PROJECT:         ReactOS Kernel
3*c2c66affSColin Finck * LICENSE:         GPL - See COPYING in the top level directory
4*c2c66affSColin Finck * FILE:            ntoskrnl/fstub/disksup.c
5*c2c66affSColin Finck * PURPOSE:         I/O HAL Routines for Disk Access
6*c2c66affSColin Finck * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
7*c2c66affSColin Finck *                  Eric Kohl
8*c2c66affSColin Finck *                  Casper S. Hornstrup (chorns@users.sourceforge.net)
9*c2c66affSColin Finck */
10*c2c66affSColin Finck 
11*c2c66affSColin Finck /* INCLUDES ******************************************************************/
12*c2c66affSColin Finck 
13*c2c66affSColin Finck #include <ntoskrnl.h>
14*c2c66affSColin Finck #define NDEBUG
15*c2c66affSColin Finck #include <debug.h>
16*c2c66affSColin Finck #include <internal/hal.h>
17*c2c66affSColin Finck 
18*c2c66affSColin Finck /* DEPRECATED FUNCTIONS ******************************************************/
19*c2c66affSColin Finck 
20*c2c66affSColin Finck #if 1
21*c2c66affSColin Finck const WCHAR DiskMountString[] = L"\\DosDevices\\%C:";
22*c2c66affSColin Finck 
23*c2c66affSColin Finck #define AUTO_DRIVE         MAXULONG
24*c2c66affSColin Finck 
25*c2c66affSColin Finck #define PARTITION_MAGIC    0xaa55
26*c2c66affSColin Finck 
27*c2c66affSColin Finck #define EFI_PMBR_OSTYPE_EFI 0xEE
28*c2c66affSColin Finck 
29*c2c66affSColin Finck #include <pshpack1.h>
30*c2c66affSColin Finck 
31*c2c66affSColin Finck typedef struct _REG_DISK_MOUNT_INFO
32*c2c66affSColin Finck {
33*c2c66affSColin Finck     ULONG Signature;
34*c2c66affSColin Finck     LARGE_INTEGER StartingOffset;
35*c2c66affSColin Finck } REG_DISK_MOUNT_INFO, *PREG_DISK_MOUNT_INFO;
36*c2c66affSColin Finck 
37*c2c66affSColin Finck #include <poppack.h>
38*c2c66affSColin Finck 
39*c2c66affSColin Finck typedef enum _DISK_MANAGER
40*c2c66affSColin Finck {
41*c2c66affSColin Finck     NoDiskManager,
42*c2c66affSColin Finck     OntrackDiskManager,
43*c2c66affSColin Finck     EZ_Drive
44*c2c66affSColin Finck } DISK_MANAGER;
45*c2c66affSColin Finck 
46*c2c66affSColin Finck static BOOLEAN
47*c2c66affSColin Finck HalpAssignDrive(IN PUNICODE_STRING PartitionName,
48*c2c66affSColin Finck                 IN ULONG DriveNumber,
49*c2c66affSColin Finck                 IN UCHAR DriveType,
50*c2c66affSColin Finck                 IN ULONG Signature,
51*c2c66affSColin Finck                 IN LARGE_INTEGER StartingOffset,
52*c2c66affSColin Finck                 IN HANDLE hKey,
53*c2c66affSColin Finck                 IN PUNICODE_STRING BootDevice,
54*c2c66affSColin Finck                 OUT PUCHAR NtSystemPath)
55*c2c66affSColin Finck {
56*c2c66affSColin Finck     WCHAR DriveNameBuffer[16];
57*c2c66affSColin Finck     UNICODE_STRING DriveName;
58*c2c66affSColin Finck     ULONG i;
59*c2c66affSColin Finck     NTSTATUS Status;
60*c2c66affSColin Finck     REG_DISK_MOUNT_INFO DiskMountInfo;
61*c2c66affSColin Finck 
62*c2c66affSColin Finck     DPRINT("HalpAssignDrive()\n");
63*c2c66affSColin Finck 
64*c2c66affSColin Finck     if ((DriveNumber != AUTO_DRIVE) && (DriveNumber < 26))
65*c2c66affSColin Finck     {
66*c2c66affSColin Finck         /* Force assignment */
67*c2c66affSColin Finck         KeAcquireGuardedMutex(&ObpDeviceMapLock);
68*c2c66affSColin Finck         if ((ObSystemDeviceMap->DriveMap & (1 << DriveNumber)) != 0)
69*c2c66affSColin Finck         {
70*c2c66affSColin Finck             DbgPrint("Drive letter already used!\n");
71*c2c66affSColin Finck             KeReleaseGuardedMutex(&ObpDeviceMapLock);
72*c2c66affSColin Finck             return FALSE;
73*c2c66affSColin Finck         }
74*c2c66affSColin Finck         KeReleaseGuardedMutex(&ObpDeviceMapLock);
75*c2c66affSColin Finck     }
76*c2c66affSColin Finck     else
77*c2c66affSColin Finck     {
78*c2c66affSColin Finck         /* Automatic assignment */
79*c2c66affSColin Finck         DriveNumber = AUTO_DRIVE;
80*c2c66affSColin Finck         KeAcquireGuardedMutex(&ObpDeviceMapLock);
81*c2c66affSColin Finck         for (i = 2; i < 26; i++)
82*c2c66affSColin Finck         {
83*c2c66affSColin Finck             if ((ObSystemDeviceMap->DriveMap & (1 << i)) == 0)
84*c2c66affSColin Finck             {
85*c2c66affSColin Finck                 DriveNumber = i;
86*c2c66affSColin Finck                 break;
87*c2c66affSColin Finck             }
88*c2c66affSColin Finck         }
89*c2c66affSColin Finck         KeReleaseGuardedMutex(&ObpDeviceMapLock);
90*c2c66affSColin Finck 
91*c2c66affSColin Finck         if (DriveNumber == AUTO_DRIVE)
92*c2c66affSColin Finck         {
93*c2c66affSColin Finck             DbgPrint("No drive letter available!\n");
94*c2c66affSColin Finck             return FALSE;
95*c2c66affSColin Finck         }
96*c2c66affSColin Finck     }
97*c2c66affSColin Finck 
98*c2c66affSColin Finck     DPRINT("DriveNumber %lu\n", DriveNumber);
99*c2c66affSColin Finck 
100*c2c66affSColin Finck     /* Build drive name */
101*c2c66affSColin Finck     swprintf(DriveNameBuffer,
102*c2c66affSColin Finck         L"\\??\\%C:",
103*c2c66affSColin Finck         'A' + DriveNumber);
104*c2c66affSColin Finck     RtlInitUnicodeString(&DriveName,
105*c2c66affSColin Finck         DriveNameBuffer);
106*c2c66affSColin Finck 
107*c2c66affSColin Finck     DPRINT("  %wZ ==> %wZ\n",
108*c2c66affSColin Finck         &DriveName,
109*c2c66affSColin Finck         PartitionName);
110*c2c66affSColin Finck 
111*c2c66affSColin Finck     /* Create symbolic link */
112*c2c66affSColin Finck     Status = IoCreateSymbolicLink(&DriveName,
113*c2c66affSColin Finck         PartitionName);
114*c2c66affSColin Finck 
115*c2c66affSColin Finck     if (hKey &&
116*c2c66affSColin Finck         DriveType == DOSDEVICE_DRIVE_FIXED &&
117*c2c66affSColin Finck         Signature)
118*c2c66affSColin Finck     {
119*c2c66affSColin Finck         DiskMountInfo.Signature = Signature;
120*c2c66affSColin Finck         DiskMountInfo.StartingOffset = StartingOffset;
121*c2c66affSColin Finck         swprintf(DriveNameBuffer, DiskMountString, L'A' + DriveNumber);
122*c2c66affSColin Finck         RtlInitUnicodeString(&DriveName, DriveNameBuffer);
123*c2c66affSColin Finck 
124*c2c66affSColin Finck         Status = ZwSetValueKey(hKey,
125*c2c66affSColin Finck             &DriveName,
126*c2c66affSColin Finck             0,
127*c2c66affSColin Finck             REG_BINARY,
128*c2c66affSColin Finck             &DiskMountInfo,
129*c2c66affSColin Finck             sizeof(DiskMountInfo));
130*c2c66affSColin Finck         if (!NT_SUCCESS(Status))
131*c2c66affSColin Finck         {
132*c2c66affSColin Finck             DPRINT1("ZwCreateValueKey failed for %wZ, status=%x\n", &DriveName, Status);
133*c2c66affSColin Finck         }
134*c2c66affSColin Finck     }
135*c2c66affSColin Finck 
136*c2c66affSColin Finck     /* Check if this is a boot partition */
137*c2c66affSColin Finck     if (RtlCompareUnicodeString(PartitionName, BootDevice, FALSE) == 0)
138*c2c66affSColin Finck     {
139*c2c66affSColin Finck         /* Set NtSystemPath to that partition's disk letter */
140*c2c66affSColin Finck         *NtSystemPath = (UCHAR)('A' + DriveNumber);
141*c2c66affSColin Finck     }
142*c2c66affSColin Finck 
143*c2c66affSColin Finck     return TRUE;
144*c2c66affSColin Finck }
145*c2c66affSColin Finck 
146*c2c66affSColin Finck ULONG
147*c2c66affSColin Finck xHalpGetRDiskCount(VOID)
148*c2c66affSColin Finck {
149*c2c66affSColin Finck     NTSTATUS Status;
150*c2c66affSColin Finck     UNICODE_STRING ArcName;
151*c2c66affSColin Finck     PWCHAR ArcNameBuffer;
152*c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
153*c2c66affSColin Finck     HANDLE DirectoryHandle;
154*c2c66affSColin Finck     POBJECT_DIRECTORY_INFORMATION DirectoryInfo;
155*c2c66affSColin Finck     ULONG Skip;
156*c2c66affSColin Finck     ULONG ResultLength;
157*c2c66affSColin Finck     ULONG CurrentRDisk;
158*c2c66affSColin Finck     ULONG RDiskCount;
159*c2c66affSColin Finck     BOOLEAN First = TRUE;
160*c2c66affSColin Finck     ULONG Count;
161*c2c66affSColin Finck 
162*c2c66affSColin Finck     DirectoryInfo = ExAllocatePoolWithTag(PagedPool, 2 * PAGE_SIZE, TAG_FILE_SYSTEM);
163*c2c66affSColin Finck     if (DirectoryInfo == NULL)
164*c2c66affSColin Finck     {
165*c2c66affSColin Finck         return 0;
166*c2c66affSColin Finck     }
167*c2c66affSColin Finck 
168*c2c66affSColin Finck     RtlInitUnicodeString(&ArcName, L"\\ArcName");
169*c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
170*c2c66affSColin Finck         &ArcName,
171*c2c66affSColin Finck         0,
172*c2c66affSColin Finck         NULL,
173*c2c66affSColin Finck         NULL);
174*c2c66affSColin Finck 
175*c2c66affSColin Finck     Status = ZwOpenDirectoryObject (&DirectoryHandle,
176*c2c66affSColin Finck         DIRECTORY_ALL_ACCESS,
177*c2c66affSColin Finck         &ObjectAttributes);
178*c2c66affSColin Finck     if (!NT_SUCCESS(Status))
179*c2c66affSColin Finck     {
180*c2c66affSColin Finck         DPRINT1("ZwOpenDirectoryObject for %wZ failed, status=%lx\n", &ArcName, Status);
181*c2c66affSColin Finck         ExFreePoolWithTag(DirectoryInfo, TAG_FILE_SYSTEM);
182*c2c66affSColin Finck         return 0;
183*c2c66affSColin Finck     }
184*c2c66affSColin Finck 
185*c2c66affSColin Finck     RDiskCount = 0;
186*c2c66affSColin Finck     Skip = 0;
187*c2c66affSColin Finck     while (NT_SUCCESS(Status))
188*c2c66affSColin Finck     {
189*c2c66affSColin Finck         Status = ZwQueryDirectoryObject (DirectoryHandle,
190*c2c66affSColin Finck             DirectoryInfo,
191*c2c66affSColin Finck             2 * PAGE_SIZE,
192*c2c66affSColin Finck             FALSE,
193*c2c66affSColin Finck             First,
194*c2c66affSColin Finck             &Skip,
195*c2c66affSColin Finck             &ResultLength);
196*c2c66affSColin Finck         First = FALSE;
197*c2c66affSColin Finck         if (NT_SUCCESS(Status))
198*c2c66affSColin Finck         {
199*c2c66affSColin Finck             Count = 0;
200*c2c66affSColin Finck             while (DirectoryInfo[Count].Name.Buffer)
201*c2c66affSColin Finck             {
202*c2c66affSColin Finck                 DPRINT("Count %x\n", Count);
203*c2c66affSColin Finck                 DirectoryInfo[Count].Name.Buffer[DirectoryInfo[Count].Name.Length / sizeof(WCHAR)] = 0;
204*c2c66affSColin Finck                 ArcNameBuffer = DirectoryInfo[Count].Name.Buffer;
205*c2c66affSColin Finck                 if (DirectoryInfo[Count].Name.Length >= sizeof(L"multi(0)disk(0)rdisk(0)") - sizeof(WCHAR) &&
206*c2c66affSColin Finck                     !_wcsnicmp(ArcNameBuffer, L"multi(0)disk(0)rdisk(", (sizeof(L"multi(0)disk(0)rdisk(") - sizeof(WCHAR)) / sizeof(WCHAR)))
207*c2c66affSColin Finck                 {
208*c2c66affSColin Finck                     DPRINT("%S\n", ArcNameBuffer);
209*c2c66affSColin Finck                     ArcNameBuffer += (sizeof(L"multi(0)disk(0)rdisk(") - sizeof(WCHAR)) / sizeof(WCHAR);
210*c2c66affSColin Finck                     CurrentRDisk = 0;
211*c2c66affSColin Finck                     while (iswdigit(*ArcNameBuffer))
212*c2c66affSColin Finck                     {
213*c2c66affSColin Finck                         CurrentRDisk = CurrentRDisk * 10 + *ArcNameBuffer - L'0';
214*c2c66affSColin Finck                         ArcNameBuffer++;
215*c2c66affSColin Finck                     }
216*c2c66affSColin Finck                     if (!_wcsicmp(ArcNameBuffer, L")") &&
217*c2c66affSColin Finck                         CurrentRDisk >= RDiskCount)
218*c2c66affSColin Finck                     {
219*c2c66affSColin Finck                         RDiskCount = CurrentRDisk + 1;
220*c2c66affSColin Finck                     }
221*c2c66affSColin Finck                 }
222*c2c66affSColin Finck                 Count++;
223*c2c66affSColin Finck             }
224*c2c66affSColin Finck         }
225*c2c66affSColin Finck     }
226*c2c66affSColin Finck 
227*c2c66affSColin Finck     ZwClose(DirectoryHandle);
228*c2c66affSColin Finck 
229*c2c66affSColin Finck     ExFreePoolWithTag(DirectoryInfo, TAG_FILE_SYSTEM);
230*c2c66affSColin Finck     return RDiskCount;
231*c2c66affSColin Finck }
232*c2c66affSColin Finck 
233*c2c66affSColin Finck NTSTATUS
234*c2c66affSColin Finck xHalpGetDiskNumberFromRDisk(ULONG RDisk, PULONG DiskNumber)
235*c2c66affSColin Finck {
236*c2c66affSColin Finck     WCHAR NameBuffer[80];
237*c2c66affSColin Finck     UNICODE_STRING ArcName;
238*c2c66affSColin Finck     UNICODE_STRING LinkName;
239*c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
240*c2c66affSColin Finck     HANDLE LinkHandle;
241*c2c66affSColin Finck     NTSTATUS Status;
242*c2c66affSColin Finck 
243*c2c66affSColin Finck     swprintf(NameBuffer,
244*c2c66affSColin Finck         L"\\ArcName\\multi(0)disk(0)rdisk(%lu)",
245*c2c66affSColin Finck         RDisk);
246*c2c66affSColin Finck 
247*c2c66affSColin Finck     RtlInitUnicodeString(&ArcName, NameBuffer);
248*c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
249*c2c66affSColin Finck         &ArcName,
250*c2c66affSColin Finck         0,
251*c2c66affSColin Finck         NULL,
252*c2c66affSColin Finck         NULL);
253*c2c66affSColin Finck     Status = ZwOpenSymbolicLinkObject(&LinkHandle,
254*c2c66affSColin Finck         SYMBOLIC_LINK_ALL_ACCESS,
255*c2c66affSColin Finck         &ObjectAttributes);
256*c2c66affSColin Finck     if (!NT_SUCCESS(Status))
257*c2c66affSColin Finck     {
258*c2c66affSColin Finck         DPRINT1("ZwOpenSymbolicLinkObject failed for %wZ, status=%lx\n", &ArcName, Status);
259*c2c66affSColin Finck         return Status;
260*c2c66affSColin Finck     }
261*c2c66affSColin Finck 
262*c2c66affSColin Finck     LinkName.Buffer = NameBuffer;
263*c2c66affSColin Finck     LinkName.Length = 0;
264*c2c66affSColin Finck     LinkName.MaximumLength = sizeof(NameBuffer);
265*c2c66affSColin Finck     Status = ZwQuerySymbolicLinkObject(LinkHandle,
266*c2c66affSColin Finck         &LinkName,
267*c2c66affSColin Finck         NULL);
268*c2c66affSColin Finck     ZwClose(LinkHandle);
269*c2c66affSColin Finck     if (!NT_SUCCESS(Status))
270*c2c66affSColin Finck     {
271*c2c66affSColin Finck         DPRINT1("ZwQuerySymbolicLinkObject failed, status=%lx\n", Status);
272*c2c66affSColin Finck         return Status;
273*c2c66affSColin Finck     }
274*c2c66affSColin Finck     if (LinkName.Length < sizeof(L"\\Device\\Harddisk0\\Partition0") - sizeof(WCHAR) ||
275*c2c66affSColin Finck         LinkName.Length >= sizeof(NameBuffer))
276*c2c66affSColin Finck     {
277*c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
278*c2c66affSColin Finck     }
279*c2c66affSColin Finck 
280*c2c66affSColin Finck     NameBuffer[LinkName.Length / sizeof(WCHAR)] = 0;
281*c2c66affSColin Finck     if (_wcsnicmp(NameBuffer, L"\\Device\\Harddisk", (sizeof(L"\\Device\\Harddisk") - sizeof(WCHAR)) / sizeof(WCHAR)))
282*c2c66affSColin Finck     {
283*c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
284*c2c66affSColin Finck     }
285*c2c66affSColin Finck     LinkName.Buffer += (sizeof(L"\\Device\\Harddisk") - sizeof(WCHAR)) / sizeof(WCHAR);
286*c2c66affSColin Finck 
287*c2c66affSColin Finck     if (!iswdigit(*LinkName.Buffer))
288*c2c66affSColin Finck     {
289*c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
290*c2c66affSColin Finck     }
291*c2c66affSColin Finck     *DiskNumber = 0;
292*c2c66affSColin Finck     while (iswdigit(*LinkName.Buffer))
293*c2c66affSColin Finck     {
294*c2c66affSColin Finck         *DiskNumber = *DiskNumber * 10 + *LinkName.Buffer - L'0';
295*c2c66affSColin Finck         LinkName.Buffer++;
296*c2c66affSColin Finck     }
297*c2c66affSColin Finck     if (_wcsicmp(LinkName.Buffer, L"\\Partition0"))
298*c2c66affSColin Finck     {
299*c2c66affSColin Finck         return STATUS_UNSUCCESSFUL;
300*c2c66affSColin Finck     }
301*c2c66affSColin Finck     return STATUS_SUCCESS;
302*c2c66affSColin Finck }
303*c2c66affSColin Finck 
304*c2c66affSColin Finck NTSTATUS
305*c2c66affSColin Finck FASTCALL
306*c2c66affSColin Finck xHalQueryDriveLayout(IN PUNICODE_STRING DeviceName,
307*c2c66affSColin Finck                      OUT PDRIVE_LAYOUT_INFORMATION *LayoutInfo)
308*c2c66affSColin Finck {
309*c2c66affSColin Finck     IO_STATUS_BLOCK StatusBlock;
310*c2c66affSColin Finck     DISK_GEOMETRY DiskGeometry;
311*c2c66affSColin Finck     PDEVICE_OBJECT DeviceObject = NULL;
312*c2c66affSColin Finck     PFILE_OBJECT FileObject;
313*c2c66affSColin Finck     KEVENT Event;
314*c2c66affSColin Finck     PIRP Irp;
315*c2c66affSColin Finck     NTSTATUS Status;
316*c2c66affSColin Finck 
317*c2c66affSColin Finck     DPRINT("xHalpQueryDriveLayout %wZ %p\n",
318*c2c66affSColin Finck         DeviceName,
319*c2c66affSColin Finck         LayoutInfo);
320*c2c66affSColin Finck 
321*c2c66affSColin Finck     /* Get the drives sector size */
322*c2c66affSColin Finck     Status = IoGetDeviceObjectPointer(DeviceName,
323*c2c66affSColin Finck         FILE_READ_ATTRIBUTES,
324*c2c66affSColin Finck         &FileObject,
325*c2c66affSColin Finck         &DeviceObject);
326*c2c66affSColin Finck     if (!NT_SUCCESS(Status))
327*c2c66affSColin Finck     {
328*c2c66affSColin Finck         DPRINT("Status %x\n", Status);
329*c2c66affSColin Finck         return(Status);
330*c2c66affSColin Finck     }
331*c2c66affSColin Finck 
332*c2c66affSColin Finck     KeInitializeEvent(&Event,
333*c2c66affSColin Finck         NotificationEvent,
334*c2c66affSColin Finck         FALSE);
335*c2c66affSColin Finck 
336*c2c66affSColin Finck     Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY,
337*c2c66affSColin Finck         DeviceObject,
338*c2c66affSColin Finck         NULL,
339*c2c66affSColin Finck         0,
340*c2c66affSColin Finck         &DiskGeometry,
341*c2c66affSColin Finck         sizeof(DISK_GEOMETRY),
342*c2c66affSColin Finck         FALSE,
343*c2c66affSColin Finck         &Event,
344*c2c66affSColin Finck         &StatusBlock);
345*c2c66affSColin Finck     if (Irp == NULL)
346*c2c66affSColin Finck     {
347*c2c66affSColin Finck         ObDereferenceObject(FileObject);
348*c2c66affSColin Finck         return(STATUS_INSUFFICIENT_RESOURCES);
349*c2c66affSColin Finck     }
350*c2c66affSColin Finck 
351*c2c66affSColin Finck     Status = IoCallDriver(DeviceObject,
352*c2c66affSColin Finck         Irp);
353*c2c66affSColin Finck     if (Status == STATUS_PENDING)
354*c2c66affSColin Finck     {
355*c2c66affSColin Finck         KeWaitForSingleObject(&Event,
356*c2c66affSColin Finck             Executive,
357*c2c66affSColin Finck             KernelMode,
358*c2c66affSColin Finck             FALSE,
359*c2c66affSColin Finck             NULL);
360*c2c66affSColin Finck         Status = StatusBlock.Status;
361*c2c66affSColin Finck     }
362*c2c66affSColin Finck     if (!NT_SUCCESS(Status))
363*c2c66affSColin Finck     {
364*c2c66affSColin Finck         if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
365*c2c66affSColin Finck         {
366*c2c66affSColin Finck             DiskGeometry.BytesPerSector = 512;
367*c2c66affSColin Finck         }
368*c2c66affSColin Finck         else
369*c2c66affSColin Finck         {
370*c2c66affSColin Finck             ObDereferenceObject(FileObject);
371*c2c66affSColin Finck             return(Status);
372*c2c66affSColin Finck         }
373*c2c66affSColin Finck     }
374*c2c66affSColin Finck 
375*c2c66affSColin Finck     DPRINT("DiskGeometry.BytesPerSector: %lu\n",
376*c2c66affSColin Finck         DiskGeometry.BytesPerSector);
377*c2c66affSColin Finck 
378*c2c66affSColin Finck     if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
379*c2c66affSColin Finck     {
380*c2c66affSColin Finck         PDRIVE_LAYOUT_INFORMATION Buffer;
381*c2c66affSColin Finck 
382*c2c66affSColin Finck         /* Allocate a partition list for a single entry. */
383*c2c66affSColin Finck         Buffer = ExAllocatePoolWithTag(NonPagedPool,
384*c2c66affSColin Finck             sizeof(DRIVE_LAYOUT_INFORMATION), TAG_FILE_SYSTEM);
385*c2c66affSColin Finck         if (Buffer != NULL)
386*c2c66affSColin Finck         {
387*c2c66affSColin Finck             RtlZeroMemory(Buffer,
388*c2c66affSColin Finck                 sizeof(DRIVE_LAYOUT_INFORMATION));
389*c2c66affSColin Finck             Buffer->PartitionCount = 1;
390*c2c66affSColin Finck             *LayoutInfo = Buffer;
391*c2c66affSColin Finck 
392*c2c66affSColin Finck             Status = STATUS_SUCCESS;
393*c2c66affSColin Finck         }
394*c2c66affSColin Finck         else
395*c2c66affSColin Finck         {
396*c2c66affSColin Finck             Status = STATUS_UNSUCCESSFUL;
397*c2c66affSColin Finck         }
398*c2c66affSColin Finck     }
399*c2c66affSColin Finck     else
400*c2c66affSColin Finck     {
401*c2c66affSColin Finck         /* Read the partition table */
402*c2c66affSColin Finck         Status = IoReadPartitionTable(DeviceObject,
403*c2c66affSColin Finck             DiskGeometry.BytesPerSector,
404*c2c66affSColin Finck             TRUE,
405*c2c66affSColin Finck             LayoutInfo);
406*c2c66affSColin Finck     }
407*c2c66affSColin Finck 
408*c2c66affSColin Finck     ObDereferenceObject(FileObject);
409*c2c66affSColin Finck 
410*c2c66affSColin Finck     return(Status);
411*c2c66affSColin Finck }
412*c2c66affSColin Finck 
413*c2c66affSColin Finck VOID
414*c2c66affSColin Finck FASTCALL
415*c2c66affSColin Finck xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
416*c2c66affSColin Finck                          IN PSTRING NtDeviceName,
417*c2c66affSColin Finck                          OUT PUCHAR NtSystemPath,
418*c2c66affSColin Finck                          OUT PSTRING NtSystemPathString)
419*c2c66affSColin Finck {
420*c2c66affSColin Finck     PDRIVE_LAYOUT_INFORMATION *LayoutArray;
421*c2c66affSColin Finck     PCONFIGURATION_INFORMATION ConfigInfo;
422*c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
423*c2c66affSColin Finck     IO_STATUS_BLOCK StatusBlock;
424*c2c66affSColin Finck     UNICODE_STRING UnicodeString1;
425*c2c66affSColin Finck     UNICODE_STRING UnicodeString2;
426*c2c66affSColin Finck     HANDLE FileHandle;
427*c2c66affSColin Finck     PWSTR Buffer1;
428*c2c66affSColin Finck     PWSTR Buffer2;
429*c2c66affSColin Finck     ULONG i, j, k;
430*c2c66affSColin Finck     ULONG DiskNumber;
431*c2c66affSColin Finck     ULONG RDisk;
432*c2c66affSColin Finck     NTSTATUS Status;
433*c2c66affSColin Finck     HANDLE hKey;
434*c2c66affSColin Finck     ULONG Length;
435*c2c66affSColin Finck     PKEY_VALUE_PARTIAL_INFORMATION PartialInformation;
436*c2c66affSColin Finck     PREG_DISK_MOUNT_INFO DiskMountInfo;
437*c2c66affSColin Finck     ULONG RDiskCount;
438*c2c66affSColin Finck     UNICODE_STRING BootDevice;
439*c2c66affSColin Finck 
440*c2c66affSColin Finck     Status = RtlAnsiStringToUnicodeString(&BootDevice,
441*c2c66affSColin Finck                                           NtDeviceName,
442*c2c66affSColin Finck                                           TRUE);
443*c2c66affSColin Finck 
444*c2c66affSColin Finck     DPRINT("xHalIoAssignDriveLetters()\n");
445*c2c66affSColin Finck 
446*c2c66affSColin Finck     ConfigInfo = IoGetConfigurationInformation();
447*c2c66affSColin Finck 
448*c2c66affSColin Finck     RDiskCount = xHalpGetRDiskCount();
449*c2c66affSColin Finck 
450*c2c66affSColin Finck     DPRINT("RDiskCount %lu\n", RDiskCount);
451*c2c66affSColin Finck 
452*c2c66affSColin Finck     Buffer1 = ExAllocatePoolWithTag(PagedPool,
453*c2c66affSColin Finck         64 * sizeof(WCHAR),
454*c2c66affSColin Finck         TAG_FILE_SYSTEM);
455*c2c66affSColin Finck     if (!Buffer1) return;
456*c2c66affSColin Finck 
457*c2c66affSColin Finck     Buffer2 = ExAllocatePoolWithTag(PagedPool,
458*c2c66affSColin Finck         32 * sizeof(WCHAR),
459*c2c66affSColin Finck         TAG_FILE_SYSTEM);
460*c2c66affSColin Finck     if (!Buffer2)
461*c2c66affSColin Finck     {
462*c2c66affSColin Finck         ExFreePoolWithTag(Buffer1, TAG_FILE_SYSTEM);
463*c2c66affSColin Finck         return;
464*c2c66affSColin Finck     }
465*c2c66affSColin Finck 
466*c2c66affSColin Finck     PartialInformation = ExAllocatePoolWithTag(PagedPool,
467*c2c66affSColin Finck         sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(REG_DISK_MOUNT_INFO),
468*c2c66affSColin Finck         TAG_FILE_SYSTEM);
469*c2c66affSColin Finck     if (!PartialInformation)
470*c2c66affSColin Finck     {
471*c2c66affSColin Finck         ExFreePoolWithTag(Buffer2, TAG_FILE_SYSTEM);
472*c2c66affSColin Finck         ExFreePoolWithTag(Buffer1, TAG_FILE_SYSTEM);
473*c2c66affSColin Finck         return;
474*c2c66affSColin Finck     }
475*c2c66affSColin Finck 
476*c2c66affSColin Finck     DiskMountInfo = (PREG_DISK_MOUNT_INFO) PartialInformation->Data;
477*c2c66affSColin Finck 
478*c2c66affSColin Finck     /* Create or open the 'MountedDevices' key */
479*c2c66affSColin Finck     RtlInitUnicodeString(&UnicodeString1, L"\\Registry\\Machine\\SYSTEM\\MountedDevices");
480*c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
481*c2c66affSColin Finck         &UnicodeString1,
482*c2c66affSColin Finck         OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
483*c2c66affSColin Finck         NULL,
484*c2c66affSColin Finck         NULL);
485*c2c66affSColin Finck     Status = ZwCreateKey(&hKey,
486*c2c66affSColin Finck         KEY_ALL_ACCESS,
487*c2c66affSColin Finck         &ObjectAttributes,
488*c2c66affSColin Finck         0,
489*c2c66affSColin Finck         NULL,
490*c2c66affSColin Finck         REG_OPTION_NON_VOLATILE,
491*c2c66affSColin Finck         NULL);
492*c2c66affSColin Finck     if (!NT_SUCCESS(Status))
493*c2c66affSColin Finck     {
494*c2c66affSColin Finck         hKey = NULL;
495*c2c66affSColin Finck         DPRINT("ZwCreateKey failed for %wZ, status=%x\n", &UnicodeString1, Status);
496*c2c66affSColin Finck     }
497*c2c66affSColin Finck 
498*c2c66affSColin Finck     /* Create PhysicalDrive links */
499*c2c66affSColin Finck     DPRINT("Physical disk drives: %lu\n", ConfigInfo->DiskCount);
500*c2c66affSColin Finck     for (i = 0; i < ConfigInfo->DiskCount; i++)
501*c2c66affSColin Finck     {
502*c2c66affSColin Finck         swprintf(Buffer1, L"\\Device\\Harddisk%lu\\Partition0", i);
503*c2c66affSColin Finck         RtlInitUnicodeString(&UnicodeString1, Buffer1);
504*c2c66affSColin Finck 
505*c2c66affSColin Finck         InitializeObjectAttributes(&ObjectAttributes,
506*c2c66affSColin Finck             &UnicodeString1,
507*c2c66affSColin Finck             0,
508*c2c66affSColin Finck             NULL,
509*c2c66affSColin Finck             NULL);
510*c2c66affSColin Finck 
511*c2c66affSColin Finck         Status = ZwOpenFile(&FileHandle,
512*c2c66affSColin Finck             FILE_READ_DATA | SYNCHRONIZE,
513*c2c66affSColin Finck             &ObjectAttributes,
514*c2c66affSColin Finck             &StatusBlock,
515*c2c66affSColin Finck             FILE_SHARE_READ,
516*c2c66affSColin Finck             FILE_SYNCHRONOUS_IO_NONALERT);
517*c2c66affSColin Finck         if (NT_SUCCESS(Status))
518*c2c66affSColin Finck         {
519*c2c66affSColin Finck             ZwClose(FileHandle);
520*c2c66affSColin Finck 
521*c2c66affSColin Finck             swprintf(Buffer2, L"\\??\\PhysicalDrive%lu", i);
522*c2c66affSColin Finck             RtlInitUnicodeString(&UnicodeString2, Buffer2);
523*c2c66affSColin Finck 
524*c2c66affSColin Finck             DPRINT("Creating link: %S ==> %S\n",
525*c2c66affSColin Finck                 Buffer2,
526*c2c66affSColin Finck                 Buffer1);
527*c2c66affSColin Finck 
528*c2c66affSColin Finck             IoCreateSymbolicLink(&UnicodeString2,
529*c2c66affSColin Finck                 &UnicodeString1);
530*c2c66affSColin Finck         }
531*c2c66affSColin Finck     }
532*c2c66affSColin Finck 
533*c2c66affSColin Finck     /* Initialize layout array */
534*c2c66affSColin Finck     if (ConfigInfo->DiskCount == 0)
535*c2c66affSColin Finck         goto end_assign_disks;
536*c2c66affSColin Finck     LayoutArray = ExAllocatePoolWithTag(NonPagedPool,
537*c2c66affSColin Finck         ConfigInfo->DiskCount * sizeof(PDRIVE_LAYOUT_INFORMATION), TAG_FILE_SYSTEM);
538*c2c66affSColin Finck     if (!LayoutArray)
539*c2c66affSColin Finck     {
540*c2c66affSColin Finck         ExFreePoolWithTag(PartialInformation, TAG_FILE_SYSTEM);
541*c2c66affSColin Finck         ExFreePoolWithTag(Buffer2, TAG_FILE_SYSTEM);
542*c2c66affSColin Finck         ExFreePoolWithTag(Buffer1, TAG_FILE_SYSTEM);
543*c2c66affSColin Finck         if (hKey) ObCloseHandle(hKey, KernelMode);
544*c2c66affSColin Finck         return;
545*c2c66affSColin Finck     }
546*c2c66affSColin Finck 
547*c2c66affSColin Finck     RtlZeroMemory(LayoutArray,
548*c2c66affSColin Finck         ConfigInfo->DiskCount * sizeof(PDRIVE_LAYOUT_INFORMATION));
549*c2c66affSColin Finck     for (i = 0; i < ConfigInfo->DiskCount; i++)
550*c2c66affSColin Finck     {
551*c2c66affSColin Finck         swprintf(Buffer1, L"\\Device\\Harddisk%lu\\Partition0", i);
552*c2c66affSColin Finck         RtlInitUnicodeString(&UnicodeString1, Buffer1);
553*c2c66affSColin Finck 
554*c2c66affSColin Finck         Status = xHalQueryDriveLayout(&UnicodeString1, &LayoutArray[i]);
555*c2c66affSColin Finck         if (!NT_SUCCESS(Status))
556*c2c66affSColin Finck         {
557*c2c66affSColin Finck             DbgPrint("xHalQueryDriveLayout() failed (Status = 0x%lx)\n",
558*c2c66affSColin Finck                 Status);
559*c2c66affSColin Finck             LayoutArray[i] = NULL;
560*c2c66affSColin Finck             continue;
561*c2c66affSColin Finck         }
562*c2c66affSColin Finck         /* We don't use the RewritePartition value while mounting the disks.
563*c2c66affSColin Finck         * We use this value for marking pre-assigned (registry) partitions.
564*c2c66affSColin Finck         */
565*c2c66affSColin Finck         for (j = 0; j < LayoutArray[i]->PartitionCount; j++)
566*c2c66affSColin Finck         {
567*c2c66affSColin Finck             LayoutArray[i]->PartitionEntry[j].RewritePartition = FALSE;
568*c2c66affSColin Finck         }
569*c2c66affSColin Finck     }
570*c2c66affSColin Finck 
571*c2c66affSColin Finck #ifndef NDEBUG
572*c2c66affSColin Finck     /* Dump layout array */
573*c2c66affSColin Finck     for (i = 0; i < ConfigInfo->DiskCount; i++)
574*c2c66affSColin Finck     {
575*c2c66affSColin Finck         DPRINT("Harddisk %d:\n",
576*c2c66affSColin Finck             i);
577*c2c66affSColin Finck 
578*c2c66affSColin Finck         if (LayoutArray[i] == NULL)
579*c2c66affSColin Finck             continue;
580*c2c66affSColin Finck 
581*c2c66affSColin Finck         DPRINT("Logical partitions: %d\n",
582*c2c66affSColin Finck             LayoutArray[i]->PartitionCount);
583*c2c66affSColin Finck 
584*c2c66affSColin Finck         for (j = 0; j < LayoutArray[i]->PartitionCount; j++)
585*c2c66affSColin Finck         {
586*c2c66affSColin Finck             DPRINT("  %d: nr:%x boot:%x type:%x startblock:%I64u count:%I64u\n",
587*c2c66affSColin Finck                 j,
588*c2c66affSColin Finck                 LayoutArray[i]->PartitionEntry[j].PartitionNumber,
589*c2c66affSColin Finck                 LayoutArray[i]->PartitionEntry[j].BootIndicator,
590*c2c66affSColin Finck                 LayoutArray[i]->PartitionEntry[j].PartitionType,
591*c2c66affSColin Finck                 LayoutArray[i]->PartitionEntry[j].StartingOffset.QuadPart,
592*c2c66affSColin Finck                 LayoutArray[i]->PartitionEntry[j].PartitionLength.QuadPart);
593*c2c66affSColin Finck         }
594*c2c66affSColin Finck     }
595*c2c66affSColin Finck #endif
596*c2c66affSColin Finck 
597*c2c66affSColin Finck     /* Assign pre-assigned (registry) partitions */
598*c2c66affSColin Finck     if (hKey)
599*c2c66affSColin Finck     {
600*c2c66affSColin Finck         for (k = 2; k < 26; k++)
601*c2c66affSColin Finck         {
602*c2c66affSColin Finck             swprintf(Buffer1, DiskMountString, L'A' + k);
603*c2c66affSColin Finck             RtlInitUnicodeString(&UnicodeString1, Buffer1);
604*c2c66affSColin Finck             Status = ZwQueryValueKey(hKey,
605*c2c66affSColin Finck                 &UnicodeString1,
606*c2c66affSColin Finck                 KeyValuePartialInformation,
607*c2c66affSColin Finck                 PartialInformation,
608*c2c66affSColin Finck                 sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(REG_DISK_MOUNT_INFO),
609*c2c66affSColin Finck                 &Length);
610*c2c66affSColin Finck             if (NT_SUCCESS(Status) &&
611*c2c66affSColin Finck                 PartialInformation->Type == REG_BINARY &&
612*c2c66affSColin Finck                 PartialInformation->DataLength == sizeof(REG_DISK_MOUNT_INFO))
613*c2c66affSColin Finck             {
614*c2c66affSColin Finck                 DPRINT("%wZ => %08x:%08x%08x\n", &UnicodeString1, DiskMountInfo->Signature,
615*c2c66affSColin Finck                     DiskMountInfo->StartingOffset.u.HighPart, DiskMountInfo->StartingOffset.u.LowPart);
616*c2c66affSColin Finck                 {
617*c2c66affSColin Finck                     BOOLEAN Found = FALSE;
618*c2c66affSColin Finck                     for (i = 0; i < ConfigInfo->DiskCount; i++)
619*c2c66affSColin Finck                     {
620*c2c66affSColin Finck                         DPRINT("%x\n", LayoutArray[i]->Signature);
621*c2c66affSColin Finck                         if (LayoutArray[i] &&
622*c2c66affSColin Finck                             LayoutArray[i]->Signature &&
623*c2c66affSColin Finck                             LayoutArray[i]->Signature == DiskMountInfo->Signature)
624*c2c66affSColin Finck                         {
625*c2c66affSColin Finck                             for (j = 0; j < LayoutArray[i]->PartitionCount; j++)
626*c2c66affSColin Finck                             {
627*c2c66affSColin Finck                                 if (LayoutArray[i]->PartitionEntry[j].StartingOffset.QuadPart == DiskMountInfo->StartingOffset.QuadPart)
628*c2c66affSColin Finck                                 {
629*c2c66affSColin Finck                                     if (IsRecognizedPartition(LayoutArray[i]->PartitionEntry[j].PartitionType) &&
630*c2c66affSColin Finck                                         LayoutArray[i]->PartitionEntry[j].RewritePartition == FALSE)
631*c2c66affSColin Finck                                     {
632*c2c66affSColin Finck                                         swprintf(Buffer2,
633*c2c66affSColin Finck                                                  L"\\Device\\Harddisk%lu\\Partition%lu",
634*c2c66affSColin Finck                                                  i,
635*c2c66affSColin Finck                                                  LayoutArray[i]->PartitionEntry[j].PartitionNumber);
636*c2c66affSColin Finck                                         RtlInitUnicodeString(&UnicodeString2, Buffer2);
637*c2c66affSColin Finck 
638*c2c66affSColin Finck                                         /* Assign drive */
639*c2c66affSColin Finck                                         DPRINT("  %wZ\n", &UnicodeString2);
640*c2c66affSColin Finck                                         Found = HalpAssignDrive(&UnicodeString2,
641*c2c66affSColin Finck                                             k,
642*c2c66affSColin Finck                                             DOSDEVICE_DRIVE_FIXED,
643*c2c66affSColin Finck                                             DiskMountInfo->Signature,
644*c2c66affSColin Finck                                             DiskMountInfo->StartingOffset,
645*c2c66affSColin Finck                                             NULL,
646*c2c66affSColin Finck                                             &BootDevice,
647*c2c66affSColin Finck                                             NtSystemPath);
648*c2c66affSColin Finck                                         /* Mark the partition as assigned */
649*c2c66affSColin Finck                                         LayoutArray[i]->PartitionEntry[j].RewritePartition = TRUE;
650*c2c66affSColin Finck                                     }
651*c2c66affSColin Finck                                     break;
652*c2c66affSColin Finck                                 }
653*c2c66affSColin Finck                             }
654*c2c66affSColin Finck                         }
655*c2c66affSColin Finck                     }
656*c2c66affSColin Finck                     if (Found == FALSE)
657*c2c66affSColin Finck                     {
658*c2c66affSColin Finck                         /* We didn't find a partition for this entry, remove them. */
659*c2c66affSColin Finck                         Status = ZwDeleteValueKey(hKey, &UnicodeString1);
660*c2c66affSColin Finck                     }
661*c2c66affSColin Finck                 }
662*c2c66affSColin Finck             }
663*c2c66affSColin Finck         }
664*c2c66affSColin Finck     }
665*c2c66affSColin Finck 
666*c2c66affSColin Finck     /* Assign bootable partition on first harddisk */
667*c2c66affSColin Finck     DPRINT("Assigning bootable primary partition on first harddisk:\n");
668*c2c66affSColin Finck     if (RDiskCount > 0)
669*c2c66affSColin Finck     {
670*c2c66affSColin Finck         Status = xHalpGetDiskNumberFromRDisk(0, &DiskNumber);
671*c2c66affSColin Finck         if (NT_SUCCESS(Status) &&
672*c2c66affSColin Finck             DiskNumber < ConfigInfo->DiskCount &&
673*c2c66affSColin Finck             LayoutArray[DiskNumber])
674*c2c66affSColin Finck         {
675*c2c66affSColin Finck             /* Search for bootable partition */
676*c2c66affSColin Finck             for (j = 0; j < NUM_PARTITION_TABLE_ENTRIES && j < LayoutArray[DiskNumber]->PartitionCount; j++)
677*c2c66affSColin Finck             {
678*c2c66affSColin Finck                 if ((LayoutArray[DiskNumber]->PartitionEntry[j].BootIndicator != FALSE) &&
679*c2c66affSColin Finck                     IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType))
680*c2c66affSColin Finck                 {
681*c2c66affSColin Finck                     if (LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE)
682*c2c66affSColin Finck                     {
683*c2c66affSColin Finck                         swprintf(Buffer2,
684*c2c66affSColin Finck                                  L"\\Device\\Harddisk%lu\\Partition%lu",
685*c2c66affSColin Finck                                  DiskNumber,
686*c2c66affSColin Finck                                  LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
687*c2c66affSColin Finck                         RtlInitUnicodeString(&UnicodeString2, Buffer2);
688*c2c66affSColin Finck 
689*c2c66affSColin Finck                         /* Assign drive */
690*c2c66affSColin Finck                         DPRINT("  %wZ\n", &UnicodeString2);
691*c2c66affSColin Finck                         HalpAssignDrive(&UnicodeString2,
692*c2c66affSColin Finck                             AUTO_DRIVE,
693*c2c66affSColin Finck                             DOSDEVICE_DRIVE_FIXED,
694*c2c66affSColin Finck                             LayoutArray[DiskNumber]->Signature,
695*c2c66affSColin Finck                             LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
696*c2c66affSColin Finck                             hKey,
697*c2c66affSColin Finck                             &BootDevice,
698*c2c66affSColin Finck                             NtSystemPath);
699*c2c66affSColin Finck                         /* Mark the partition as assigned */
700*c2c66affSColin Finck                         LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
701*c2c66affSColin Finck                     }
702*c2c66affSColin Finck                     break;
703*c2c66affSColin Finck                 }
704*c2c66affSColin Finck             }
705*c2c66affSColin Finck         }
706*c2c66affSColin Finck     }
707*c2c66affSColin Finck 
708*c2c66affSColin Finck     /* Assign remaining primary partitions */
709*c2c66affSColin Finck     DPRINT("Assigning remaining primary partitions:\n");
710*c2c66affSColin Finck     for (RDisk = 0; RDisk < RDiskCount; RDisk++)
711*c2c66affSColin Finck     {
712*c2c66affSColin Finck         Status = xHalpGetDiskNumberFromRDisk(RDisk, &DiskNumber);
713*c2c66affSColin Finck         if (NT_SUCCESS(Status) &&
714*c2c66affSColin Finck             DiskNumber < ConfigInfo->DiskCount &&
715*c2c66affSColin Finck             LayoutArray[DiskNumber])
716*c2c66affSColin Finck         {
717*c2c66affSColin Finck             /* Search for primary partitions */
718*c2c66affSColin Finck             for (j = 0; (j < NUM_PARTITION_TABLE_ENTRIES) && (j < LayoutArray[DiskNumber]->PartitionCount); j++)
719*c2c66affSColin Finck             {
720*c2c66affSColin Finck                 if (LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE &&
721*c2c66affSColin Finck                     IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType))
722*c2c66affSColin Finck                 {
723*c2c66affSColin Finck                     swprintf(Buffer2,
724*c2c66affSColin Finck                              L"\\Device\\Harddisk%lu\\Partition%lu",
725*c2c66affSColin Finck                              DiskNumber,
726*c2c66affSColin Finck                              LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
727*c2c66affSColin Finck                     RtlInitUnicodeString(&UnicodeString2, Buffer2);
728*c2c66affSColin Finck 
729*c2c66affSColin Finck                     /* Assign drive */
730*c2c66affSColin Finck                     DPRINT("  %wZ\n",
731*c2c66affSColin Finck                         &UnicodeString2);
732*c2c66affSColin Finck                     HalpAssignDrive(&UnicodeString2,
733*c2c66affSColin Finck                         AUTO_DRIVE,
734*c2c66affSColin Finck                         DOSDEVICE_DRIVE_FIXED,
735*c2c66affSColin Finck                         LayoutArray[DiskNumber]->Signature,
736*c2c66affSColin Finck                         LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
737*c2c66affSColin Finck                         hKey,
738*c2c66affSColin Finck                         &BootDevice,
739*c2c66affSColin Finck                         NtSystemPath);
740*c2c66affSColin Finck                     /* Mark the partition as assigned */
741*c2c66affSColin Finck                     LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
742*c2c66affSColin Finck                 }
743*c2c66affSColin Finck             }
744*c2c66affSColin Finck         }
745*c2c66affSColin Finck     }
746*c2c66affSColin Finck 
747*c2c66affSColin Finck     /* Assign extended (logical) partitions */
748*c2c66affSColin Finck     DPRINT("Assigning extended (logical) partitions:\n");
749*c2c66affSColin Finck     for (RDisk = 0; RDisk < RDiskCount; RDisk++)
750*c2c66affSColin Finck     {
751*c2c66affSColin Finck         Status = xHalpGetDiskNumberFromRDisk(RDisk, &DiskNumber);
752*c2c66affSColin Finck         if (NT_SUCCESS(Status) &&
753*c2c66affSColin Finck             DiskNumber < ConfigInfo->DiskCount &&
754*c2c66affSColin Finck             LayoutArray[DiskNumber])
755*c2c66affSColin Finck         {
756*c2c66affSColin Finck             /* Search for extended partitions */
757*c2c66affSColin Finck             for (j = NUM_PARTITION_TABLE_ENTRIES; j < LayoutArray[DiskNumber]->PartitionCount; j++)
758*c2c66affSColin Finck             {
759*c2c66affSColin Finck                 if (IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType) &&
760*c2c66affSColin Finck                     LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE &&
761*c2c66affSColin Finck                     LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber != 0)
762*c2c66affSColin Finck                 {
763*c2c66affSColin Finck                     swprintf(Buffer2,
764*c2c66affSColin Finck                              L"\\Device\\Harddisk%lu\\Partition%lu",
765*c2c66affSColin Finck                              DiskNumber,
766*c2c66affSColin Finck                              LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
767*c2c66affSColin Finck                     RtlInitUnicodeString(&UnicodeString2, Buffer2);
768*c2c66affSColin Finck 
769*c2c66affSColin Finck                     /* Assign drive */
770*c2c66affSColin Finck                     DPRINT("  %wZ\n",
771*c2c66affSColin Finck                         &UnicodeString2);
772*c2c66affSColin Finck                     HalpAssignDrive(&UnicodeString2,
773*c2c66affSColin Finck                         AUTO_DRIVE,
774*c2c66affSColin Finck                         DOSDEVICE_DRIVE_FIXED,
775*c2c66affSColin Finck                         LayoutArray[DiskNumber]->Signature,
776*c2c66affSColin Finck                         LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
777*c2c66affSColin Finck                         hKey,
778*c2c66affSColin Finck                         &BootDevice,
779*c2c66affSColin Finck                         NtSystemPath);
780*c2c66affSColin Finck                     /* Mark the partition as assigned */
781*c2c66affSColin Finck                     LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
782*c2c66affSColin Finck                 }
783*c2c66affSColin Finck             }
784*c2c66affSColin Finck         }
785*c2c66affSColin Finck     }
786*c2c66affSColin Finck 
787*c2c66affSColin Finck     /* Assign remaining primary partitions without an arc-name */
788*c2c66affSColin Finck     DPRINT("Assigning remaining primary partitions:\n");
789*c2c66affSColin Finck     for (DiskNumber = 0; DiskNumber < ConfigInfo->DiskCount; DiskNumber++)
790*c2c66affSColin Finck     {
791*c2c66affSColin Finck         if (LayoutArray[DiskNumber])
792*c2c66affSColin Finck         {
793*c2c66affSColin Finck             /* Search for primary partitions */
794*c2c66affSColin Finck             for (j = 0; (j < NUM_PARTITION_TABLE_ENTRIES) && (j < LayoutArray[DiskNumber]->PartitionCount); j++)
795*c2c66affSColin Finck             {
796*c2c66affSColin Finck                 if (LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE &&
797*c2c66affSColin Finck                     IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType))
798*c2c66affSColin Finck                 {
799*c2c66affSColin Finck                     swprintf(Buffer2,
800*c2c66affSColin Finck                              L"\\Device\\Harddisk%lu\\Partition%lu",
801*c2c66affSColin Finck                              DiskNumber,
802*c2c66affSColin Finck                              LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
803*c2c66affSColin Finck                     RtlInitUnicodeString(&UnicodeString2, Buffer2);
804*c2c66affSColin Finck 
805*c2c66affSColin Finck                     /* Assign drive */
806*c2c66affSColin Finck                     DPRINT("  %wZ\n",
807*c2c66affSColin Finck                         &UnicodeString2);
808*c2c66affSColin Finck                     HalpAssignDrive(&UnicodeString2,
809*c2c66affSColin Finck                         AUTO_DRIVE,
810*c2c66affSColin Finck                         DOSDEVICE_DRIVE_FIXED,
811*c2c66affSColin Finck                         LayoutArray[DiskNumber]->Signature,
812*c2c66affSColin Finck                         LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
813*c2c66affSColin Finck                         hKey,
814*c2c66affSColin Finck                         &BootDevice,
815*c2c66affSColin Finck                         NtSystemPath);
816*c2c66affSColin Finck                     /* Mark the partition as assigned */
817*c2c66affSColin Finck                     LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
818*c2c66affSColin Finck                 }
819*c2c66affSColin Finck             }
820*c2c66affSColin Finck         }
821*c2c66affSColin Finck     }
822*c2c66affSColin Finck 
823*c2c66affSColin Finck     /* Assign extended (logical) partitions without an arc-name */
824*c2c66affSColin Finck     DPRINT("Assigning extended (logical) partitions:\n");
825*c2c66affSColin Finck     for (DiskNumber = 0; DiskNumber < ConfigInfo->DiskCount; DiskNumber++)
826*c2c66affSColin Finck     {
827*c2c66affSColin Finck         if (LayoutArray[DiskNumber])
828*c2c66affSColin Finck         {
829*c2c66affSColin Finck             /* Search for extended partitions */
830*c2c66affSColin Finck             for (j = NUM_PARTITION_TABLE_ENTRIES; j < LayoutArray[DiskNumber]->PartitionCount; j++)
831*c2c66affSColin Finck             {
832*c2c66affSColin Finck                 if (IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType) &&
833*c2c66affSColin Finck                     LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE &&
834*c2c66affSColin Finck                     LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber != 0)
835*c2c66affSColin Finck                 {
836*c2c66affSColin Finck                     swprintf(Buffer2,
837*c2c66affSColin Finck                              L"\\Device\\Harddisk%lu\\Partition%lu",
838*c2c66affSColin Finck                              DiskNumber,
839*c2c66affSColin Finck                              LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber);
840*c2c66affSColin Finck                     RtlInitUnicodeString(&UnicodeString2, Buffer2);
841*c2c66affSColin Finck 
842*c2c66affSColin Finck                     /* Assign drive */
843*c2c66affSColin Finck                     DPRINT("  %wZ\n",
844*c2c66affSColin Finck                         &UnicodeString2);
845*c2c66affSColin Finck                     HalpAssignDrive(&UnicodeString2,
846*c2c66affSColin Finck                         AUTO_DRIVE,
847*c2c66affSColin Finck                         DOSDEVICE_DRIVE_FIXED,
848*c2c66affSColin Finck                         LayoutArray[DiskNumber]->Signature,
849*c2c66affSColin Finck                         LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset,
850*c2c66affSColin Finck                         hKey,
851*c2c66affSColin Finck                         &BootDevice,
852*c2c66affSColin Finck                         NtSystemPath);
853*c2c66affSColin Finck                     /* Mark the partition as assigned */
854*c2c66affSColin Finck                     LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE;
855*c2c66affSColin Finck                 }
856*c2c66affSColin Finck             }
857*c2c66affSColin Finck         }
858*c2c66affSColin Finck     }
859*c2c66affSColin Finck 
860*c2c66affSColin Finck     /* Assign removable disk drives */
861*c2c66affSColin Finck     DPRINT("Assigning removable disk drives:\n");
862*c2c66affSColin Finck     for (i = 0; i < ConfigInfo->DiskCount; i++)
863*c2c66affSColin Finck     {
864*c2c66affSColin Finck         if (LayoutArray[i])
865*c2c66affSColin Finck         {
866*c2c66affSColin Finck             /* Search for virtual partitions */
867*c2c66affSColin Finck             if (LayoutArray[i]->PartitionCount == 1 &&
868*c2c66affSColin Finck                 LayoutArray[i]->PartitionEntry[0].PartitionType == 0)
869*c2c66affSColin Finck             {
870*c2c66affSColin Finck                 swprintf(Buffer2, L"\\Device\\Harddisk%lu\\Partition1", i);
871*c2c66affSColin Finck                 RtlInitUnicodeString(&UnicodeString2, Buffer2);
872*c2c66affSColin Finck 
873*c2c66affSColin Finck                 /* Assign drive */
874*c2c66affSColin Finck                 DPRINT("  %wZ\n",
875*c2c66affSColin Finck                     &UnicodeString2);
876*c2c66affSColin Finck                 HalpAssignDrive(&UnicodeString2,
877*c2c66affSColin Finck                     AUTO_DRIVE,
878*c2c66affSColin Finck                     DOSDEVICE_DRIVE_REMOVABLE,
879*c2c66affSColin Finck                     0,
880*c2c66affSColin Finck                     RtlConvertLongToLargeInteger(0),
881*c2c66affSColin Finck                     hKey,
882*c2c66affSColin Finck                     &BootDevice,
883*c2c66affSColin Finck                     NtSystemPath);
884*c2c66affSColin Finck             }
885*c2c66affSColin Finck         }
886*c2c66affSColin Finck     }
887*c2c66affSColin Finck 
888*c2c66affSColin Finck     /* Free layout array */
889*c2c66affSColin Finck     for (i = 0; i < ConfigInfo->DiskCount; i++)
890*c2c66affSColin Finck     {
891*c2c66affSColin Finck         if (LayoutArray[i] != NULL)
892*c2c66affSColin Finck             ExFreePoolWithTag(LayoutArray[i], TAG_FILE_SYSTEM);
893*c2c66affSColin Finck     }
894*c2c66affSColin Finck     ExFreePoolWithTag(LayoutArray, TAG_FILE_SYSTEM);
895*c2c66affSColin Finck end_assign_disks:
896*c2c66affSColin Finck 
897*c2c66affSColin Finck     /* Assign floppy drives */
898*c2c66affSColin Finck     DPRINT("Floppy drives: %lu\n", ConfigInfo->FloppyCount);
899*c2c66affSColin Finck     for (i = 0; i < ConfigInfo->FloppyCount; i++)
900*c2c66affSColin Finck     {
901*c2c66affSColin Finck         swprintf(Buffer1, L"\\Device\\Floppy%lu", i);
902*c2c66affSColin Finck         RtlInitUnicodeString(&UnicodeString1, Buffer1);
903*c2c66affSColin Finck 
904*c2c66affSColin Finck         /* Assign drive letters A: or B: or first free drive letter */
905*c2c66affSColin Finck         DPRINT("  %wZ\n",
906*c2c66affSColin Finck             &UnicodeString1);
907*c2c66affSColin Finck         HalpAssignDrive(&UnicodeString1,
908*c2c66affSColin Finck             (i < 2) ? i : AUTO_DRIVE,
909*c2c66affSColin Finck             DOSDEVICE_DRIVE_REMOVABLE,
910*c2c66affSColin Finck             0,
911*c2c66affSColin Finck             RtlConvertLongToLargeInteger(0),
912*c2c66affSColin Finck             hKey,
913*c2c66affSColin Finck             &BootDevice,
914*c2c66affSColin Finck             NtSystemPath);
915*c2c66affSColin Finck     }
916*c2c66affSColin Finck 
917*c2c66affSColin Finck     /* Assign cdrom drives */
918*c2c66affSColin Finck     DPRINT("CD-Rom drives: %lu\n", ConfigInfo->CdRomCount);
919*c2c66affSColin Finck     for (i = 0; i < ConfigInfo->CdRomCount; i++)
920*c2c66affSColin Finck     {
921*c2c66affSColin Finck         swprintf(Buffer1, L"\\Device\\CdRom%lu", i);
922*c2c66affSColin Finck         RtlInitUnicodeString(&UnicodeString1, Buffer1);
923*c2c66affSColin Finck 
924*c2c66affSColin Finck         /* Assign first free drive letter */
925*c2c66affSColin Finck         DPRINT("  %wZ\n", &UnicodeString1);
926*c2c66affSColin Finck         HalpAssignDrive(&UnicodeString1,
927*c2c66affSColin Finck             AUTO_DRIVE,
928*c2c66affSColin Finck             DOSDEVICE_DRIVE_CDROM,
929*c2c66affSColin Finck             0,
930*c2c66affSColin Finck             RtlConvertLongToLargeInteger(0),
931*c2c66affSColin Finck             hKey,
932*c2c66affSColin Finck             &BootDevice,
933*c2c66affSColin Finck             NtSystemPath);
934*c2c66affSColin Finck     }
935*c2c66affSColin Finck 
936*c2c66affSColin Finck     /* Anything else to do? */
937*c2c66affSColin Finck 
938*c2c66affSColin Finck     ExFreePoolWithTag(PartialInformation, TAG_FILE_SYSTEM);
939*c2c66affSColin Finck     ExFreePoolWithTag(Buffer2, TAG_FILE_SYSTEM);
940*c2c66affSColin Finck     ExFreePoolWithTag(Buffer1, TAG_FILE_SYSTEM);
941*c2c66affSColin Finck     if (hKey) ObCloseHandle(hKey, KernelMode);
942*c2c66affSColin Finck }
943*c2c66affSColin Finck 
944*c2c66affSColin Finck #endif
945*c2c66affSColin Finck 
946*c2c66affSColin Finck /* PRIVATE FUNCTIONS *********************************************************/
947*c2c66affSColin Finck 
948*c2c66affSColin Finck NTSTATUS
949*c2c66affSColin Finck NTAPI
950*c2c66affSColin Finck HalpGetFullGeometry(IN PDEVICE_OBJECT DeviceObject,
951*c2c66affSColin Finck                     IN PDISK_GEOMETRY Geometry,
952*c2c66affSColin Finck                     OUT PULONGLONG RealSectorCount)
953*c2c66affSColin Finck {
954*c2c66affSColin Finck     PIRP Irp;
955*c2c66affSColin Finck     IO_STATUS_BLOCK IoStatusBlock;
956*c2c66affSColin Finck     PKEVENT Event;
957*c2c66affSColin Finck     NTSTATUS Status;
958*c2c66affSColin Finck     PARTITION_INFORMATION PartitionInfo;
959*c2c66affSColin Finck     PAGED_CODE();
960*c2c66affSColin Finck 
961*c2c66affSColin Finck     /* Allocate a non-paged event */
962*c2c66affSColin Finck     Event = ExAllocatePoolWithTag(NonPagedPool,
963*c2c66affSColin Finck                                      sizeof(KEVENT),
964*c2c66affSColin Finck                                      TAG_FILE_SYSTEM);
965*c2c66affSColin Finck     if (!Event) return STATUS_INSUFFICIENT_RESOURCES;
966*c2c66affSColin Finck 
967*c2c66affSColin Finck     /* Initialize it */
968*c2c66affSColin Finck     KeInitializeEvent(Event, NotificationEvent, FALSE);
969*c2c66affSColin Finck 
970*c2c66affSColin Finck     /* Build the IRP */
971*c2c66affSColin Finck     Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY,
972*c2c66affSColin Finck                                              DeviceObject,
973*c2c66affSColin Finck                                              NULL,
974*c2c66affSColin Finck                                              0UL,
975*c2c66affSColin Finck                                              Geometry,
976*c2c66affSColin Finck                                              sizeof(DISK_GEOMETRY),
977*c2c66affSColin Finck                                              FALSE,
978*c2c66affSColin Finck                                              Event,
979*c2c66affSColin Finck                                              &IoStatusBlock);
980*c2c66affSColin Finck     if (!Irp)
981*c2c66affSColin Finck     {
982*c2c66affSColin Finck         /* Fail, free the event */
983*c2c66affSColin Finck         ExFreePoolWithTag(Event, TAG_FILE_SYSTEM);
984*c2c66affSColin Finck         return STATUS_INSUFFICIENT_RESOURCES;
985*c2c66affSColin Finck     }
986*c2c66affSColin Finck 
987*c2c66affSColin Finck     /* Call the driver and check if it's pending */
988*c2c66affSColin Finck     Status = IoCallDriver(DeviceObject, Irp);
989*c2c66affSColin Finck     if (Status == STATUS_PENDING)
990*c2c66affSColin Finck     {
991*c2c66affSColin Finck         /* Wait on the driver */
992*c2c66affSColin Finck         KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL);
993*c2c66affSColin Finck         Status = IoStatusBlock.Status;
994*c2c66affSColin Finck     }
995*c2c66affSColin Finck 
996*c2c66affSColin Finck     /* Check if the driver returned success */
997*c2c66affSColin Finck     if(NT_SUCCESS(Status))
998*c2c66affSColin Finck     {
999*c2c66affSColin Finck         /* Build another IRP */
1000*c2c66affSColin Finck         Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO,
1001*c2c66affSColin Finck                                                  DeviceObject,
1002*c2c66affSColin Finck                                                  NULL,
1003*c2c66affSColin Finck                                                  0UL,
1004*c2c66affSColin Finck                                                  &PartitionInfo,
1005*c2c66affSColin Finck                                                  sizeof(PARTITION_INFORMATION),
1006*c2c66affSColin Finck                                                  FALSE,
1007*c2c66affSColin Finck                                                  Event,
1008*c2c66affSColin Finck                                                  &IoStatusBlock);
1009*c2c66affSColin Finck         if (!Irp)
1010*c2c66affSColin Finck         {
1011*c2c66affSColin Finck             /* Fail, free the event */
1012*c2c66affSColin Finck             ExFreePoolWithTag(Event, TAG_FILE_SYSTEM);
1013*c2c66affSColin Finck             return STATUS_INSUFFICIENT_RESOURCES;
1014*c2c66affSColin Finck         }
1015*c2c66affSColin Finck 
1016*c2c66affSColin Finck         /* Reset event */
1017*c2c66affSColin Finck         KeResetEvent(Event);
1018*c2c66affSColin Finck 
1019*c2c66affSColin Finck         /* Call the driver and check if it's pending */
1020*c2c66affSColin Finck         Status = IoCallDriver(DeviceObject, Irp);
1021*c2c66affSColin Finck         if (Status == STATUS_PENDING)
1022*c2c66affSColin Finck         {
1023*c2c66affSColin Finck             /* Wait on the driver */
1024*c2c66affSColin Finck             KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL);
1025*c2c66affSColin Finck             Status = IoStatusBlock.Status;
1026*c2c66affSColin Finck         }
1027*c2c66affSColin Finck 
1028*c2c66affSColin Finck         /* Check if the driver returned success */
1029*c2c66affSColin Finck         if(NT_SUCCESS(Status))
1030*c2c66affSColin Finck         {
1031*c2c66affSColin Finck             /* Get the number of sectors */
1032*c2c66affSColin Finck             *RealSectorCount = (PartitionInfo.PartitionLength.QuadPart /
1033*c2c66affSColin Finck                                 Geometry->BytesPerSector);
1034*c2c66affSColin Finck         }
1035*c2c66affSColin Finck     }
1036*c2c66affSColin Finck 
1037*c2c66affSColin Finck     /* Free the event and return the Status */
1038*c2c66affSColin Finck     ExFreePoolWithTag(Event, TAG_FILE_SYSTEM);
1039*c2c66affSColin Finck     return Status;
1040*c2c66affSColin Finck }
1041*c2c66affSColin Finck 
1042*c2c66affSColin Finck BOOLEAN
1043*c2c66affSColin Finck NTAPI
1044*c2c66affSColin Finck HalpIsValidPartitionEntry(IN PPARTITION_DESCRIPTOR Entry,
1045*c2c66affSColin Finck                           IN ULONGLONG MaxOffset,
1046*c2c66affSColin Finck                           IN ULONGLONG MaxSector)
1047*c2c66affSColin Finck {
1048*c2c66affSColin Finck     ULONGLONG EndingSector;
1049*c2c66affSColin Finck     PAGED_CODE();
1050*c2c66affSColin Finck 
1051*c2c66affSColin Finck     /* Unused partitions are considered valid */
1052*c2c66affSColin Finck     if (Entry->PartitionType == PARTITION_ENTRY_UNUSED) return TRUE;
1053*c2c66affSColin Finck 
1054*c2c66affSColin Finck     /* Get the last sector of the partition */
1055*c2c66affSColin Finck     EndingSector = GET_STARTING_SECTOR(Entry) +  GET_PARTITION_LENGTH(Entry);
1056*c2c66affSColin Finck 
1057*c2c66affSColin Finck     /* Check if it's more then the maximum sector */
1058*c2c66affSColin Finck     if (EndingSector > MaxSector)
1059*c2c66affSColin Finck     {
1060*c2c66affSColin Finck         /* Invalid partition */
1061*c2c66affSColin Finck         DPRINT1("FSTUB: entry is invalid\n");
1062*c2c66affSColin Finck         DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry));
1063*c2c66affSColin Finck         DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry));
1064*c2c66affSColin Finck         DPRINT1("FSTUB: end %#I64x\n", EndingSector);
1065*c2c66affSColin Finck         DPRINT1("FSTUB: max %#I64x\n", MaxSector);
1066*c2c66affSColin Finck         return FALSE;
1067*c2c66affSColin Finck     }
1068*c2c66affSColin Finck     else if(GET_STARTING_SECTOR(Entry) > MaxOffset)
1069*c2c66affSColin Finck     {
1070*c2c66affSColin Finck         /* Invalid partition */
1071*c2c66affSColin Finck         DPRINT1("FSTUB: entry is invalid\n");
1072*c2c66affSColin Finck         DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry));
1073*c2c66affSColin Finck         DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry));
1074*c2c66affSColin Finck         DPRINT1("FSTUB: end %#I64x\n", EndingSector);
1075*c2c66affSColin Finck         DPRINT1("FSTUB: maxOffset %#I64x\n", MaxOffset);
1076*c2c66affSColin Finck         return FALSE;
1077*c2c66affSColin Finck     }
1078*c2c66affSColin Finck 
1079*c2c66affSColin Finck     /* It's fine, return success */
1080*c2c66affSColin Finck     return TRUE;
1081*c2c66affSColin Finck }
1082*c2c66affSColin Finck 
1083*c2c66affSColin Finck VOID
1084*c2c66affSColin Finck NTAPI
1085*c2c66affSColin Finck HalpCalculateChsValues(IN PLARGE_INTEGER PartitionOffset,
1086*c2c66affSColin Finck                        IN PLARGE_INTEGER PartitionLength,
1087*c2c66affSColin Finck                        IN CCHAR ShiftCount,
1088*c2c66affSColin Finck                        IN ULONG SectorsPerTrack,
1089*c2c66affSColin Finck                        IN ULONG NumberOfTracks,
1090*c2c66affSColin Finck                        IN ULONG ConventionalCylinders,
1091*c2c66affSColin Finck                        OUT PPARTITION_DESCRIPTOR PartitionDescriptor)
1092*c2c66affSColin Finck {
1093*c2c66affSColin Finck     LARGE_INTEGER FirstSector, SectorCount;
1094*c2c66affSColin Finck     ULONG LastSector, Remainder, SectorsPerCylinder;
1095*c2c66affSColin Finck     ULONG StartingCylinder, EndingCylinder;
1096*c2c66affSColin Finck     ULONG StartingTrack, EndingTrack;
1097*c2c66affSColin Finck     ULONG StartingSector, EndingSector;
1098*c2c66affSColin Finck     PAGED_CODE();
1099*c2c66affSColin Finck 
1100*c2c66affSColin Finck     /* Calculate the number of sectors for each cylinder */
1101*c2c66affSColin Finck     SectorsPerCylinder = SectorsPerTrack * NumberOfTracks;
1102*c2c66affSColin Finck 
1103*c2c66affSColin Finck     /* Calculate the first sector, and the sector count */
1104*c2c66affSColin Finck     FirstSector.QuadPart = PartitionOffset->QuadPart >> ShiftCount;
1105*c2c66affSColin Finck     SectorCount.QuadPart = PartitionLength->QuadPart >> ShiftCount;
1106*c2c66affSColin Finck 
1107*c2c66affSColin Finck     /* Now calculate the last sector */
1108*c2c66affSColin Finck     LastSector = FirstSector.LowPart + SectorCount.LowPart - 1;
1109*c2c66affSColin Finck 
1110*c2c66affSColin Finck     /* Calculate the first and last cylinders */
1111*c2c66affSColin Finck     StartingCylinder = FirstSector.LowPart / SectorsPerCylinder;
1112*c2c66affSColin Finck     EndingCylinder = LastSector / SectorsPerCylinder;
1113*c2c66affSColin Finck 
1114*c2c66affSColin Finck     /* Set the default number of cylinders */
1115*c2c66affSColin Finck     if (!ConventionalCylinders) ConventionalCylinders = 1024;
1116*c2c66affSColin Finck 
1117*c2c66affSColin Finck     /* Normalize the values */
1118*c2c66affSColin Finck     if (StartingCylinder >= ConventionalCylinders)
1119*c2c66affSColin Finck     {
1120*c2c66affSColin Finck         /* Set the maximum to 1023 */
1121*c2c66affSColin Finck         StartingCylinder = ConventionalCylinders - 1;
1122*c2c66affSColin Finck     }
1123*c2c66affSColin Finck     if (EndingCylinder >= ConventionalCylinders)
1124*c2c66affSColin Finck     {
1125*c2c66affSColin Finck         /* Set the maximum to 1023 */
1126*c2c66affSColin Finck         EndingCylinder = ConventionalCylinders - 1;
1127*c2c66affSColin Finck     }
1128*c2c66affSColin Finck 
1129*c2c66affSColin Finck     /* Calculate the starting head and sector that still remain */
1130*c2c66affSColin Finck     Remainder = FirstSector.LowPart % SectorsPerCylinder;
1131*c2c66affSColin Finck     StartingTrack = Remainder / SectorsPerTrack;
1132*c2c66affSColin Finck     StartingSector = Remainder % SectorsPerTrack;
1133*c2c66affSColin Finck 
1134*c2c66affSColin Finck     /* Calculate the ending head and sector that still remain */
1135*c2c66affSColin Finck     Remainder = LastSector % SectorsPerCylinder;
1136*c2c66affSColin Finck     EndingTrack = Remainder / SectorsPerTrack;
1137*c2c66affSColin Finck     EndingSector = Remainder % SectorsPerTrack;
1138*c2c66affSColin Finck 
1139*c2c66affSColin Finck     /* Set cylinder data for the MSB */
1140*c2c66affSColin Finck     PartitionDescriptor->StartingCylinderMsb = (UCHAR)StartingCylinder;
1141*c2c66affSColin Finck     PartitionDescriptor->EndingCylinderMsb = (UCHAR)EndingCylinder;
1142*c2c66affSColin Finck 
1143*c2c66affSColin Finck     /* Set the track data */
1144*c2c66affSColin Finck     PartitionDescriptor->StartingTrack = (UCHAR)StartingTrack;
1145*c2c66affSColin Finck     PartitionDescriptor->EndingTrack = (UCHAR)EndingTrack;
1146*c2c66affSColin Finck 
1147*c2c66affSColin Finck     /* Update cylinder data for the LSB */
1148*c2c66affSColin Finck     StartingCylinder = ((StartingSector + 1) & 0x3F) |
1149*c2c66affSColin Finck                        ((StartingCylinder >> 2) & 0xC0);
1150*c2c66affSColin Finck     EndingCylinder = ((EndingSector + 1) & 0x3F) |
1151*c2c66affSColin Finck                      ((EndingCylinder >> 2) & 0xC0);
1152*c2c66affSColin Finck 
1153*c2c66affSColin Finck     /* Set the cylinder data for the LSB */
1154*c2c66affSColin Finck     PartitionDescriptor->StartingCylinderLsb = (UCHAR)StartingCylinder;
1155*c2c66affSColin Finck     PartitionDescriptor->EndingCylinderLsb = (UCHAR)EndingCylinder;
1156*c2c66affSColin Finck }
1157*c2c66affSColin Finck 
1158*c2c66affSColin Finck VOID
1159*c2c66affSColin Finck FASTCALL
1160*c2c66affSColin Finck xHalGetPartialGeometry(IN PDEVICE_OBJECT DeviceObject,
1161*c2c66affSColin Finck                        IN PULONG ConventionalCylinders,
1162*c2c66affSColin Finck                        IN PLONGLONG DiskSize)
1163*c2c66affSColin Finck {
1164*c2c66affSColin Finck     PDISK_GEOMETRY DiskGeometry = NULL;
1165*c2c66affSColin Finck     PIO_STATUS_BLOCK IoStatusBlock = NULL;
1166*c2c66affSColin Finck     PKEVENT Event = NULL;
1167*c2c66affSColin Finck     PIRP Irp;
1168*c2c66affSColin Finck     NTSTATUS Status;
1169*c2c66affSColin Finck 
1170*c2c66affSColin Finck     /* Set defaults */
1171*c2c66affSColin Finck     *ConventionalCylinders = 0;
1172*c2c66affSColin Finck     *DiskSize = 0;
1173*c2c66affSColin Finck 
1174*c2c66affSColin Finck     /* Allocate the structure in nonpaged pool */
1175*c2c66affSColin Finck     DiskGeometry = ExAllocatePoolWithTag(NonPagedPool,
1176*c2c66affSColin Finck                                          sizeof(DISK_GEOMETRY),
1177*c2c66affSColin Finck                                          TAG_FILE_SYSTEM);
1178*c2c66affSColin Finck     if (!DiskGeometry) goto Cleanup;
1179*c2c66affSColin Finck 
1180*c2c66affSColin Finck     /* Allocate the status block in nonpaged pool */
1181*c2c66affSColin Finck     IoStatusBlock = ExAllocatePoolWithTag(NonPagedPool,
1182*c2c66affSColin Finck                                           sizeof(IO_STATUS_BLOCK),
1183*c2c66affSColin Finck                                           TAG_FILE_SYSTEM);
1184*c2c66affSColin Finck     if (!IoStatusBlock) goto Cleanup;
1185*c2c66affSColin Finck 
1186*c2c66affSColin Finck     /* Allocate the event in nonpaged pool too */
1187*c2c66affSColin Finck     Event = ExAllocatePoolWithTag(NonPagedPool,
1188*c2c66affSColin Finck                                   sizeof(KEVENT),
1189*c2c66affSColin Finck                                   TAG_FILE_SYSTEM);
1190*c2c66affSColin Finck     if (!Event) goto Cleanup;
1191*c2c66affSColin Finck 
1192*c2c66affSColin Finck     /* Initialize the event */
1193*c2c66affSColin Finck     KeInitializeEvent(Event, NotificationEvent, FALSE);
1194*c2c66affSColin Finck 
1195*c2c66affSColin Finck     /* Build the IRP */
1196*c2c66affSColin Finck     Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY,
1197*c2c66affSColin Finck                                         DeviceObject,
1198*c2c66affSColin Finck                                         NULL,
1199*c2c66affSColin Finck                                         0,
1200*c2c66affSColin Finck                                         DiskGeometry,
1201*c2c66affSColin Finck                                         sizeof(DISK_GEOMETRY),
1202*c2c66affSColin Finck                                         FALSE,
1203*c2c66affSColin Finck                                         Event,
1204*c2c66affSColin Finck                                         IoStatusBlock);
1205*c2c66affSColin Finck     if (!Irp) goto Cleanup;
1206*c2c66affSColin Finck 
1207*c2c66affSColin Finck     /* Now call the driver */
1208*c2c66affSColin Finck     Status = IoCallDriver(DeviceObject, Irp);
1209*c2c66affSColin Finck     if (Status == STATUS_PENDING)
1210*c2c66affSColin Finck     {
1211*c2c66affSColin Finck         /* Wait for it to complete */
1212*c2c66affSColin Finck         KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL);
1213*c2c66affSColin Finck         Status = IoStatusBlock->Status;
1214*c2c66affSColin Finck     }
1215*c2c66affSColin Finck 
1216*c2c66affSColin Finck     /* Check driver status */
1217*c2c66affSColin Finck     if (NT_SUCCESS(Status))
1218*c2c66affSColin Finck     {
1219*c2c66affSColin Finck         /* Return the cylinder count */
1220*c2c66affSColin Finck         *ConventionalCylinders = DiskGeometry->Cylinders.LowPart;
1221*c2c66affSColin Finck 
1222*c2c66affSColin Finck         /* Make sure it's not larger then 1024 */
1223*c2c66affSColin Finck         if (DiskGeometry->Cylinders.LowPart >= 1024)
1224*c2c66affSColin Finck         {
1225*c2c66affSColin Finck             /* Otherwise, normalize the value */
1226*c2c66affSColin Finck             *ConventionalCylinders = 1024;
1227*c2c66affSColin Finck         }
1228*c2c66affSColin Finck 
1229*c2c66affSColin Finck         /* Calculate the disk size */
1230*c2c66affSColin Finck         *DiskSize = DiskGeometry->Cylinders.QuadPart *
1231*c2c66affSColin Finck                     DiskGeometry->TracksPerCylinder *
1232*c2c66affSColin Finck                     DiskGeometry->SectorsPerTrack *
1233*c2c66affSColin Finck                     DiskGeometry->BytesPerSector;
1234*c2c66affSColin Finck     }
1235*c2c66affSColin Finck 
1236*c2c66affSColin Finck Cleanup:
1237*c2c66affSColin Finck     /* Free all the pointers */
1238*c2c66affSColin Finck     if (Event) ExFreePoolWithTag(Event, TAG_FILE_SYSTEM);
1239*c2c66affSColin Finck     if (IoStatusBlock) ExFreePoolWithTag(IoStatusBlock, TAG_FILE_SYSTEM);
1240*c2c66affSColin Finck     if (DiskGeometry) ExFreePoolWithTag(DiskGeometry, TAG_FILE_SYSTEM);
1241*c2c66affSColin Finck     return;
1242*c2c66affSColin Finck }
1243*c2c66affSColin Finck 
1244*c2c66affSColin Finck VOID
1245*c2c66affSColin Finck FASTCALL
1246*c2c66affSColin Finck xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject,
1247*c2c66affSColin Finck                IN ULONG SectorSize,
1248*c2c66affSColin Finck                IN ULONG MbrTypeIdentifier,
1249*c2c66affSColin Finck                OUT PVOID *MbrBuffer)
1250*c2c66affSColin Finck {
1251*c2c66affSColin Finck     LARGE_INTEGER Offset;
1252*c2c66affSColin Finck     PUCHAR Buffer;
1253*c2c66affSColin Finck     ULONG BufferSize;
1254*c2c66affSColin Finck     KEVENT Event;
1255*c2c66affSColin Finck     IO_STATUS_BLOCK IoStatusBlock;
1256*c2c66affSColin Finck     PIRP Irp;
1257*c2c66affSColin Finck     PPARTITION_DESCRIPTOR PartitionDescriptor;
1258*c2c66affSColin Finck     NTSTATUS Status;
1259*c2c66affSColin Finck     PIO_STACK_LOCATION IoStackLocation;
1260*c2c66affSColin Finck     Offset.QuadPart = 0;
1261*c2c66affSColin Finck 
1262*c2c66affSColin Finck     /* Assume failure */
1263*c2c66affSColin Finck     *MbrBuffer = NULL;
1264*c2c66affSColin Finck 
1265*c2c66affSColin Finck     /* Normalize the buffer size */
1266*c2c66affSColin Finck     BufferSize = max(SectorSize, 512);
1267*c2c66affSColin Finck 
1268*c2c66affSColin Finck     /* Allocate the buffer */
1269*c2c66affSColin Finck     Buffer = ExAllocatePoolWithTag(NonPagedPool,
1270*c2c66affSColin Finck                                        PAGE_SIZE > BufferSize ?
1271*c2c66affSColin Finck                                        PAGE_SIZE : BufferSize,
1272*c2c66affSColin Finck                                        TAG_FILE_SYSTEM);
1273*c2c66affSColin Finck     if (!Buffer) return;
1274*c2c66affSColin Finck 
1275*c2c66affSColin Finck     /* Initialize the Event */
1276*c2c66affSColin Finck     KeInitializeEvent(&Event, NotificationEvent, FALSE);
1277*c2c66affSColin Finck 
1278*c2c66affSColin Finck     /* Build the IRP */
1279*c2c66affSColin Finck     Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
1280*c2c66affSColin Finck                                        DeviceObject,
1281*c2c66affSColin Finck                                        Buffer,
1282*c2c66affSColin Finck                                        BufferSize,
1283*c2c66affSColin Finck                                        &Offset,
1284*c2c66affSColin Finck                                        &Event,
1285*c2c66affSColin Finck                                        &IoStatusBlock);
1286*c2c66affSColin Finck     if (!Irp)
1287*c2c66affSColin Finck     {
1288*c2c66affSColin Finck         /* Failed */
1289*c2c66affSColin Finck         ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM);
1290*c2c66affSColin Finck         return;
1291*c2c66affSColin Finck     }
1292*c2c66affSColin Finck 
1293*c2c66affSColin Finck     /* Make sure to override volume verification */
1294*c2c66affSColin Finck     IoStackLocation = IoGetNextIrpStackLocation(Irp);
1295*c2c66affSColin Finck     IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
1296*c2c66affSColin Finck 
1297*c2c66affSColin Finck     /* Call the driver */
1298*c2c66affSColin Finck     Status = IoCallDriver(DeviceObject, Irp);
1299*c2c66affSColin Finck     if (Status == STATUS_PENDING)
1300*c2c66affSColin Finck     {
1301*c2c66affSColin Finck         /* Wait for completion */
1302*c2c66affSColin Finck         KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1303*c2c66affSColin Finck         Status = IoStatusBlock.Status;
1304*c2c66affSColin Finck     }
1305*c2c66affSColin Finck 
1306*c2c66affSColin Finck     /* Check driver Status */
1307*c2c66affSColin Finck     if (NT_SUCCESS(Status))
1308*c2c66affSColin Finck     {
1309*c2c66affSColin Finck         /* Validate the MBR Signature */
1310*c2c66affSColin Finck         if (((PUSHORT)Buffer)[BOOT_SIGNATURE_OFFSET] != BOOT_RECORD_SIGNATURE)
1311*c2c66affSColin Finck         {
1312*c2c66affSColin Finck             /* Failed */
1313*c2c66affSColin Finck             ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM);
1314*c2c66affSColin Finck             return;
1315*c2c66affSColin Finck         }
1316*c2c66affSColin Finck 
1317*c2c66affSColin Finck         /* Get the partition entry */
1318*c2c66affSColin Finck         PartitionDescriptor = (PPARTITION_DESCRIPTOR)
1319*c2c66affSColin Finck                                &(((PUSHORT)Buffer)[PARTITION_TABLE_OFFSET]);
1320*c2c66affSColin Finck 
1321*c2c66affSColin Finck         /* Make sure it's what the caller wanted */
1322*c2c66affSColin Finck         if (PartitionDescriptor->PartitionType != MbrTypeIdentifier)
1323*c2c66affSColin Finck         {
1324*c2c66affSColin Finck             /* It's not, free our buffer */
1325*c2c66affSColin Finck             ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM);
1326*c2c66affSColin Finck         }
1327*c2c66affSColin Finck         else
1328*c2c66affSColin Finck         {
1329*c2c66affSColin Finck             /* Check if this is a secondary entry */
1330*c2c66affSColin Finck             if (PartitionDescriptor->PartitionType == 0x54)
1331*c2c66affSColin Finck             {
1332*c2c66affSColin Finck                 /* Return our buffer, but at sector 63 */
1333*c2c66affSColin Finck                 *(PULONG)Buffer = 63;
1334*c2c66affSColin Finck                 *MbrBuffer = Buffer;
1335*c2c66affSColin Finck             }
1336*c2c66affSColin Finck             else if (PartitionDescriptor->PartitionType == 0x55)
1337*c2c66affSColin Finck             {
1338*c2c66affSColin Finck                 /* EZ Drive, return the buffer directly */
1339*c2c66affSColin Finck                 *MbrBuffer = Buffer;
1340*c2c66affSColin Finck             }
1341*c2c66affSColin Finck             else
1342*c2c66affSColin Finck             {
1343*c2c66affSColin Finck                 /* Otherwise crash on debug builds */
1344*c2c66affSColin Finck                 ASSERT(PartitionDescriptor->PartitionType == 0x55);
1345*c2c66affSColin Finck             }
1346*c2c66affSColin Finck         }
1347*c2c66affSColin Finck     }
1348*c2c66affSColin Finck }
1349*c2c66affSColin Finck 
1350*c2c66affSColin Finck VOID
1351*c2c66affSColin Finck NTAPI
1352*c2c66affSColin Finck FstubFixupEfiPartition(IN PPARTITION_DESCRIPTOR PartitionDescriptor,
1353*c2c66affSColin Finck                        IN ULONGLONG MaxOffset)
1354*c2c66affSColin Finck {
1355*c2c66affSColin Finck     ULONG PartitionMaxOffset, PartitionLength;
1356*c2c66affSColin Finck     PAGED_CODE();
1357*c2c66affSColin Finck 
1358*c2c66affSColin Finck     /* Compute partition length (according to MBR entry) */
1359*c2c66affSColin Finck     PartitionMaxOffset = GET_STARTING_SECTOR(PartitionDescriptor) + GET_PARTITION_LENGTH(PartitionDescriptor);
1360*c2c66affSColin Finck     /* In case the partition length goes beyond disk size... */
1361*c2c66affSColin Finck     if (PartitionMaxOffset > MaxOffset)
1362*c2c66affSColin Finck     {
1363*c2c66affSColin Finck         /* Resize partition to its maximum real length */
1364*c2c66affSColin Finck         PartitionLength = (ULONG)(PartitionMaxOffset - GET_STARTING_SECTOR(PartitionDescriptor));
1365*c2c66affSColin Finck         SET_PARTITION_LENGTH(PartitionDescriptor, PartitionLength);
1366*c2c66affSColin Finck     }
1367*c2c66affSColin Finck }
1368*c2c66affSColin Finck 
1369*c2c66affSColin Finck NTSTATUS
1370*c2c66affSColin Finck FASTCALL
1371*c2c66affSColin Finck xHalIoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject,
1372*c2c66affSColin Finck                          IN ULONG SectorSize,
1373*c2c66affSColin Finck                          IN BOOLEAN ReturnRecognizedPartitions,
1374*c2c66affSColin Finck                          IN OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
1375*c2c66affSColin Finck {
1376*c2c66affSColin Finck     KEVENT Event;
1377*c2c66affSColin Finck     IO_STATUS_BLOCK IoStatusBlock;
1378*c2c66affSColin Finck     PIRP Irp;
1379*c2c66affSColin Finck     PPARTITION_DESCRIPTOR PartitionDescriptor;
1380*c2c66affSColin Finck     CCHAR Entry;
1381*c2c66affSColin Finck     NTSTATUS Status;
1382*c2c66affSColin Finck     PPARTITION_INFORMATION PartitionInfo;
1383*c2c66affSColin Finck     PUCHAR Buffer = NULL;
1384*c2c66affSColin Finck     ULONG BufferSize = 2048, InputSize;
1385*c2c66affSColin Finck     PDRIVE_LAYOUT_INFORMATION DriveLayoutInfo = NULL;
1386*c2c66affSColin Finck     LONG j = -1, i = -1, k;
1387*c2c66affSColin Finck     DISK_GEOMETRY DiskGeometry;
1388*c2c66affSColin Finck     LONGLONG EndSector, MaxSector, StartOffset;
1389*c2c66affSColin Finck     ULONGLONG MaxOffset;
1390*c2c66affSColin Finck     LARGE_INTEGER Offset, VolumeOffset;
1391*c2c66affSColin Finck     BOOLEAN IsPrimary = TRUE, IsEzDrive = FALSE, MbrFound = FALSE;
1392*c2c66affSColin Finck     BOOLEAN IsValid, IsEmpty = TRUE;
1393*c2c66affSColin Finck     PVOID MbrBuffer;
1394*c2c66affSColin Finck     PIO_STACK_LOCATION IoStackLocation;
1395*c2c66affSColin Finck     PBOOT_SECTOR_INFO BootSectorInfo = (PBOOT_SECTOR_INFO)Buffer;
1396*c2c66affSColin Finck     UCHAR PartitionType;
1397*c2c66affSColin Finck     LARGE_INTEGER HiddenSectors64;
1398*c2c66affSColin Finck     VolumeOffset.QuadPart = Offset.QuadPart = 0;
1399*c2c66affSColin Finck     PAGED_CODE();
1400*c2c66affSColin Finck 
1401*c2c66affSColin Finck     /* Allocate the buffer */
1402*c2c66affSColin Finck     *PartitionBuffer = ExAllocatePoolWithTag(NonPagedPool,
1403*c2c66affSColin Finck                                              BufferSize,
1404*c2c66affSColin Finck                                              TAG_FILE_SYSTEM);
1405*c2c66affSColin Finck     if (!(*PartitionBuffer)) return STATUS_INSUFFICIENT_RESOURCES;
1406*c2c66affSColin Finck 
1407*c2c66affSColin Finck     /* Normalize the buffer size */
1408*c2c66affSColin Finck     InputSize = max(512, SectorSize);
1409*c2c66affSColin Finck 
1410*c2c66affSColin Finck     /* Check for EZ Drive */
1411*c2c66affSColin Finck     HalExamineMBR(DeviceObject, InputSize, 0x55, &MbrBuffer);
1412*c2c66affSColin Finck     if (MbrBuffer)
1413*c2c66affSColin Finck     {
1414*c2c66affSColin Finck         /* EZ Drive found, bias the offset */
1415*c2c66affSColin Finck         IsEzDrive = TRUE;
1416*c2c66affSColin Finck         ExFreePoolWithTag(MbrBuffer, TAG_FILE_SYSTEM);
1417*c2c66affSColin Finck         Offset.QuadPart = 512;
1418*c2c66affSColin Finck     }
1419*c2c66affSColin Finck 
1420*c2c66affSColin Finck     /* Get drive geometry */
1421*c2c66affSColin Finck     Status = HalpGetFullGeometry(DeviceObject, &DiskGeometry, &MaxOffset);
1422*c2c66affSColin Finck     if (!NT_SUCCESS(Status))
1423*c2c66affSColin Finck     {
1424*c2c66affSColin Finck         ExFreePoolWithTag(*PartitionBuffer, TAG_FILE_SYSTEM);
1425*c2c66affSColin Finck         *PartitionBuffer = NULL;
1426*c2c66affSColin Finck         return Status;
1427*c2c66affSColin Finck     }
1428*c2c66affSColin Finck 
1429*c2c66affSColin Finck     /* Get the end and maximum sector */
1430*c2c66affSColin Finck     EndSector = MaxOffset;
1431*c2c66affSColin Finck     MaxSector = MaxOffset << 1;
1432*c2c66affSColin Finck     DPRINT("FSTUB: MaxOffset = %#I64x, MaxSector = %#I64x\n",
1433*c2c66affSColin Finck             MaxOffset, MaxSector);
1434*c2c66affSColin Finck 
1435*c2c66affSColin Finck     /* Allocate our buffer */
1436*c2c66affSColin Finck     Buffer = ExAllocatePoolWithTag(NonPagedPool, InputSize, TAG_FILE_SYSTEM);
1437*c2c66affSColin Finck     if (!Buffer)
1438*c2c66affSColin Finck     {
1439*c2c66affSColin Finck         /* Fail, free the input buffer */
1440*c2c66affSColin Finck         ExFreePoolWithTag(*PartitionBuffer, TAG_FILE_SYSTEM);
1441*c2c66affSColin Finck         *PartitionBuffer = NULL;
1442*c2c66affSColin Finck         return STATUS_INSUFFICIENT_RESOURCES;
1443*c2c66affSColin Finck     }
1444*c2c66affSColin Finck 
1445*c2c66affSColin Finck     /* Start partition loop */
1446*c2c66affSColin Finck     do
1447*c2c66affSColin Finck     {
1448*c2c66affSColin Finck         /* Assume the partition is valid */
1449*c2c66affSColin Finck         IsValid = TRUE;
1450*c2c66affSColin Finck 
1451*c2c66affSColin Finck         /* Initialize the event */
1452*c2c66affSColin Finck         KeInitializeEvent(&Event, NotificationEvent, FALSE);
1453*c2c66affSColin Finck 
1454*c2c66affSColin Finck         /* Clear the buffer and build the IRP */
1455*c2c66affSColin Finck         RtlZeroMemory(Buffer, InputSize);
1456*c2c66affSColin Finck         Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
1457*c2c66affSColin Finck                                            DeviceObject,
1458*c2c66affSColin Finck                                            Buffer,
1459*c2c66affSColin Finck                                            InputSize,
1460*c2c66affSColin Finck                                            &Offset,
1461*c2c66affSColin Finck                                            &Event,
1462*c2c66affSColin Finck                                            &IoStatusBlock);
1463*c2c66affSColin Finck         if (!Irp)
1464*c2c66affSColin Finck         {
1465*c2c66affSColin Finck             /* Failed */
1466*c2c66affSColin Finck             Status = STATUS_INSUFFICIENT_RESOURCES;
1467*c2c66affSColin Finck             break;
1468*c2c66affSColin Finck         }
1469*c2c66affSColin Finck 
1470*c2c66affSColin Finck         /* Make sure to disable volume verification */
1471*c2c66affSColin Finck         IoStackLocation = IoGetNextIrpStackLocation(Irp);
1472*c2c66affSColin Finck         IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
1473*c2c66affSColin Finck 
1474*c2c66affSColin Finck         /* Call the driver */
1475*c2c66affSColin Finck         Status = IoCallDriver(DeviceObject, Irp);
1476*c2c66affSColin Finck         if (Status == STATUS_PENDING)
1477*c2c66affSColin Finck         {
1478*c2c66affSColin Finck             /* Wait for completion */
1479*c2c66affSColin Finck             KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1480*c2c66affSColin Finck             Status = IoStatusBlock.Status;
1481*c2c66affSColin Finck         }
1482*c2c66affSColin Finck 
1483*c2c66affSColin Finck         /* Normalize status code and check for failure */
1484*c2c66affSColin Finck         if (Status == STATUS_NO_DATA_DETECTED) Status = STATUS_SUCCESS;
1485*c2c66affSColin Finck         if (!NT_SUCCESS(Status)) break;
1486*c2c66affSColin Finck 
1487*c2c66affSColin Finck         /* If we biased for EZ-Drive, unbias now */
1488*c2c66affSColin Finck         if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
1489*c2c66affSColin Finck 
1490*c2c66affSColin Finck         /* Make sure this is a valid MBR */
1491*c2c66affSColin Finck         if (((PUSHORT)Buffer)[BOOT_SIGNATURE_OFFSET] != BOOT_RECORD_SIGNATURE)
1492*c2c66affSColin Finck         {
1493*c2c66affSColin Finck             /* It's not, fail */
1494*c2c66affSColin Finck             DPRINT1("FSTUB: (IoReadPartitionTable) No 0xaa55 found in "
1495*c2c66affSColin Finck                     "partition table %d\n", j + 1);
1496*c2c66affSColin Finck             break;
1497*c2c66affSColin Finck         }
1498*c2c66affSColin Finck 
1499*c2c66affSColin Finck         /* At this point we have a valid MBR */
1500*c2c66affSColin Finck         MbrFound = TRUE;
1501*c2c66affSColin Finck 
1502*c2c66affSColin Finck         /* Check if we weren't given an offset */
1503*c2c66affSColin Finck         if (!Offset.QuadPart)
1504*c2c66affSColin Finck         {
1505*c2c66affSColin Finck             /* Then read the signature off the disk */
1506*c2c66affSColin Finck             (*PartitionBuffer)->Signature =  ((PULONG)Buffer)
1507*c2c66affSColin Finck                                              [PARTITION_TABLE_OFFSET / 2 - 1];
1508*c2c66affSColin Finck         }
1509*c2c66affSColin Finck 
1510*c2c66affSColin Finck         /* Get the partition descriptor array */
1511*c2c66affSColin Finck         PartitionDescriptor = (PPARTITION_DESCRIPTOR)
1512*c2c66affSColin Finck                                &(((PUSHORT)Buffer)[PARTITION_TABLE_OFFSET]);
1513*c2c66affSColin Finck 
1514*c2c66affSColin Finck         /* Start looping partitions */
1515*c2c66affSColin Finck         j++;
1516*c2c66affSColin Finck         DPRINT("FSTUB: Partition Table %d:\n", j);
1517*c2c66affSColin Finck         for (Entry = 1, k = 0; Entry <= 4; Entry++, PartitionDescriptor++)
1518*c2c66affSColin Finck         {
1519*c2c66affSColin Finck             /* Get the partition type */
1520*c2c66affSColin Finck             PartitionType = PartitionDescriptor->PartitionType;
1521*c2c66affSColin Finck 
1522*c2c66affSColin Finck             /* Print debug messages */
1523*c2c66affSColin Finck             DPRINT("Partition Entry %d,%d: type %#x %s\n",
1524*c2c66affSColin Finck                     j,
1525*c2c66affSColin Finck                     Entry,
1526*c2c66affSColin Finck                     PartitionType,
1527*c2c66affSColin Finck                     (PartitionDescriptor->ActiveFlag) ? "Active" : "");
1528*c2c66affSColin Finck             DPRINT("\tOffset %#08lx for %#08lx Sectors\n",
1529*c2c66affSColin Finck                     GET_STARTING_SECTOR(PartitionDescriptor),
1530*c2c66affSColin Finck                     GET_PARTITION_LENGTH(PartitionDescriptor));
1531*c2c66affSColin Finck 
1532*c2c66affSColin Finck             /* Check whether we're facing a protective MBR */
1533*c2c66affSColin Finck             if (PartitionType == EFI_PMBR_OSTYPE_EFI)
1534*c2c66affSColin Finck             {
1535*c2c66affSColin Finck                 /* Partition length might be bigger than disk size */
1536*c2c66affSColin Finck                 FstubFixupEfiPartition(PartitionDescriptor,
1537*c2c66affSColin Finck                                        MaxOffset);
1538*c2c66affSColin Finck             }
1539*c2c66affSColin Finck 
1540*c2c66affSColin Finck             /* Make sure that the partition is valid, unless it's the first */
1541*c2c66affSColin Finck             if (!(HalpIsValidPartitionEntry(PartitionDescriptor,
1542*c2c66affSColin Finck                                             MaxOffset,
1543*c2c66affSColin Finck                                             MaxSector)) && !(j))
1544*c2c66affSColin Finck             {
1545*c2c66affSColin Finck                 /* It's invalid, so fail */
1546*c2c66affSColin Finck                 IsValid = FALSE;
1547*c2c66affSColin Finck                 break;
1548*c2c66affSColin Finck             }
1549*c2c66affSColin Finck 
1550*c2c66affSColin Finck             /* Check if it's a container */
1551*c2c66affSColin Finck             if (IsContainerPartition(PartitionType))
1552*c2c66affSColin Finck             {
1553*c2c66affSColin Finck                 /* Increase the count of containers */
1554*c2c66affSColin Finck                 if (++k != 1)
1555*c2c66affSColin Finck                 {
1556*c2c66affSColin Finck                     /* More then one table is invalid */
1557*c2c66affSColin Finck                     DPRINT1("FSTUB: Multiple container partitions found in "
1558*c2c66affSColin Finck                             "partition table %d\n - table is invalid\n",
1559*c2c66affSColin Finck                             j);
1560*c2c66affSColin Finck                     IsValid = FALSE;
1561*c2c66affSColin Finck                     break;
1562*c2c66affSColin Finck                 }
1563*c2c66affSColin Finck             }
1564*c2c66affSColin Finck 
1565*c2c66affSColin Finck             /* Check if the partition is supposedly empty */
1566*c2c66affSColin Finck             if (IsEmpty)
1567*c2c66affSColin Finck             {
1568*c2c66affSColin Finck                 /* But check if it actually has a start and/or length */
1569*c2c66affSColin Finck                 if ((GET_STARTING_SECTOR(PartitionDescriptor)) ||
1570*c2c66affSColin Finck                     (GET_PARTITION_LENGTH(PartitionDescriptor)))
1571*c2c66affSColin Finck                 {
1572*c2c66affSColin Finck                     /* So then it's not really empty */
1573*c2c66affSColin Finck                     IsEmpty = FALSE;
1574*c2c66affSColin Finck                 }
1575*c2c66affSColin Finck             }
1576*c2c66affSColin Finck 
1577*c2c66affSColin Finck             /* Check if the caller wanted only recognized partitions */
1578*c2c66affSColin Finck             if (ReturnRecognizedPartitions)
1579*c2c66affSColin Finck             {
1580*c2c66affSColin Finck                 /* Then check if this one is unused, or a container */
1581*c2c66affSColin Finck                 if ((PartitionType == PARTITION_ENTRY_UNUSED) ||
1582*c2c66affSColin Finck                     IsContainerPartition(PartitionType))
1583*c2c66affSColin Finck                 {
1584*c2c66affSColin Finck                     /* Skip it, since the caller doesn't want it */
1585*c2c66affSColin Finck                     continue;
1586*c2c66affSColin Finck                 }
1587*c2c66affSColin Finck             }
1588*c2c66affSColin Finck 
1589*c2c66affSColin Finck             /* Increase the structure count and check if they can fit */
1590*c2c66affSColin Finck             if ((sizeof(DRIVE_LAYOUT_INFORMATION) +
1591*c2c66affSColin Finck                  (++i * sizeof(PARTITION_INFORMATION))) >
1592*c2c66affSColin Finck                 BufferSize)
1593*c2c66affSColin Finck             {
1594*c2c66affSColin Finck                 /* Allocate a new buffer that's twice as big */
1595*c2c66affSColin Finck                 DriveLayoutInfo = ExAllocatePoolWithTag(NonPagedPool,
1596*c2c66affSColin Finck                                                         BufferSize << 1,
1597*c2c66affSColin Finck                                                         TAG_FILE_SYSTEM);
1598*c2c66affSColin Finck                 if (!DriveLayoutInfo)
1599*c2c66affSColin Finck                 {
1600*c2c66affSColin Finck                     /* Out of memory, unto this extra structure */
1601*c2c66affSColin Finck                     --i;
1602*c2c66affSColin Finck                     Status = STATUS_INSUFFICIENT_RESOURCES;
1603*c2c66affSColin Finck                     break;
1604*c2c66affSColin Finck                 }
1605*c2c66affSColin Finck 
1606*c2c66affSColin Finck                 /* Copy the contents of the old buffer */
1607*c2c66affSColin Finck                 RtlMoveMemory(DriveLayoutInfo,
1608*c2c66affSColin Finck                               *PartitionBuffer,
1609*c2c66affSColin Finck                               BufferSize);
1610*c2c66affSColin Finck 
1611*c2c66affSColin Finck                 /* Free the old buffer and set this one as the new one */
1612*c2c66affSColin Finck                 ExFreePoolWithTag(*PartitionBuffer, TAG_FILE_SYSTEM);
1613*c2c66affSColin Finck                 *PartitionBuffer = DriveLayoutInfo;
1614*c2c66affSColin Finck 
1615*c2c66affSColin Finck                 /* Double the size */
1616*c2c66affSColin Finck                 BufferSize <<= 1;
1617*c2c66affSColin Finck             }
1618*c2c66affSColin Finck 
1619*c2c66affSColin Finck             /* Now get the current structure being filled and initialize it */
1620*c2c66affSColin Finck             PartitionInfo = &(*PartitionBuffer)->PartitionEntry[i];
1621*c2c66affSColin Finck             PartitionInfo->PartitionType = PartitionType;
1622*c2c66affSColin Finck             PartitionInfo->RewritePartition = FALSE;
1623*c2c66affSColin Finck 
1624*c2c66affSColin Finck             /* Check if we're dealing with a partition that's in use */
1625*c2c66affSColin Finck             if (PartitionType != PARTITION_ENTRY_UNUSED)
1626*c2c66affSColin Finck             {
1627*c2c66affSColin Finck                 /* Check if it's bootable */
1628*c2c66affSColin Finck                 PartitionInfo->BootIndicator = PartitionDescriptor->
1629*c2c66affSColin Finck                                                ActiveFlag & 0x80 ?
1630*c2c66affSColin Finck                                                TRUE : FALSE;
1631*c2c66affSColin Finck 
1632*c2c66affSColin Finck                 /* Check if its' a container */
1633*c2c66affSColin Finck                 if (IsContainerPartition(PartitionType))
1634*c2c66affSColin Finck                 {
1635*c2c66affSColin Finck                     /* Then don't recognize it and use the volume offset */
1636*c2c66affSColin Finck                     PartitionInfo->RecognizedPartition = FALSE;
1637*c2c66affSColin Finck                     StartOffset = VolumeOffset.QuadPart;
1638*c2c66affSColin Finck                 }
1639*c2c66affSColin Finck                 else
1640*c2c66affSColin Finck                 {
1641*c2c66affSColin Finck                     /* Then recognize it and use the partition offset */
1642*c2c66affSColin Finck                     PartitionInfo->RecognizedPartition = TRUE;
1643*c2c66affSColin Finck                     StartOffset = Offset.QuadPart;
1644*c2c66affSColin Finck                 }
1645*c2c66affSColin Finck 
1646*c2c66affSColin Finck                 /* Get the starting offset */
1647*c2c66affSColin Finck                 PartitionInfo->StartingOffset.QuadPart =
1648*c2c66affSColin Finck                     StartOffset +
1649*c2c66affSColin Finck                     UInt32x32To64(GET_STARTING_SECTOR(PartitionDescriptor),
1650*c2c66affSColin Finck                                   SectorSize);
1651*c2c66affSColin Finck 
1652*c2c66affSColin Finck                 /* Calculate the number of hidden sectors */
1653*c2c66affSColin Finck                 HiddenSectors64.QuadPart = (PartitionInfo->
1654*c2c66affSColin Finck                                             StartingOffset.QuadPart -
1655*c2c66affSColin Finck                                             StartOffset) /
1656*c2c66affSColin Finck                                             SectorSize;
1657*c2c66affSColin Finck                 PartitionInfo->HiddenSectors = HiddenSectors64.LowPart;
1658*c2c66affSColin Finck 
1659*c2c66affSColin Finck                 /* Get the partition length */
1660*c2c66affSColin Finck                 PartitionInfo->PartitionLength.QuadPart =
1661*c2c66affSColin Finck                     UInt32x32To64(GET_PARTITION_LENGTH(PartitionDescriptor),
1662*c2c66affSColin Finck                                   SectorSize);
1663*c2c66affSColin Finck 
1664*c2c66affSColin Finck                 /* Get the partition number */
1665*c2c66affSColin Finck                 PartitionInfo->PartitionNumber = (!IsContainerPartition(PartitionType)) ? i + 1 : 0;
1666*c2c66affSColin Finck             }
1667*c2c66affSColin Finck             else
1668*c2c66affSColin Finck             {
1669*c2c66affSColin Finck                 /* Otherwise, clear all the relevant fields */
1670*c2c66affSColin Finck                 PartitionInfo->BootIndicator = FALSE;
1671*c2c66affSColin Finck                 PartitionInfo->RecognizedPartition = FALSE;
1672*c2c66affSColin Finck                 PartitionInfo->StartingOffset.QuadPart = 0;
1673*c2c66affSColin Finck                 PartitionInfo->PartitionLength.QuadPart = 0;
1674*c2c66affSColin Finck                 PartitionInfo->HiddenSectors = 0;
1675*c2c66affSColin Finck 
1676*c2c66affSColin Finck                 PartitionInfo->PartitionNumber = 0;
1677*c2c66affSColin Finck             }
1678*c2c66affSColin Finck         }
1679*c2c66affSColin Finck 
1680*c2c66affSColin Finck         /* Finish debug log, and check for failure */
1681*c2c66affSColin Finck         DPRINT("\n");
1682*c2c66affSColin Finck         if (!NT_SUCCESS(Status)) break;
1683*c2c66affSColin Finck 
1684*c2c66affSColin Finck         /* Also check if we hit an invalid entry here */
1685*c2c66affSColin Finck         if (!IsValid)
1686*c2c66affSColin Finck         {
1687*c2c66affSColin Finck             /* We did, so break out of the loop minus one entry */
1688*c2c66affSColin Finck             j--;
1689*c2c66affSColin Finck             break;
1690*c2c66affSColin Finck         }
1691*c2c66affSColin Finck 
1692*c2c66affSColin Finck         /* Reset the offset */
1693*c2c66affSColin Finck         Offset.QuadPart = 0;
1694*c2c66affSColin Finck 
1695*c2c66affSColin Finck         /* Go back to the descriptor array and loop it */
1696*c2c66affSColin Finck         PartitionDescriptor = (PPARTITION_DESCRIPTOR)
1697*c2c66affSColin Finck                                &(((PUSHORT)Buffer)[PARTITION_TABLE_OFFSET]);
1698*c2c66affSColin Finck         for (Entry = 1; Entry <= 4; Entry++, PartitionDescriptor++)
1699*c2c66affSColin Finck         {
1700*c2c66affSColin Finck             /* Check if this is a container partition, since we skipped them */
1701*c2c66affSColin Finck             if (IsContainerPartition(PartitionDescriptor->PartitionType))
1702*c2c66affSColin Finck             {
1703*c2c66affSColin Finck                 /* Get its offset */
1704*c2c66affSColin Finck                 Offset.QuadPart = VolumeOffset.QuadPart +
1705*c2c66affSColin Finck                                   UInt32x32To64(
1706*c2c66affSColin Finck                                      GET_STARTING_SECTOR(PartitionDescriptor),
1707*c2c66affSColin Finck                                      SectorSize);
1708*c2c66affSColin Finck 
1709*c2c66affSColin Finck                 /* If this is a primary partition, this is the volume offset */
1710*c2c66affSColin Finck                 if (IsPrimary) VolumeOffset = Offset;
1711*c2c66affSColin Finck 
1712*c2c66affSColin Finck                 /* Also update the maximum sector */
1713*c2c66affSColin Finck                 MaxSector = GET_PARTITION_LENGTH(PartitionDescriptor);
1714*c2c66affSColin Finck                 DPRINT1("FSTUB: MaxSector now = %I64d\n", MaxSector);
1715*c2c66affSColin Finck                 break;
1716*c2c66affSColin Finck             }
1717*c2c66affSColin Finck         }
1718*c2c66affSColin Finck 
1719*c2c66affSColin Finck         /* Loop the next partitions, which are not primary anymore */
1720*c2c66affSColin Finck         IsPrimary = FALSE;
1721*c2c66affSColin Finck     } while (Offset.HighPart | Offset.LowPart);
1722*c2c66affSColin Finck 
1723*c2c66affSColin Finck     /* Check if this is a removable device that's probably a super-floppy */
1724*c2c66affSColin Finck     if ((DiskGeometry.MediaType == RemovableMedia) &&
1725*c2c66affSColin Finck         !(j) &&
1726*c2c66affSColin Finck         (MbrFound) &&
1727*c2c66affSColin Finck         (IsEmpty))
1728*c2c66affSColin Finck     {
1729*c2c66affSColin Finck         /* Read the jump bytes to detect super-floppy */
1730*c2c66affSColin Finck         if ((BootSectorInfo->JumpByte[0] == 0xeb) ||
1731*c2c66affSColin Finck             (BootSectorInfo->JumpByte[0] == 0xe9))
1732*c2c66affSColin Finck         {
1733*c2c66affSColin Finck             /* Super floppes don't have typical MBRs, so skip them */
1734*c2c66affSColin Finck             DPRINT1("FSTUB: Jump byte %#x found along with empty partition "
1735*c2c66affSColin Finck                     "table - disk is a super floppy and has no valid MBR\n",
1736*c2c66affSColin Finck                     BootSectorInfo->JumpByte);
1737*c2c66affSColin Finck             j = -1;
1738*c2c66affSColin Finck         }
1739*c2c66affSColin Finck     }
1740*c2c66affSColin Finck 
1741*c2c66affSColin Finck     /* Check if we're still at partition -1 */
1742*c2c66affSColin Finck     if (j == -1)
1743*c2c66affSColin Finck     {
1744*c2c66affSColin Finck         /* The likely cause is the super floppy detection above */
1745*c2c66affSColin Finck         if ((MbrFound) || (DiskGeometry.MediaType == RemovableMedia))
1746*c2c66affSColin Finck         {
1747*c2c66affSColin Finck             /* Print out debugging information */
1748*c2c66affSColin Finck             DPRINT1("FSTUB: Drive %#p has no valid MBR. Make it into a "
1749*c2c66affSColin Finck                     "super-floppy\n",
1750*c2c66affSColin Finck                     DeviceObject);
1751*c2c66affSColin Finck             DPRINT1("FSTUB: Drive has %I64d sectors and is %#016I64x "
1752*c2c66affSColin Finck                     "bytes large\n",
1753*c2c66affSColin Finck                     EndSector, EndSector * DiskGeometry.BytesPerSector);
1754*c2c66affSColin Finck 
1755*c2c66affSColin Finck             /* We should at least have some sectors */
1756*c2c66affSColin Finck             if (EndSector > 0)
1757*c2c66affSColin Finck             {
1758*c2c66affSColin Finck                 /* Get the entry we'll use */
1759*c2c66affSColin Finck                 PartitionInfo = &(*PartitionBuffer)->PartitionEntry[0];
1760*c2c66affSColin Finck 
1761*c2c66affSColin Finck                 /* Fill it out with data for a super-floppy */
1762*c2c66affSColin Finck                 PartitionInfo->RewritePartition = FALSE;
1763*c2c66affSColin Finck                 PartitionInfo->RecognizedPartition = TRUE;
1764*c2c66affSColin Finck                 PartitionInfo->PartitionType = PARTITION_FAT_16;
1765*c2c66affSColin Finck                 PartitionInfo->BootIndicator = FALSE;
1766*c2c66affSColin Finck                 PartitionInfo->HiddenSectors = 0;
1767*c2c66affSColin Finck                 PartitionInfo->StartingOffset.QuadPart = 0;
1768*c2c66affSColin Finck                 PartitionInfo->PartitionLength.QuadPart = (EndSector *
1769*c2c66affSColin Finck                                                            DiskGeometry.
1770*c2c66affSColin Finck                                                            BytesPerSector);
1771*c2c66affSColin Finck 
1772*c2c66affSColin Finck                 /* FIXME: REACTOS HACK */
1773*c2c66affSColin Finck                 PartitionInfo->PartitionNumber = 0;
1774*c2c66affSColin Finck 
1775*c2c66affSColin Finck                 /* Set the signature and set the count back to 0 */
1776*c2c66affSColin Finck                 (*PartitionBuffer)->Signature = 1;
1777*c2c66affSColin Finck                 i = 0;
1778*c2c66affSColin Finck             }
1779*c2c66affSColin Finck         }
1780*c2c66affSColin Finck         else
1781*c2c66affSColin Finck         {
1782*c2c66affSColin Finck             /* Otherwise, this isn't a super floppy, so set an invalid count */
1783*c2c66affSColin Finck             i = -1;
1784*c2c66affSColin Finck         }
1785*c2c66affSColin Finck     }
1786*c2c66affSColin Finck 
1787*c2c66affSColin Finck     /* Set the partition count */
1788*c2c66affSColin Finck     (*PartitionBuffer)->PartitionCount = ++i;
1789*c2c66affSColin Finck 
1790*c2c66affSColin Finck     /* If we have no count, delete the signature */
1791*c2c66affSColin Finck     if (!i) (*PartitionBuffer)->Signature = 0;
1792*c2c66affSColin Finck 
1793*c2c66affSColin Finck     /* Free the buffer and check for success */
1794*c2c66affSColin Finck     if (Buffer) ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM);
1795*c2c66affSColin Finck     if (!NT_SUCCESS(Status))
1796*c2c66affSColin Finck     {
1797*c2c66affSColin Finck         ExFreePoolWithTag(*PartitionBuffer, TAG_FILE_SYSTEM);
1798*c2c66affSColin Finck         *PartitionBuffer = NULL;
1799*c2c66affSColin Finck     }
1800*c2c66affSColin Finck 
1801*c2c66affSColin Finck     /* Return status */
1802*c2c66affSColin Finck     return Status;
1803*c2c66affSColin Finck }
1804*c2c66affSColin Finck 
1805*c2c66affSColin Finck NTSTATUS
1806*c2c66affSColin Finck FASTCALL
1807*c2c66affSColin Finck xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject,
1808*c2c66affSColin Finck                               IN ULONG SectorSize,
1809*c2c66affSColin Finck                               IN ULONG PartitionNumber,
1810*c2c66affSColin Finck                               IN ULONG PartitionType)
1811*c2c66affSColin Finck {
1812*c2c66affSColin Finck     PIRP Irp;
1813*c2c66affSColin Finck     KEVENT Event;
1814*c2c66affSColin Finck     IO_STATUS_BLOCK IoStatusBlock;
1815*c2c66affSColin Finck     NTSTATUS Status;
1816*c2c66affSColin Finck     LARGE_INTEGER Offset, VolumeOffset;
1817*c2c66affSColin Finck     PUCHAR Buffer = NULL;
1818*c2c66affSColin Finck     ULONG BufferSize;
1819*c2c66affSColin Finck     ULONG i = 0;
1820*c2c66affSColin Finck     ULONG Entry;
1821*c2c66affSColin Finck     PPARTITION_DESCRIPTOR PartitionDescriptor;
1822*c2c66affSColin Finck     BOOLEAN IsPrimary = TRUE, IsEzDrive = FALSE;
1823*c2c66affSColin Finck     PVOID MbrBuffer;
1824*c2c66affSColin Finck     PIO_STACK_LOCATION IoStackLocation;
1825*c2c66affSColin Finck     VolumeOffset.QuadPart = Offset.QuadPart = 0;
1826*c2c66affSColin Finck     PAGED_CODE();
1827*c2c66affSColin Finck 
1828*c2c66affSColin Finck     /* Normalize the buffer size */
1829*c2c66affSColin Finck     BufferSize = max(512, SectorSize);
1830*c2c66affSColin Finck 
1831*c2c66affSColin Finck     /* Check for EZ Drive */
1832*c2c66affSColin Finck     HalExamineMBR(DeviceObject, BufferSize, 0x55, &MbrBuffer);
1833*c2c66affSColin Finck     if (MbrBuffer)
1834*c2c66affSColin Finck     {
1835*c2c66affSColin Finck         /* EZ Drive found, bias the offset */
1836*c2c66affSColin Finck         IsEzDrive = TRUE;
1837*c2c66affSColin Finck         ExFreePoolWithTag(MbrBuffer, TAG_FILE_SYSTEM);
1838*c2c66affSColin Finck         Offset.QuadPart = 512;
1839*c2c66affSColin Finck     }
1840*c2c66affSColin Finck 
1841*c2c66affSColin Finck     /* Allocate our partition buffer */
1842*c2c66affSColin Finck     Buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, TAG_FILE_SYSTEM);
1843*c2c66affSColin Finck     if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES;
1844*c2c66affSColin Finck 
1845*c2c66affSColin Finck     /* Initialize the event we'll use and loop partitions */
1846*c2c66affSColin Finck     KeInitializeEvent(&Event, NotificationEvent, FALSE);
1847*c2c66affSColin Finck     do
1848*c2c66affSColin Finck     {
1849*c2c66affSColin Finck         /* Reset the event since we reuse it */
1850*c2c66affSColin Finck         KeResetEvent(&Event);
1851*c2c66affSColin Finck 
1852*c2c66affSColin Finck         /* Build the read IRP */
1853*c2c66affSColin Finck         Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
1854*c2c66affSColin Finck                                            DeviceObject,
1855*c2c66affSColin Finck                                            Buffer,
1856*c2c66affSColin Finck                                            BufferSize,
1857*c2c66affSColin Finck                                            &Offset,
1858*c2c66affSColin Finck                                            &Event,
1859*c2c66affSColin Finck                                            &IoStatusBlock);
1860*c2c66affSColin Finck         if (!Irp)
1861*c2c66affSColin Finck         {
1862*c2c66affSColin Finck             /* Fail */
1863*c2c66affSColin Finck             Status = STATUS_INSUFFICIENT_RESOURCES;
1864*c2c66affSColin Finck             break;
1865*c2c66affSColin Finck         }
1866*c2c66affSColin Finck 
1867*c2c66affSColin Finck         /* Make sure to disable volume verification */
1868*c2c66affSColin Finck         IoStackLocation = IoGetNextIrpStackLocation(Irp);
1869*c2c66affSColin Finck         IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
1870*c2c66affSColin Finck 
1871*c2c66affSColin Finck         /* Call the driver */
1872*c2c66affSColin Finck         Status = IoCallDriver(DeviceObject, Irp);
1873*c2c66affSColin Finck         if (Status == STATUS_PENDING)
1874*c2c66affSColin Finck         {
1875*c2c66affSColin Finck             /* Wait for completion */
1876*c2c66affSColin Finck             KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
1877*c2c66affSColin Finck             Status = IoStatusBlock.Status;
1878*c2c66affSColin Finck         }
1879*c2c66affSColin Finck 
1880*c2c66affSColin Finck         /* Check for failure */
1881*c2c66affSColin Finck         if (!NT_SUCCESS(Status)) break;
1882*c2c66affSColin Finck 
1883*c2c66affSColin Finck         /* If we biased for EZ-Drive, unbias now */
1884*c2c66affSColin Finck         if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
1885*c2c66affSColin Finck 
1886*c2c66affSColin Finck         /* Make sure this is a valid MBR */
1887*c2c66affSColin Finck         if (((PUSHORT)Buffer)[BOOT_SIGNATURE_OFFSET] != BOOT_RECORD_SIGNATURE)
1888*c2c66affSColin Finck         {
1889*c2c66affSColin Finck             /* It's not, fail */
1890*c2c66affSColin Finck             Status = STATUS_BAD_MASTER_BOOT_RECORD;
1891*c2c66affSColin Finck             break;
1892*c2c66affSColin Finck         }
1893*c2c66affSColin Finck 
1894*c2c66affSColin Finck         /* Get the partition descriptors and loop them */
1895*c2c66affSColin Finck         PartitionDescriptor = (PPARTITION_DESCRIPTOR)
1896*c2c66affSColin Finck                               &(((PUSHORT)Buffer)[PARTITION_TABLE_OFFSET]);
1897*c2c66affSColin Finck         for (Entry = 1; Entry <= 4; Entry++, PartitionDescriptor++)
1898*c2c66affSColin Finck         {
1899*c2c66affSColin Finck             /* Check if it's unused or a container partition */
1900*c2c66affSColin Finck             if ((PartitionDescriptor->PartitionType ==
1901*c2c66affSColin Finck                  PARTITION_ENTRY_UNUSED) ||
1902*c2c66affSColin Finck                 (IsContainerPartition(PartitionDescriptor->PartitionType)))
1903*c2c66affSColin Finck             {
1904*c2c66affSColin Finck                 /* Go to the next one */
1905*c2c66affSColin Finck                 continue;
1906*c2c66affSColin Finck             }
1907*c2c66affSColin Finck 
1908*c2c66affSColin Finck             /* It's a valid partition, so increase the partition count */
1909*c2c66affSColin Finck             if (++i == PartitionNumber)
1910*c2c66affSColin Finck             {
1911*c2c66affSColin Finck                 /* We found a match, set the type */
1912*c2c66affSColin Finck                 PartitionDescriptor->PartitionType = (UCHAR)PartitionType;
1913*c2c66affSColin Finck 
1914*c2c66affSColin Finck                 /* Reset the reusable event */
1915*c2c66affSColin Finck                 KeResetEvent(&Event);
1916*c2c66affSColin Finck 
1917*c2c66affSColin Finck                 /* Build the write IRP */
1918*c2c66affSColin Finck                 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
1919*c2c66affSColin Finck                                                    DeviceObject,
1920*c2c66affSColin Finck                                                    Buffer,
1921*c2c66affSColin Finck                                                    BufferSize,
1922*c2c66affSColin Finck                                                    &Offset,
1923*c2c66affSColin Finck                                                    &Event,
1924*c2c66affSColin Finck                                                    &IoStatusBlock);
1925*c2c66affSColin Finck                 if (!Irp)
1926*c2c66affSColin Finck                 {
1927*c2c66affSColin Finck                     /* Fail */
1928*c2c66affSColin Finck                     Status = STATUS_INSUFFICIENT_RESOURCES;
1929*c2c66affSColin Finck                     break;
1930*c2c66affSColin Finck                 }
1931*c2c66affSColin Finck 
1932*c2c66affSColin Finck                 /* Disable volume verification */
1933*c2c66affSColin Finck                 IoStackLocation = IoGetNextIrpStackLocation(Irp);
1934*c2c66affSColin Finck                 IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
1935*c2c66affSColin Finck 
1936*c2c66affSColin Finck                 /* Call the driver */
1937*c2c66affSColin Finck                 Status = IoCallDriver(DeviceObject, Irp);
1938*c2c66affSColin Finck                 if (Status == STATUS_PENDING)
1939*c2c66affSColin Finck                 {
1940*c2c66affSColin Finck                     /* Wait for completion */
1941*c2c66affSColin Finck                     KeWaitForSingleObject(&Event,
1942*c2c66affSColin Finck                                           Executive,
1943*c2c66affSColin Finck                                           KernelMode,
1944*c2c66affSColin Finck                                           FALSE,
1945*c2c66affSColin Finck                                           NULL);
1946*c2c66affSColin Finck                     Status = IoStatusBlock.Status;
1947*c2c66affSColin Finck                 }
1948*c2c66affSColin Finck 
1949*c2c66affSColin Finck                 /* We're done, break out of the loop */
1950*c2c66affSColin Finck                 break;
1951*c2c66affSColin Finck             }
1952*c2c66affSColin Finck         }
1953*c2c66affSColin Finck 
1954*c2c66affSColin Finck         /* If we looped all the partitions, break out */
1955*c2c66affSColin Finck         if (Entry <= NUM_PARTITION_TABLE_ENTRIES) break;
1956*c2c66affSColin Finck 
1957*c2c66affSColin Finck         /* Nothing found yet, get the partition array again */
1958*c2c66affSColin Finck         PartitionDescriptor = (PPARTITION_DESCRIPTOR)
1959*c2c66affSColin Finck                                &(((PUSHORT)Buffer)[PARTITION_TABLE_OFFSET]);
1960*c2c66affSColin Finck         for (Entry = 1; Entry <= 4; Entry++, PartitionDescriptor++)
1961*c2c66affSColin Finck         {
1962*c2c66affSColin Finck             /* Check if this was a container partition (we skipped these) */
1963*c2c66affSColin Finck             if (IsContainerPartition(PartitionDescriptor->PartitionType))
1964*c2c66affSColin Finck             {
1965*c2c66affSColin Finck                 /* Update the partition offset */
1966*c2c66affSColin Finck                 Offset.QuadPart = VolumeOffset.QuadPart +
1967*c2c66affSColin Finck                                   GET_STARTING_SECTOR(PartitionDescriptor) *
1968*c2c66affSColin Finck                                   SectorSize;
1969*c2c66affSColin Finck 
1970*c2c66affSColin Finck                 /* If this was the primary partition, update the volume too */
1971*c2c66affSColin Finck                 if (IsPrimary) VolumeOffset = Offset;
1972*c2c66affSColin Finck                 break;
1973*c2c66affSColin Finck             }
1974*c2c66affSColin Finck         }
1975*c2c66affSColin Finck 
1976*c2c66affSColin Finck         /* Check if we already searched all the partitions */
1977*c2c66affSColin Finck         if (Entry > NUM_PARTITION_TABLE_ENTRIES)
1978*c2c66affSColin Finck         {
1979*c2c66affSColin Finck             /* Then we failed to find a good MBR */
1980*c2c66affSColin Finck             Status = STATUS_BAD_MASTER_BOOT_RECORD;
1981*c2c66affSColin Finck             break;
1982*c2c66affSColin Finck         }
1983*c2c66affSColin Finck 
1984*c2c66affSColin Finck         /* Loop the next partitions, which are not primary anymore */
1985*c2c66affSColin Finck         IsPrimary = FALSE;
1986*c2c66affSColin Finck     } while (i < PartitionNumber);
1987*c2c66affSColin Finck 
1988*c2c66affSColin Finck     /* Everything done, cleanup */
1989*c2c66affSColin Finck     if (Buffer) ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM);
1990*c2c66affSColin Finck     return Status;
1991*c2c66affSColin Finck }
1992*c2c66affSColin Finck 
1993*c2c66affSColin Finck NTSTATUS
1994*c2c66affSColin Finck FASTCALL
1995*c2c66affSColin Finck xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject,
1996*c2c66affSColin Finck                           IN ULONG SectorSize,
1997*c2c66affSColin Finck                           IN ULONG SectorsPerTrack,
1998*c2c66affSColin Finck                           IN ULONG NumberOfHeads,
1999*c2c66affSColin Finck                           IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
2000*c2c66affSColin Finck {
2001*c2c66affSColin Finck     KEVENT Event;
2002*c2c66affSColin Finck     IO_STATUS_BLOCK IoStatusBlock;
2003*c2c66affSColin Finck     PIRP Irp;
2004*c2c66affSColin Finck     NTSTATUS Status = STATUS_SUCCESS;
2005*c2c66affSColin Finck     ULONG BufferSize;
2006*c2c66affSColin Finck     PUSHORT Buffer;
2007*c2c66affSColin Finck     PPTE Entry;
2008*c2c66affSColin Finck     PPARTITION_TABLE PartitionTable;
2009*c2c66affSColin Finck     LARGE_INTEGER Offset, NextOffset, ExtendedOffset, SectorOffset;
2010*c2c66affSColin Finck     LARGE_INTEGER StartOffset, PartitionLength;
2011*c2c66affSColin Finck     ULONG i, j;
2012*c2c66affSColin Finck     CCHAR k;
2013*c2c66affSColin Finck     BOOLEAN IsEzDrive = FALSE, IsSuperFloppy = FALSE, DoRewrite = FALSE, IsMbr;
2014*c2c66affSColin Finck     ULONG ConventionalCylinders;
2015*c2c66affSColin Finck     LONGLONG DiskSize;
2016*c2c66affSColin Finck     PDISK_LAYOUT DiskLayout = (PDISK_LAYOUT)PartitionBuffer;
2017*c2c66affSColin Finck     PVOID MbrBuffer;
2018*c2c66affSColin Finck     UCHAR PartitionType;
2019*c2c66affSColin Finck     PIO_STACK_LOCATION IoStackLocation;
2020*c2c66affSColin Finck     PPARTITION_INFORMATION PartitionInfo = PartitionBuffer->PartitionEntry;
2021*c2c66affSColin Finck     PPARTITION_INFORMATION TableEntry;
2022*c2c66affSColin Finck     ExtendedOffset.QuadPart = NextOffset.QuadPart = Offset.QuadPart = 0;
2023*c2c66affSColin Finck     PAGED_CODE();
2024*c2c66affSColin Finck 
2025*c2c66affSColin Finck     /* Normalize the buffer size */
2026*c2c66affSColin Finck     BufferSize = max(512, SectorSize);
2027*c2c66affSColin Finck 
2028*c2c66affSColin Finck     /* Get the partial drive geometry */
2029*c2c66affSColin Finck     xHalGetPartialGeometry(DeviceObject, &ConventionalCylinders, &DiskSize);
2030*c2c66affSColin Finck 
2031*c2c66affSColin Finck     /* Check for EZ Drive */
2032*c2c66affSColin Finck     HalExamineMBR(DeviceObject, BufferSize, 0x55, &MbrBuffer);
2033*c2c66affSColin Finck     if (MbrBuffer)
2034*c2c66affSColin Finck     {
2035*c2c66affSColin Finck         /* EZ Drive found, bias the offset */
2036*c2c66affSColin Finck         IsEzDrive = TRUE;
2037*c2c66affSColin Finck         ExFreePoolWithTag(MbrBuffer, TAG_FILE_SYSTEM);
2038*c2c66affSColin Finck         Offset.QuadPart = 512;
2039*c2c66affSColin Finck     }
2040*c2c66affSColin Finck 
2041*c2c66affSColin Finck     /* Get the number of bits to shift to multiply by the sector size */
2042*c2c66affSColin Finck     for (k = 0; k < 32; k++) if ((SectorSize >> k) == 1) break;
2043*c2c66affSColin Finck 
2044*c2c66affSColin Finck     /* Check if there's only one partition */
2045*c2c66affSColin Finck     if (PartitionBuffer->PartitionCount == 1)
2046*c2c66affSColin Finck     {
2047*c2c66affSColin Finck         /* Check if it has no starting offset or hidden sectors */
2048*c2c66affSColin Finck         if (!(PartitionInfo->StartingOffset.QuadPart) &&
2049*c2c66affSColin Finck             !(PartitionInfo->HiddenSectors))
2050*c2c66affSColin Finck         {
2051*c2c66affSColin Finck             /* Then it's a super floppy */
2052*c2c66affSColin Finck             IsSuperFloppy = TRUE;
2053*c2c66affSColin Finck 
2054*c2c66affSColin Finck             /* Which also means it must be non-bootable FAT-16 */
2055*c2c66affSColin Finck             if ((PartitionInfo->PartitionNumber) ||
2056*c2c66affSColin Finck                 (PartitionInfo->PartitionType != PARTITION_FAT_16) ||
2057*c2c66affSColin Finck                 (PartitionInfo->BootIndicator))
2058*c2c66affSColin Finck             {
2059*c2c66affSColin Finck                 /* It's not, so we fail */
2060*c2c66affSColin Finck                 return STATUS_INVALID_PARAMETER;
2061*c2c66affSColin Finck             }
2062*c2c66affSColin Finck 
2063*c2c66affSColin Finck             /* Check if it needs a rewrite, and disable EZ drive for sure */
2064*c2c66affSColin Finck             if (PartitionInfo->RewritePartition) DoRewrite = TRUE;
2065*c2c66affSColin Finck             IsEzDrive = FALSE;
2066*c2c66affSColin Finck         }
2067*c2c66affSColin Finck     }
2068*c2c66affSColin Finck 
2069*c2c66affSColin Finck     /* Count the number of partition tables */
2070*c2c66affSColin Finck     DiskLayout->TableCount = (PartitionBuffer->PartitionCount + 4 - 1) / 4;
2071*c2c66affSColin Finck 
2072*c2c66affSColin Finck     /* Allocate our partition buffer */
2073*c2c66affSColin Finck     Buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, TAG_FILE_SYSTEM);
2074*c2c66affSColin Finck     if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES;
2075*c2c66affSColin Finck 
2076*c2c66affSColin Finck     /* Loop the entries */
2077*c2c66affSColin Finck     Entry = (PPTE)&Buffer[PARTITION_TABLE_OFFSET];
2078*c2c66affSColin Finck     for (i = 0; i < DiskLayout->TableCount; i++)
2079*c2c66affSColin Finck     {
2080*c2c66affSColin Finck         /* Set if this is the MBR partition */
2081*c2c66affSColin Finck         IsMbr= (BOOLEAN)!i;
2082*c2c66affSColin Finck 
2083*c2c66affSColin Finck         /* Initialize th event */
2084*c2c66affSColin Finck         KeInitializeEvent(&Event, NotificationEvent, FALSE);
2085*c2c66affSColin Finck 
2086*c2c66affSColin Finck         /* Build the read IRP */
2087*c2c66affSColin Finck         Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
2088*c2c66affSColin Finck                                            DeviceObject,
2089*c2c66affSColin Finck                                            Buffer,
2090*c2c66affSColin Finck                                            BufferSize,
2091*c2c66affSColin Finck                                            &Offset,
2092*c2c66affSColin Finck                                            &Event,
2093*c2c66affSColin Finck                                            &IoStatusBlock);
2094*c2c66affSColin Finck         if (!Irp)
2095*c2c66affSColin Finck         {
2096*c2c66affSColin Finck             /* Fail */
2097*c2c66affSColin Finck             Status = STATUS_INSUFFICIENT_RESOURCES;
2098*c2c66affSColin Finck             break;
2099*c2c66affSColin Finck         }
2100*c2c66affSColin Finck 
2101*c2c66affSColin Finck         /* Make sure to disable volume verification */
2102*c2c66affSColin Finck         IoStackLocation = IoGetNextIrpStackLocation(Irp);
2103*c2c66affSColin Finck         IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
2104*c2c66affSColin Finck 
2105*c2c66affSColin Finck         /* Call the driver */
2106*c2c66affSColin Finck         Status = IoCallDriver(DeviceObject, Irp);
2107*c2c66affSColin Finck         if (Status == STATUS_PENDING)
2108*c2c66affSColin Finck         {
2109*c2c66affSColin Finck             /* Wait for completion */
2110*c2c66affSColin Finck             KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
2111*c2c66affSColin Finck             Status = IoStatusBlock.Status;
2112*c2c66affSColin Finck         }
2113*c2c66affSColin Finck 
2114*c2c66affSColin Finck         /* Check for failure */
2115*c2c66affSColin Finck         if (!NT_SUCCESS(Status)) break;
2116*c2c66affSColin Finck 
2117*c2c66affSColin Finck         /* If we biased for EZ-Drive, unbias now */
2118*c2c66affSColin Finck         if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
2119*c2c66affSColin Finck 
2120*c2c66affSColin Finck         /* Check if this is a normal disk */
2121*c2c66affSColin Finck         if (!IsSuperFloppy)
2122*c2c66affSColin Finck         {
2123*c2c66affSColin Finck             /* Set the boot record signature */
2124*c2c66affSColin Finck             Buffer[BOOT_SIGNATURE_OFFSET] = BOOT_RECORD_SIGNATURE;
2125*c2c66affSColin Finck 
2126*c2c66affSColin Finck             /* By default, don't require a rewrite */
2127*c2c66affSColin Finck             DoRewrite = FALSE;
2128*c2c66affSColin Finck 
2129*c2c66affSColin Finck             /* Check if we don't have an offset */
2130*c2c66affSColin Finck             if (!Offset.QuadPart)
2131*c2c66affSColin Finck             {
2132*c2c66affSColin Finck                 /* Check if the signature doesn't match */
2133*c2c66affSColin Finck                 if (((PULONG)Buffer)[PARTITION_TABLE_OFFSET / 2 - 1] !=
2134*c2c66affSColin Finck                     PartitionBuffer->Signature)
2135*c2c66affSColin Finck                 {
2136*c2c66affSColin Finck                     /* Then write the signature and now w need a rewrite */
2137*c2c66affSColin Finck                     ((PULONG)Buffer)[PARTITION_TABLE_OFFSET / 2 - 1] =
2138*c2c66affSColin Finck                         PartitionBuffer->Signature;
2139*c2c66affSColin Finck                     DoRewrite = TRUE;
2140*c2c66affSColin Finck                 }
2141*c2c66affSColin Finck             }
2142*c2c66affSColin Finck 
2143*c2c66affSColin Finck             /* Loop the partition table entries */
2144*c2c66affSColin Finck             PartitionTable = &DiskLayout->PartitionTable[i];
2145*c2c66affSColin Finck             for (j = 0; j < 4; j++)
2146*c2c66affSColin Finck             {
2147*c2c66affSColin Finck                 /* Get the current entry and type */
2148*c2c66affSColin Finck                 TableEntry = &PartitionTable->PartitionEntry[j];
2149*c2c66affSColin Finck                 PartitionType = TableEntry->PartitionType;
2150*c2c66affSColin Finck 
2151*c2c66affSColin Finck                 /* Check if the entry needs a rewrite */
2152*c2c66affSColin Finck                 if (TableEntry->RewritePartition)
2153*c2c66affSColin Finck                 {
2154*c2c66affSColin Finck                     /* Then we need one too */
2155*c2c66affSColin Finck                     DoRewrite = TRUE;
2156*c2c66affSColin Finck 
2157*c2c66affSColin Finck                     /* Save the type and if it's a bootable partition */
2158*c2c66affSColin Finck                     Entry[j].PartitionType = TableEntry->PartitionType;
2159*c2c66affSColin Finck                     Entry[j].ActiveFlag = TableEntry->BootIndicator ? 0x80 : 0;
2160*c2c66affSColin Finck 
2161*c2c66affSColin Finck                     /* Make sure it's used */
2162*c2c66affSColin Finck                     if (PartitionType != PARTITION_ENTRY_UNUSED)
2163*c2c66affSColin Finck                     {
2164*c2c66affSColin Finck                         /* Make sure it's not a container (unless primary) */
2165*c2c66affSColin Finck                         if ((IsMbr) || !(IsContainerPartition(PartitionType)))
2166*c2c66affSColin Finck                         {
2167*c2c66affSColin Finck                             /* Use the partition offset */
2168*c2c66affSColin Finck                             StartOffset.QuadPart = Offset.QuadPart;
2169*c2c66affSColin Finck                         }
2170*c2c66affSColin Finck                         else
2171*c2c66affSColin Finck                         {
2172*c2c66affSColin Finck                             /* Use the extended logical partition offset */
2173*c2c66affSColin Finck                             StartOffset.QuadPart = ExtendedOffset.QuadPart;
2174*c2c66affSColin Finck                         }
2175*c2c66affSColin Finck 
2176*c2c66affSColin Finck                         /* Set the sector offset */
2177*c2c66affSColin Finck                         SectorOffset.QuadPart = TableEntry->
2178*c2c66affSColin Finck                                                 StartingOffset.QuadPart -
2179*c2c66affSColin Finck                                                 StartOffset.QuadPart;
2180*c2c66affSColin Finck 
2181*c2c66affSColin Finck                         /* Now calculate the starting sector */
2182*c2c66affSColin Finck                         StartOffset.QuadPart = SectorOffset.QuadPart >> k;
2183*c2c66affSColin Finck                         Entry[j].StartingSector = StartOffset.LowPart;
2184*c2c66affSColin Finck 
2185*c2c66affSColin Finck                         /* As well as the length */
2186*c2c66affSColin Finck                         PartitionLength.QuadPart = TableEntry->PartitionLength.
2187*c2c66affSColin Finck                                                    QuadPart >> k;
2188*c2c66affSColin Finck                         Entry[j].PartitionLength = PartitionLength.LowPart;
2189*c2c66affSColin Finck 
2190*c2c66affSColin Finck                         /* Calculate the CHS values */
2191*c2c66affSColin Finck                         HalpCalculateChsValues(&TableEntry->StartingOffset,
2192*c2c66affSColin Finck                                                &TableEntry->PartitionLength,
2193*c2c66affSColin Finck                                                k,
2194*c2c66affSColin Finck                                                SectorsPerTrack,
2195*c2c66affSColin Finck                                                NumberOfHeads,
2196*c2c66affSColin Finck                                                ConventionalCylinders,
2197*c2c66affSColin Finck                                                (PPARTITION_DESCRIPTOR)
2198*c2c66affSColin Finck                                                &Entry[j]);
2199*c2c66affSColin Finck                     }
2200*c2c66affSColin Finck                     else
2201*c2c66affSColin Finck                     {
2202*c2c66affSColin Finck                         /* Otherwise set up an empty entry */
2203*c2c66affSColin Finck                         Entry[j].StartingSector = 0;
2204*c2c66affSColin Finck                         Entry[j].PartitionLength = 0;
2205*c2c66affSColin Finck                         Entry[j].StartingTrack = 0;
2206*c2c66affSColin Finck                         Entry[j].EndingTrack = 0;
2207*c2c66affSColin Finck                         Entry[j].StartingCylinder = 0;
2208*c2c66affSColin Finck                         Entry[j].EndingCylinder = 0;
2209*c2c66affSColin Finck                     }
2210*c2c66affSColin Finck                 }
2211*c2c66affSColin Finck 
2212*c2c66affSColin Finck                 /* Check if this is a container partition */
2213*c2c66affSColin Finck                 if (IsContainerPartition(PartitionType))
2214*c2c66affSColin Finck                 {
2215*c2c66affSColin Finck                     /* Then update the offset to use */
2216*c2c66affSColin Finck                     NextOffset = TableEntry->StartingOffset;
2217*c2c66affSColin Finck                 }
2218*c2c66affSColin Finck             }
2219*c2c66affSColin Finck         }
2220*c2c66affSColin Finck 
2221*c2c66affSColin Finck         /* Check if we need to write back the buffer */
2222*c2c66affSColin Finck         if (DoRewrite)
2223*c2c66affSColin Finck         {
2224*c2c66affSColin Finck             /* We don't need to do this again */
2225*c2c66affSColin Finck             DoRewrite = FALSE;
2226*c2c66affSColin Finck 
2227*c2c66affSColin Finck             /* Initialize the event */
2228*c2c66affSColin Finck             KeInitializeEvent(&Event, NotificationEvent, FALSE);
2229*c2c66affSColin Finck 
2230*c2c66affSColin Finck             /* If we unbiased for EZ-Drive, rebias now */
2231*c2c66affSColin Finck             if ((IsEzDrive) && !(Offset.QuadPart)) Offset.QuadPart = 512;
2232*c2c66affSColin Finck 
2233*c2c66affSColin Finck             /* Build the write IRP */
2234*c2c66affSColin Finck             Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
2235*c2c66affSColin Finck                                                DeviceObject,
2236*c2c66affSColin Finck                                                Buffer,
2237*c2c66affSColin Finck                                                BufferSize,
2238*c2c66affSColin Finck                                                &Offset,
2239*c2c66affSColin Finck                                                &Event,
2240*c2c66affSColin Finck                                                &IoStatusBlock);
2241*c2c66affSColin Finck             if (!Irp)
2242*c2c66affSColin Finck             {
2243*c2c66affSColin Finck                 /* Fail */
2244*c2c66affSColin Finck                 Status = STATUS_INSUFFICIENT_RESOURCES;
2245*c2c66affSColin Finck                 break;
2246*c2c66affSColin Finck             }
2247*c2c66affSColin Finck 
2248*c2c66affSColin Finck             /* Make sure to disable volume verification */
2249*c2c66affSColin Finck             IoStackLocation = IoGetNextIrpStackLocation(Irp);
2250*c2c66affSColin Finck             IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
2251*c2c66affSColin Finck 
2252*c2c66affSColin Finck             /* Call the driver */
2253*c2c66affSColin Finck             Status = IoCallDriver(DeviceObject, Irp);
2254*c2c66affSColin Finck             if (Status == STATUS_PENDING)
2255*c2c66affSColin Finck             {
2256*c2c66affSColin Finck                 /* Wait for completion */
2257*c2c66affSColin Finck                 KeWaitForSingleObject(&Event,
2258*c2c66affSColin Finck                                       Executive,
2259*c2c66affSColin Finck                                       KernelMode,
2260*c2c66affSColin Finck                                       FALSE,
2261*c2c66affSColin Finck                                       NULL);
2262*c2c66affSColin Finck                 Status = IoStatusBlock.Status;
2263*c2c66affSColin Finck             }
2264*c2c66affSColin Finck 
2265*c2c66affSColin Finck             /* Check for failure */
2266*c2c66affSColin Finck             if (!NT_SUCCESS(Status)) break;
2267*c2c66affSColin Finck 
2268*c2c66affSColin Finck             /* If we biased for EZ-Drive, unbias now */
2269*c2c66affSColin Finck             if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0;
2270*c2c66affSColin Finck         }
2271*c2c66affSColin Finck 
2272*c2c66affSColin Finck         /* Update the partition offset and set the extended offset if needed */
2273*c2c66affSColin Finck         Offset = NextOffset;
2274*c2c66affSColin Finck         if (IsMbr) ExtendedOffset = NextOffset;
2275*c2c66affSColin Finck     }
2276*c2c66affSColin Finck 
2277*c2c66affSColin Finck     /* If we had a buffer, free it, then return status */
2278*c2c66affSColin Finck     if (Buffer) ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM);
2279*c2c66affSColin Finck     return Status;
2280*c2c66affSColin Finck }
2281*c2c66affSColin Finck 
2282*c2c66affSColin Finck /* PUBLIC FUNCTIONS **********************************************************/
2283*c2c66affSColin Finck 
2284*c2c66affSColin Finck /*
2285*c2c66affSColin Finck  * @implemented
2286*c2c66affSColin Finck  */
2287*c2c66affSColin Finck VOID
2288*c2c66affSColin Finck FASTCALL
2289*c2c66affSColin Finck HalExamineMBR(IN PDEVICE_OBJECT DeviceObject,
2290*c2c66affSColin Finck               IN ULONG SectorSize,
2291*c2c66affSColin Finck               IN ULONG MbrTypeIdentifier,
2292*c2c66affSColin Finck               OUT PVOID *MbrBuffer)
2293*c2c66affSColin Finck {
2294*c2c66affSColin Finck     HALDISPATCH->HalExamineMBR(DeviceObject,
2295*c2c66affSColin Finck                                SectorSize,
2296*c2c66affSColin Finck                                MbrTypeIdentifier,
2297*c2c66affSColin Finck                                MbrBuffer);
2298*c2c66affSColin Finck }
2299*c2c66affSColin Finck 
2300*c2c66affSColin Finck /*
2301*c2c66affSColin Finck  * @implemented
2302*c2c66affSColin Finck  */
2303*c2c66affSColin Finck NTSTATUS
2304*c2c66affSColin Finck FASTCALL
2305*c2c66affSColin Finck IoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject,
2306*c2c66affSColin Finck                      IN ULONG SectorSize,
2307*c2c66affSColin Finck                      IN BOOLEAN ReturnRecognizedPartitions,
2308*c2c66affSColin Finck                      IN OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
2309*c2c66affSColin Finck {
2310*c2c66affSColin Finck     return HALDISPATCH->HalIoReadPartitionTable(DeviceObject,
2311*c2c66affSColin Finck                                                 SectorSize,
2312*c2c66affSColin Finck                                                 ReturnRecognizedPartitions,
2313*c2c66affSColin Finck                                                 PartitionBuffer);
2314*c2c66affSColin Finck }
2315*c2c66affSColin Finck 
2316*c2c66affSColin Finck /*
2317*c2c66affSColin Finck  * @implemented
2318*c2c66affSColin Finck  */
2319*c2c66affSColin Finck NTSTATUS
2320*c2c66affSColin Finck FASTCALL
2321*c2c66affSColin Finck IoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject,
2322*c2c66affSColin Finck                           IN ULONG SectorSize,
2323*c2c66affSColin Finck                           IN ULONG PartitionNumber,
2324*c2c66affSColin Finck                           IN ULONG PartitionType)
2325*c2c66affSColin Finck {
2326*c2c66affSColin Finck     return HALDISPATCH->HalIoSetPartitionInformation(DeviceObject,
2327*c2c66affSColin Finck                                                      SectorSize,
2328*c2c66affSColin Finck                                                      PartitionNumber,
2329*c2c66affSColin Finck                                                      PartitionType);
2330*c2c66affSColin Finck }
2331*c2c66affSColin Finck 
2332*c2c66affSColin Finck /*
2333*c2c66affSColin Finck  * @implemented
2334*c2c66affSColin Finck  */
2335*c2c66affSColin Finck NTSTATUS
2336*c2c66affSColin Finck FASTCALL
2337*c2c66affSColin Finck IoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject,
2338*c2c66affSColin Finck                       IN ULONG SectorSize,
2339*c2c66affSColin Finck                       IN ULONG SectorsPerTrack,
2340*c2c66affSColin Finck                       IN ULONG NumberOfHeads,
2341*c2c66affSColin Finck                       IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
2342*c2c66affSColin Finck {
2343*c2c66affSColin Finck     return HALDISPATCH->HalIoWritePartitionTable(DeviceObject,
2344*c2c66affSColin Finck                                                  SectorSize,
2345*c2c66affSColin Finck                                                  SectorsPerTrack,
2346*c2c66affSColin Finck                                                  NumberOfHeads,
2347*c2c66affSColin Finck                                                  PartitionBuffer);
2348*c2c66affSColin Finck }
2349*c2c66affSColin Finck 
2350*c2c66affSColin Finck /*
2351*c2c66affSColin Finck  * @implemented
2352*c2c66affSColin Finck  */
2353*c2c66affSColin Finck VOID
2354*c2c66affSColin Finck FASTCALL
2355*c2c66affSColin Finck IoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
2356*c2c66affSColin Finck                      IN PSTRING NtDeviceName,
2357*c2c66affSColin Finck                      OUT PUCHAR NtSystemPath,
2358*c2c66affSColin Finck                      OUT PSTRING NtSystemPathString)
2359*c2c66affSColin Finck {
2360*c2c66affSColin Finck     HALDISPATCH->HalIoAssignDriveLetters(LoaderBlock,
2361*c2c66affSColin Finck                                          NtDeviceName,
2362*c2c66affSColin Finck                                          NtSystemPath,
2363*c2c66affSColin Finck                                          NtSystemPathString);
2364*c2c66affSColin Finck }
2365*c2c66affSColin Finck 
2366*c2c66affSColin Finck /* EOF */
2367