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