2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/fstub/disksup.c
5 * PURPOSE: I/O HAL Routines for Disk Access
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
8 * Casper S. Hornstrup (chorns@users.sourceforge.net)
11 /* INCLUDES ******************************************************************/
16 #include <internal/hal.h>
18 /* DEPRECATED FUNCTIONS ******************************************************/
21 const WCHAR DiskMountString
[] = L
"\\DosDevices\\%C:";
23 #define AUTO_DRIVE MAXULONG
25 #define PARTITION_MAGIC 0xaa55
27 #define EFI_PMBR_OSTYPE_EFI 0xEE
31 typedef struct _REG_DISK_MOUNT_INFO
34 LARGE_INTEGER StartingOffset
;
35 } REG_DISK_MOUNT_INFO
, *PREG_DISK_MOUNT_INFO
;
39 typedef enum _DISK_MANAGER
47 HalpAssignDrive(IN PUNICODE_STRING PartitionName
,
51 IN LARGE_INTEGER StartingOffset
,
53 IN PUNICODE_STRING BootDevice
,
54 OUT PUCHAR NtSystemPath
)
56 WCHAR DriveNameBuffer
[16];
57 UNICODE_STRING DriveName
;
60 REG_DISK_MOUNT_INFO DiskMountInfo
;
62 DPRINT("HalpAssignDrive()\n");
64 if ((DriveNumber
!= AUTO_DRIVE
) && (DriveNumber
< 26))
66 /* Force assignment */
67 KeAcquireGuardedMutex(&ObpDeviceMapLock
);
68 if ((ObSystemDeviceMap
->DriveMap
& (1 << DriveNumber
)) != 0)
70 DbgPrint("Drive letter already used!\n");
71 KeReleaseGuardedMutex(&ObpDeviceMapLock
);
74 KeReleaseGuardedMutex(&ObpDeviceMapLock
);
78 /* Automatic assignment */
79 DriveNumber
= AUTO_DRIVE
;
80 KeAcquireGuardedMutex(&ObpDeviceMapLock
);
81 for (i
= 2; i
< 26; i
++)
83 if ((ObSystemDeviceMap
->DriveMap
& (1 << i
)) == 0)
89 KeReleaseGuardedMutex(&ObpDeviceMapLock
);
91 if (DriveNumber
== AUTO_DRIVE
)
93 DbgPrint("No drive letter available!\n");
98 DPRINT("DriveNumber %lu\n", DriveNumber
);
100 /* Build drive name */
101 swprintf(DriveNameBuffer
,
104 RtlInitUnicodeString(&DriveName
,
107 DPRINT(" %wZ ==> %wZ\n",
111 /* Create symbolic link */
112 Status
= IoCreateSymbolicLink(&DriveName
,
116 DriveType
== DOSDEVICE_DRIVE_FIXED
&&
119 DiskMountInfo
.Signature
= Signature
;
120 DiskMountInfo
.StartingOffset
= StartingOffset
;
121 swprintf(DriveNameBuffer
, DiskMountString
, L
'A' + DriveNumber
);
122 RtlInitUnicodeString(&DriveName
, DriveNameBuffer
);
124 Status
= ZwSetValueKey(hKey
,
129 sizeof(DiskMountInfo
));
130 if (!NT_SUCCESS(Status
))
132 DPRINT1("ZwCreateValueKey failed for %wZ, status=%x\n", &DriveName
, Status
);
136 /* Check if this is a boot partition */
137 if (RtlCompareUnicodeString(PartitionName
, BootDevice
, FALSE
) == 0)
139 /* Set NtSystemPath to that partition's disk letter */
140 *NtSystemPath
= (UCHAR
)('A' + DriveNumber
);
147 xHalpGetRDiskCount(VOID
)
150 UNICODE_STRING ArcName
;
151 PWCHAR ArcNameBuffer
;
152 OBJECT_ATTRIBUTES ObjectAttributes
;
153 HANDLE DirectoryHandle
;
154 POBJECT_DIRECTORY_INFORMATION DirectoryInfo
;
159 BOOLEAN First
= TRUE
;
162 DirectoryInfo
= ExAllocatePoolWithTag(PagedPool
, 2 * PAGE_SIZE
, TAG_FILE_SYSTEM
);
163 if (DirectoryInfo
== NULL
)
168 RtlInitUnicodeString(&ArcName
, L
"\\ArcName");
169 InitializeObjectAttributes(&ObjectAttributes
,
175 Status
= ZwOpenDirectoryObject (&DirectoryHandle
,
176 SYMBOLIC_LINK_ALL_ACCESS
,
178 if (!NT_SUCCESS(Status
))
180 DPRINT1("ZwOpenDirectoryObject for %wZ failed, status=%lx\n", &ArcName
, Status
);
181 ExFreePoolWithTag(DirectoryInfo
, TAG_FILE_SYSTEM
);
187 while (NT_SUCCESS(Status
))
189 Status
= NtQueryDirectoryObject (DirectoryHandle
,
197 if (NT_SUCCESS(Status
))
200 while (DirectoryInfo
[Count
].Name
.Buffer
)
202 DPRINT("Count %x\n", Count
);
203 DirectoryInfo
[Count
].Name
.Buffer
[DirectoryInfo
[Count
].Name
.Length
/ sizeof(WCHAR
)] = 0;
204 ArcNameBuffer
= DirectoryInfo
[Count
].Name
.Buffer
;
205 if (DirectoryInfo
[Count
].Name
.Length
>= sizeof(L
"multi(0)disk(0)rdisk(0)") - sizeof(WCHAR
) &&
206 !_wcsnicmp(ArcNameBuffer
, L
"multi(0)disk(0)rdisk(", (sizeof(L
"multi(0)disk(0)rdisk(") - sizeof(WCHAR
)) / sizeof(WCHAR
)))
208 DPRINT("%S\n", ArcNameBuffer
);
209 ArcNameBuffer
+= (sizeof(L
"multi(0)disk(0)rdisk(") - sizeof(WCHAR
)) / sizeof(WCHAR
);
211 while (iswdigit(*ArcNameBuffer
))
213 CurrentRDisk
= CurrentRDisk
* 10 + *ArcNameBuffer
- L
'0';
216 if (!_wcsicmp(ArcNameBuffer
, L
")") &&
217 CurrentRDisk
>= RDiskCount
)
219 RDiskCount
= CurrentRDisk
+ 1;
226 ExFreePoolWithTag(DirectoryInfo
, TAG_FILE_SYSTEM
);
231 xHalpGetDiskNumberFromRDisk(ULONG RDisk
, PULONG DiskNumber
)
233 WCHAR NameBuffer
[80];
234 UNICODE_STRING ArcName
;
235 UNICODE_STRING LinkName
;
236 OBJECT_ATTRIBUTES ObjectAttributes
;
241 L
"\\ArcName\\multi(0)disk(0)rdisk(%lu)",
244 RtlInitUnicodeString(&ArcName
, NameBuffer
);
245 InitializeObjectAttributes(&ObjectAttributes
,
250 Status
= ZwOpenSymbolicLinkObject(&LinkHandle
,
251 SYMBOLIC_LINK_ALL_ACCESS
,
253 if (!NT_SUCCESS(Status
))
255 DPRINT1("ZwOpenSymbolicLinkObject failed for %wZ, status=%lx\n", &ArcName
, Status
);
259 LinkName
.Buffer
= NameBuffer
;
261 LinkName
.MaximumLength
= sizeof(NameBuffer
);
262 Status
= ZwQuerySymbolicLinkObject(LinkHandle
,
266 if (!NT_SUCCESS(Status
))
268 DPRINT1("ZwQuerySymbolicLinkObject failed, status=%lx\n", Status
);
271 if (LinkName
.Length
< sizeof(L
"\\Device\\Harddisk0\\Partition0") - sizeof(WCHAR
) ||
272 LinkName
.Length
>= sizeof(NameBuffer
))
274 return STATUS_UNSUCCESSFUL
;
277 NameBuffer
[LinkName
.Length
/ sizeof(WCHAR
)] = 0;
278 if (_wcsnicmp(NameBuffer
, L
"\\Device\\Harddisk", (sizeof(L
"\\Device\\Harddisk") - sizeof(WCHAR
)) / sizeof(WCHAR
)))
280 return STATUS_UNSUCCESSFUL
;
282 LinkName
.Buffer
+= (sizeof(L
"\\Device\\Harddisk") - sizeof(WCHAR
)) / sizeof(WCHAR
);
284 if (!iswdigit(*LinkName
.Buffer
))
286 return STATUS_UNSUCCESSFUL
;
289 while (iswdigit(*LinkName
.Buffer
))
291 *DiskNumber
= *DiskNumber
* 10 + *LinkName
.Buffer
- L
'0';
294 if (_wcsicmp(LinkName
.Buffer
, L
"\\Partition0"))
296 return STATUS_UNSUCCESSFUL
;
298 return STATUS_SUCCESS
;
303 xHalQueryDriveLayout(IN PUNICODE_STRING DeviceName
,
304 OUT PDRIVE_LAYOUT_INFORMATION
*LayoutInfo
)
306 IO_STATUS_BLOCK StatusBlock
;
307 DISK_GEOMETRY DiskGeometry
;
308 PDEVICE_OBJECT DeviceObject
= NULL
;
309 PFILE_OBJECT FileObject
;
314 DPRINT("xHalpQueryDriveLayout %wZ %p\n",
318 /* Get the drives sector size */
319 Status
= IoGetDeviceObjectPointer(DeviceName
,
320 FILE_READ_ATTRIBUTES
,
323 if (!NT_SUCCESS(Status
))
325 DPRINT("Status %x\n", Status
);
329 KeInitializeEvent(&Event
,
333 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
338 sizeof(DISK_GEOMETRY
),
344 ObDereferenceObject(FileObject
);
345 return(STATUS_INSUFFICIENT_RESOURCES
);
348 Status
= IoCallDriver(DeviceObject
,
350 if (Status
== STATUS_PENDING
)
352 KeWaitForSingleObject(&Event
,
357 Status
= StatusBlock
.Status
;
359 if (!NT_SUCCESS(Status
))
361 if (DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
363 DiskGeometry
.BytesPerSector
= 512;
367 ObDereferenceObject(FileObject
);
372 DPRINT("DiskGeometry.BytesPerSector: %lu\n",
373 DiskGeometry
.BytesPerSector
);
375 if (DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
377 PDRIVE_LAYOUT_INFORMATION Buffer
;
379 /* Allocate a partition list for a single entry. */
380 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
381 sizeof(DRIVE_LAYOUT_INFORMATION
), TAG_FILE_SYSTEM
);
384 RtlZeroMemory(Buffer
,
385 sizeof(DRIVE_LAYOUT_INFORMATION
));
386 Buffer
->PartitionCount
= 1;
387 *LayoutInfo
= Buffer
;
389 Status
= STATUS_SUCCESS
;
393 Status
= STATUS_UNSUCCESSFUL
;
398 /* Read the partition table */
399 Status
= IoReadPartitionTable(DeviceObject
,
400 DiskGeometry
.BytesPerSector
,
405 ObDereferenceObject(FileObject
);
412 xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
413 IN PSTRING NtDeviceName
,
414 OUT PUCHAR NtSystemPath
,
415 OUT PSTRING NtSystemPathString
)
417 PDRIVE_LAYOUT_INFORMATION
*LayoutArray
;
418 PCONFIGURATION_INFORMATION ConfigInfo
;
419 OBJECT_ATTRIBUTES ObjectAttributes
;
420 IO_STATUS_BLOCK StatusBlock
;
421 UNICODE_STRING UnicodeString1
;
422 UNICODE_STRING UnicodeString2
;
432 PKEY_VALUE_PARTIAL_INFORMATION PartialInformation
;
433 PREG_DISK_MOUNT_INFO DiskMountInfo
;
435 UNICODE_STRING BootDevice
;
437 Status
= RtlAnsiStringToUnicodeString(&BootDevice
,
441 DPRINT("xHalIoAssignDriveLetters()\n");
443 ConfigInfo
= IoGetConfigurationInformation();
445 RDiskCount
= xHalpGetRDiskCount();
447 DPRINT("RDiskCount %lu\n", RDiskCount
);
449 Buffer1
= ExAllocatePoolWithTag(PagedPool
,
452 if (!Buffer1
) return;
454 Buffer2
= ExAllocatePoolWithTag(PagedPool
,
459 ExFreePoolWithTag(Buffer1
, TAG_FILE_SYSTEM
);
463 PartialInformation
= ExAllocatePoolWithTag(PagedPool
,
464 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(REG_DISK_MOUNT_INFO
),
466 if (!PartialInformation
)
468 ExFreePoolWithTag(Buffer2
, TAG_FILE_SYSTEM
);
469 ExFreePoolWithTag(Buffer1
, TAG_FILE_SYSTEM
);
473 DiskMountInfo
= (PREG_DISK_MOUNT_INFO
) PartialInformation
->Data
;
475 /* Create or open the 'MountedDevices' key */
476 RtlInitUnicodeString(&UnicodeString1
, L
"\\Registry\\Machine\\SYSTEM\\MountedDevices");
477 InitializeObjectAttributes(&ObjectAttributes
,
479 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
482 Status
= ZwCreateKey(&hKey
,
487 REG_OPTION_NON_VOLATILE
,
489 if (!NT_SUCCESS(Status
))
492 DPRINT("ZwCreateKey failed for %wZ, status=%x\n", &UnicodeString1
, Status
);
495 /* Create PhysicalDrive links */
496 DPRINT("Physical disk drives: %lu\n", ConfigInfo
->DiskCount
);
497 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
499 swprintf(Buffer1
, L
"\\Device\\Harddisk%lu\\Partition0", i
);
500 RtlInitUnicodeString(&UnicodeString1
, Buffer1
);
502 InitializeObjectAttributes(&ObjectAttributes
,
508 Status
= ZwOpenFile(&FileHandle
,
509 FILE_READ_DATA
| SYNCHRONIZE
,
513 FILE_SYNCHRONOUS_IO_NONALERT
);
514 if (NT_SUCCESS(Status
))
518 swprintf(Buffer2
, L
"\\??\\PhysicalDrive%lu", i
);
519 RtlInitUnicodeString(&UnicodeString2
, Buffer2
);
521 DPRINT("Creating link: %S ==> %S\n",
525 IoCreateSymbolicLink(&UnicodeString2
,
530 /* Initialize layout array */
531 if (ConfigInfo
->DiskCount
== 0)
532 goto end_assign_disks
;
533 LayoutArray
= ExAllocatePoolWithTag(NonPagedPool
,
534 ConfigInfo
->DiskCount
* sizeof(PDRIVE_LAYOUT_INFORMATION
), TAG_FILE_SYSTEM
);
537 ExFreePoolWithTag(PartialInformation
, TAG_FILE_SYSTEM
);
538 ExFreePoolWithTag(Buffer2
, TAG_FILE_SYSTEM
);
539 ExFreePoolWithTag(Buffer1
, TAG_FILE_SYSTEM
);
540 if (hKey
) ObCloseHandle(hKey
, KernelMode
);
544 RtlZeroMemory(LayoutArray
,
545 ConfigInfo
->DiskCount
* sizeof(PDRIVE_LAYOUT_INFORMATION
));
546 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
548 swprintf(Buffer1
, L
"\\Device\\Harddisk%lu\\Partition0", i
);
549 RtlInitUnicodeString(&UnicodeString1
, Buffer1
);
551 Status
= xHalQueryDriveLayout(&UnicodeString1
, &LayoutArray
[i
]);
552 if (!NT_SUCCESS(Status
))
554 DbgPrint("xHalQueryDriveLayout() failed (Status = 0x%lx)\n",
556 LayoutArray
[i
] = NULL
;
559 /* We don't use the RewritePartition value while mounting the disks.
560 * We use this value for marking pre-assigned (registry) partitions.
562 for (j
= 0; j
< LayoutArray
[i
]->PartitionCount
; j
++)
564 LayoutArray
[i
]->PartitionEntry
[j
].RewritePartition
= FALSE
;
569 /* Dump layout array */
570 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
572 DPRINT("Harddisk %d:\n",
575 if (LayoutArray
[i
] == NULL
)
578 DPRINT("Logical partitions: %d\n",
579 LayoutArray
[i
]->PartitionCount
);
581 for (j
= 0; j
< LayoutArray
[i
]->PartitionCount
; j
++)
583 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%I64u count:%I64u\n",
585 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
,
586 LayoutArray
[i
]->PartitionEntry
[j
].BootIndicator
,
587 LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
,
588 LayoutArray
[i
]->PartitionEntry
[j
].StartingOffset
.QuadPart
,
589 LayoutArray
[i
]->PartitionEntry
[j
].PartitionLength
.QuadPart
);
594 /* Assign pre-assigned (registry) partitions */
597 for (k
= 2; k
< 26; k
++)
599 swprintf(Buffer1
, DiskMountString
, L
'A' + k
);
600 RtlInitUnicodeString(&UnicodeString1
, Buffer1
);
601 Status
= ZwQueryValueKey(hKey
,
603 KeyValuePartialInformation
,
605 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(REG_DISK_MOUNT_INFO
),
607 if (NT_SUCCESS(Status
) &&
608 PartialInformation
->Type
== REG_BINARY
&&
609 PartialInformation
->DataLength
== sizeof(REG_DISK_MOUNT_INFO
))
611 DPRINT("%wZ => %08x:%08x%08x\n", &UnicodeString1
, DiskMountInfo
->Signature
,
612 DiskMountInfo
->StartingOffset
.u
.HighPart
, DiskMountInfo
->StartingOffset
.u
.LowPart
);
614 BOOLEAN Found
= FALSE
;
615 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
617 DPRINT("%x\n", LayoutArray
[i
]->Signature
);
618 if (LayoutArray
[i
] &&
619 LayoutArray
[i
]->Signature
&&
620 LayoutArray
[i
]->Signature
== DiskMountInfo
->Signature
)
622 for (j
= 0; j
< LayoutArray
[i
]->PartitionCount
; j
++)
624 if (LayoutArray
[i
]->PartitionEntry
[j
].StartingOffset
.QuadPart
== DiskMountInfo
->StartingOffset
.QuadPart
)
626 if (IsRecognizedPartition(LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
) &&
627 LayoutArray
[i
]->PartitionEntry
[j
].RewritePartition
== FALSE
)
630 L
"\\Device\\Harddisk%lu\\Partition%lu",
632 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
);
633 RtlInitUnicodeString(&UnicodeString2
, Buffer2
);
636 DPRINT(" %wZ\n", &UnicodeString2
);
637 Found
= HalpAssignDrive(&UnicodeString2
,
639 DOSDEVICE_DRIVE_FIXED
,
640 DiskMountInfo
->Signature
,
641 DiskMountInfo
->StartingOffset
,
645 /* Mark the partition as assigned */
646 LayoutArray
[i
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
655 /* We didn't find a partition for this entry, remove them. */
656 Status
= ZwDeleteValueKey(hKey
, &UnicodeString1
);
663 /* Assign bootable partition on first harddisk */
664 DPRINT("Assigning bootable primary partition on first harddisk:\n");
667 Status
= xHalpGetDiskNumberFromRDisk(0, &DiskNumber
);
668 if (NT_SUCCESS(Status
) &&
669 DiskNumber
< ConfigInfo
->DiskCount
&&
670 LayoutArray
[DiskNumber
])
672 /* Search for bootable partition */
673 for (j
= 0; j
< NUM_PARTITION_TABLE_ENTRIES
&& j
< LayoutArray
[DiskNumber
]->PartitionCount
; j
++)
675 if ((LayoutArray
[DiskNumber
]->PartitionEntry
[j
].BootIndicator
== TRUE
) &&
676 IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
))
678 if (LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
)
681 L
"\\Device\\Harddisk%lu\\Partition%lu",
683 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
684 RtlInitUnicodeString(&UnicodeString2
, Buffer2
);
687 DPRINT(" %wZ\n", &UnicodeString2
);
688 HalpAssignDrive(&UnicodeString2
,
690 DOSDEVICE_DRIVE_FIXED
,
691 LayoutArray
[DiskNumber
]->Signature
,
692 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
696 /* Mark the partition as assigned */
697 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
705 /* Assign remaining primary partitions */
706 DPRINT("Assigning remaining primary partitions:\n");
707 for (RDisk
= 0; RDisk
< RDiskCount
; RDisk
++)
709 Status
= xHalpGetDiskNumberFromRDisk(RDisk
, &DiskNumber
);
710 if (NT_SUCCESS(Status
) &&
711 DiskNumber
< ConfigInfo
->DiskCount
&&
712 LayoutArray
[DiskNumber
])
714 /* Search for primary partitions */
715 for (j
= 0; (j
< NUM_PARTITION_TABLE_ENTRIES
) && (j
< LayoutArray
[DiskNumber
]->PartitionCount
); j
++)
717 if (LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
&&
718 IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
))
721 L
"\\Device\\Harddisk%lu\\Partition%lu",
723 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
724 RtlInitUnicodeString(&UnicodeString2
, Buffer2
);
729 HalpAssignDrive(&UnicodeString2
,
731 DOSDEVICE_DRIVE_FIXED
,
732 LayoutArray
[DiskNumber
]->Signature
,
733 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
737 /* Mark the partition as assigned */
738 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
744 /* Assign extended (logical) partitions */
745 DPRINT("Assigning extended (logical) partitions:\n");
746 for (RDisk
= 0; RDisk
< RDiskCount
; RDisk
++)
748 Status
= xHalpGetDiskNumberFromRDisk(RDisk
, &DiskNumber
);
749 if (NT_SUCCESS(Status
) &&
750 DiskNumber
< ConfigInfo
->DiskCount
&&
751 LayoutArray
[DiskNumber
])
753 /* Search for extended partitions */
754 for (j
= NUM_PARTITION_TABLE_ENTRIES
; j
< LayoutArray
[DiskNumber
]->PartitionCount
; j
++)
756 if (IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
) &&
757 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
&&
758 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
!= 0)
761 L
"\\Device\\Harddisk%lu\\Partition%lu",
763 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
764 RtlInitUnicodeString(&UnicodeString2
, Buffer2
);
769 HalpAssignDrive(&UnicodeString2
,
771 DOSDEVICE_DRIVE_FIXED
,
772 LayoutArray
[DiskNumber
]->Signature
,
773 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
777 /* Mark the partition as assigned */
778 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
784 /* Assign remaining primary partitions without an arc-name */
785 DPRINT("Assigning remaining primary partitions:\n");
786 for (DiskNumber
= 0; DiskNumber
< ConfigInfo
->DiskCount
; DiskNumber
++)
788 if (LayoutArray
[DiskNumber
])
790 /* Search for primary partitions */
791 for (j
= 0; (j
< NUM_PARTITION_TABLE_ENTRIES
) && (j
< LayoutArray
[DiskNumber
]->PartitionCount
); j
++)
793 if (LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
&&
794 IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
))
797 L
"\\Device\\Harddisk%lu\\Partition%lu",
799 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
800 RtlInitUnicodeString(&UnicodeString2
, Buffer2
);
805 HalpAssignDrive(&UnicodeString2
,
807 DOSDEVICE_DRIVE_FIXED
,
808 LayoutArray
[DiskNumber
]->Signature
,
809 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
813 /* Mark the partition as assigned */
814 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
820 /* Assign extended (logical) partitions without an arc-name */
821 DPRINT("Assigning extended (logical) partitions:\n");
822 for (DiskNumber
= 0; DiskNumber
< ConfigInfo
->DiskCount
; DiskNumber
++)
824 if (LayoutArray
[DiskNumber
])
826 /* Search for extended partitions */
827 for (j
= NUM_PARTITION_TABLE_ENTRIES
; j
< LayoutArray
[DiskNumber
]->PartitionCount
; j
++)
829 if (IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
) &&
830 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
&&
831 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
!= 0)
834 L
"\\Device\\Harddisk%lu\\Partition%lu",
836 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
837 RtlInitUnicodeString(&UnicodeString2
, Buffer2
);
842 HalpAssignDrive(&UnicodeString2
,
844 DOSDEVICE_DRIVE_FIXED
,
845 LayoutArray
[DiskNumber
]->Signature
,
846 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
850 /* Mark the partition as assigned */
851 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
857 /* Assign removable disk drives */
858 DPRINT("Assigning removable disk drives:\n");
859 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
863 /* Search for virtual partitions */
864 if (LayoutArray
[i
]->PartitionCount
== 1 &&
865 LayoutArray
[i
]->PartitionEntry
[0].PartitionType
== 0)
867 swprintf(Buffer2
, L
"\\Device\\Harddisk%lu\\Partition1", i
);
868 RtlInitUnicodeString(&UnicodeString2
, Buffer2
);
873 HalpAssignDrive(&UnicodeString2
,
875 DOSDEVICE_DRIVE_REMOVABLE
,
877 RtlConvertLongToLargeInteger(0),
885 /* Free layout array */
886 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
888 if (LayoutArray
[i
] != NULL
)
889 ExFreePoolWithTag(LayoutArray
[i
], TAG_FILE_SYSTEM
);
891 ExFreePoolWithTag(LayoutArray
, TAG_FILE_SYSTEM
);
894 /* Assign floppy drives */
895 DPRINT("Floppy drives: %lu\n", ConfigInfo
->FloppyCount
);
896 for (i
= 0; i
< ConfigInfo
->FloppyCount
; i
++)
898 swprintf(Buffer1
, L
"\\Device\\Floppy%lu", i
);
899 RtlInitUnicodeString(&UnicodeString1
, Buffer1
);
901 /* Assign drive letters A: or B: or first free drive letter */
904 HalpAssignDrive(&UnicodeString1
,
905 (i
< 2) ? i
: AUTO_DRIVE
,
906 DOSDEVICE_DRIVE_REMOVABLE
,
908 RtlConvertLongToLargeInteger(0),
914 /* Assign cdrom drives */
915 DPRINT("CD-Rom drives: %lu\n", ConfigInfo
->CdRomCount
);
916 for (i
= 0; i
< ConfigInfo
->CdRomCount
; i
++)
918 swprintf(Buffer1
, L
"\\Device\\CdRom%lu", i
);
919 RtlInitUnicodeString(&UnicodeString1
, Buffer1
);
921 /* Assign first free drive letter */
922 DPRINT(" %wZ\n", &UnicodeString1
);
923 HalpAssignDrive(&UnicodeString1
,
925 DOSDEVICE_DRIVE_CDROM
,
927 RtlConvertLongToLargeInteger(0),
933 /* Anything else to do? */
935 ExFreePoolWithTag(PartialInformation
, TAG_FILE_SYSTEM
);
936 ExFreePoolWithTag(Buffer2
, TAG_FILE_SYSTEM
);
937 ExFreePoolWithTag(Buffer1
, TAG_FILE_SYSTEM
);
938 if (hKey
) ObCloseHandle(hKey
, KernelMode
);
943 /* PRIVATE FUNCTIONS *********************************************************/
947 HalpGetFullGeometry(IN PDEVICE_OBJECT DeviceObject
,
948 IN PDISK_GEOMETRY Geometry
,
949 OUT PULONGLONG RealSectorCount
)
952 IO_STATUS_BLOCK IoStatusBlock
;
955 PARTITION_INFORMATION PartitionInfo
;
958 /* Allocate a non-paged event */
959 Event
= ExAllocatePoolWithTag(NonPagedPool
,
962 if (!Event
) return STATUS_INSUFFICIENT_RESOURCES
;
965 KeInitializeEvent(Event
, NotificationEvent
, FALSE
);
968 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
973 sizeof(DISK_GEOMETRY
),
979 /* Fail, free the event */
980 ExFreePoolWithTag(Event
, TAG_FILE_SYSTEM
);
981 return STATUS_INSUFFICIENT_RESOURCES
;
984 /* Call the driver and check if it's pending */
985 Status
= IoCallDriver(DeviceObject
, Irp
);
986 if (Status
== STATUS_PENDING
)
988 /* Wait on the driver */
989 KeWaitForSingleObject(Event
, Executive
, KernelMode
, FALSE
, NULL
);
990 Status
= IoStatusBlock
.Status
;
993 /* Check if the driver returned success */
994 if(NT_SUCCESS(Status
))
996 /* Build another IRP */
997 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO
,
1002 sizeof(PARTITION_INFORMATION
),
1008 /* Fail, free the event */
1009 ExFreePoolWithTag(Event
, TAG_FILE_SYSTEM
);
1010 return STATUS_INSUFFICIENT_RESOURCES
;
1013 /* Call the driver and check if it's pending */
1014 Status
= IoCallDriver(DeviceObject
, Irp
);
1015 if (Status
== STATUS_PENDING
)
1017 /* Wait on the driver */
1018 KeWaitForSingleObject(Event
, Executive
, KernelMode
, FALSE
, NULL
);
1019 Status
= IoStatusBlock
.Status
;
1022 /* Check if the driver returned success */
1023 if(NT_SUCCESS(Status
))
1025 /* Get the number of sectors */
1026 *RealSectorCount
= (PartitionInfo
.PartitionLength
.QuadPart
/
1027 Geometry
->BytesPerSector
);
1031 /* Free the event and return the Status */
1032 ExFreePoolWithTag(Event
, TAG_FILE_SYSTEM
);
1038 HalpIsValidPartitionEntry(IN PPARTITION_DESCRIPTOR Entry
,
1039 IN ULONGLONG MaxOffset
,
1040 IN ULONGLONG MaxSector
)
1042 ULONGLONG EndingSector
;
1045 /* Unused partitions are considered valid */
1046 if (Entry
->PartitionType
== PARTITION_ENTRY_UNUSED
) return TRUE
;
1048 /* Get the last sector of the partition */
1049 EndingSector
= GET_STARTING_SECTOR(Entry
) + GET_PARTITION_LENGTH(Entry
);
1051 /* Check if it's more then the maximum sector */
1052 if (EndingSector
> MaxSector
)
1054 /* Invalid partition */
1055 DPRINT1("FSTUB: entry is invalid\n");
1056 DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry
));
1057 DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry
));
1058 DPRINT1("FSTUB: end %#I64x\n", EndingSector
);
1059 DPRINT1("FSTUB: max %#I64x\n", MaxSector
);
1062 else if(GET_STARTING_SECTOR(Entry
) > MaxOffset
)
1064 /* Invalid partition */
1065 DPRINT1("FSTUB: entry is invalid\n");
1066 DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry
));
1067 DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry
));
1068 DPRINT1("FSTUB: end %#I64x\n", EndingSector
);
1069 DPRINT1("FSTUB: maxOffset %#I64x\n", MaxOffset
);
1073 /* It's fine, return success */
1079 HalpCalculateChsValues(IN PLARGE_INTEGER PartitionOffset
,
1080 IN PLARGE_INTEGER PartitionLength
,
1081 IN CCHAR ShiftCount
,
1082 IN ULONG SectorsPerTrack
,
1083 IN ULONG NumberOfTracks
,
1084 IN ULONG ConventionalCylinders
,
1085 OUT PPARTITION_DESCRIPTOR PartitionDescriptor
)
1087 LARGE_INTEGER FirstSector
, SectorCount
;
1088 ULONG LastSector
, Remainder
, SectorsPerCylinder
;
1089 ULONG StartingCylinder
, EndingCylinder
;
1090 ULONG StartingTrack
, EndingTrack
;
1091 ULONG StartingSector
, EndingSector
;
1094 /* Calculate the number of sectors for each cylinder */
1095 SectorsPerCylinder
= SectorsPerTrack
* NumberOfTracks
;
1097 /* Calculate the first sector, and the sector count */
1098 FirstSector
.QuadPart
= PartitionOffset
->QuadPart
>> ShiftCount
;
1099 SectorCount
.QuadPart
= PartitionLength
->QuadPart
>> ShiftCount
;
1101 /* Now calculate the last sector */
1102 LastSector
= FirstSector
.LowPart
+ SectorCount
.LowPart
- 1;
1104 /* Calculate the first and last cylinders */
1105 StartingCylinder
= FirstSector
.LowPart
/ SectorsPerCylinder
;
1106 EndingCylinder
= LastSector
/ SectorsPerCylinder
;
1108 /* Set the default number of cylinders */
1109 if (!ConventionalCylinders
) ConventionalCylinders
= 1024;
1111 /* Normalize the values */
1112 if (StartingCylinder
>= ConventionalCylinders
)
1114 /* Set the maximum to 1023 */
1115 StartingCylinder
= ConventionalCylinders
- 1;
1117 if (EndingCylinder
>= ConventionalCylinders
)
1119 /* Set the maximum to 1023 */
1120 EndingCylinder
= ConventionalCylinders
- 1;
1123 /* Calculate the starting head and sector that still remain */
1124 Remainder
= FirstSector
.LowPart
% SectorsPerCylinder
;
1125 StartingTrack
= Remainder
/ SectorsPerTrack
;
1126 StartingSector
= Remainder
% SectorsPerTrack
;
1128 /* Calculate the ending head and sector that still remain */
1129 Remainder
= LastSector
% SectorsPerCylinder
;
1130 EndingTrack
= Remainder
/ SectorsPerTrack
;
1131 EndingSector
= Remainder
% SectorsPerTrack
;
1133 /* Set cylinder data for the MSB */
1134 PartitionDescriptor
->StartingCylinderMsb
= (UCHAR
)StartingCylinder
;
1135 PartitionDescriptor
->EndingCylinderMsb
= (UCHAR
)EndingCylinder
;
1137 /* Set the track data */
1138 PartitionDescriptor
->StartingTrack
= (UCHAR
)StartingTrack
;
1139 PartitionDescriptor
->EndingTrack
= (UCHAR
)EndingTrack
;
1141 /* Update cylinder data for the LSB */
1142 StartingCylinder
= ((StartingSector
+ 1) & 0x3F) |
1143 ((StartingCylinder
>> 2) & 0xC0);
1144 EndingCylinder
= ((EndingSector
+ 1) & 0x3F) |
1145 ((EndingCylinder
>> 2) & 0xC0);
1147 /* Set the cylinder data for the LSB */
1148 PartitionDescriptor
->StartingCylinderLsb
= (UCHAR
)StartingCylinder
;
1149 PartitionDescriptor
->EndingCylinderLsb
= (UCHAR
)EndingCylinder
;
1154 xHalGetPartialGeometry(IN PDEVICE_OBJECT DeviceObject
,
1155 IN PULONG ConventionalCylinders
,
1156 IN PLONGLONG DiskSize
)
1158 PDISK_GEOMETRY DiskGeometry
= NULL
;
1159 PIO_STATUS_BLOCK IoStatusBlock
= NULL
;
1160 PKEVENT Event
= NULL
;
1165 *ConventionalCylinders
= 0;
1168 /* Allocate the structure in nonpaged pool */
1169 DiskGeometry
= ExAllocatePoolWithTag(NonPagedPool
,
1170 sizeof(DISK_GEOMETRY
),
1172 if (!DiskGeometry
) goto Cleanup
;
1174 /* Allocate the status block in nonpaged pool */
1175 IoStatusBlock
= ExAllocatePoolWithTag(NonPagedPool
,
1176 sizeof(IO_STATUS_BLOCK
),
1178 if (!IoStatusBlock
) goto Cleanup
;
1180 /* Allocate the event in nonpaged pool too */
1181 Event
= ExAllocatePoolWithTag(NonPagedPool
,
1184 if (!Event
) goto Cleanup
;
1186 /* Initialize the event */
1187 KeInitializeEvent(Event
, NotificationEvent
, FALSE
);
1190 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
1195 sizeof(DISK_GEOMETRY
),
1199 if (!Irp
) goto Cleanup
;
1201 /* Now call the driver */
1202 Status
= IoCallDriver(DeviceObject
, Irp
);
1203 if (Status
== STATUS_PENDING
)
1205 /* Wait for it to complete */
1206 KeWaitForSingleObject(Event
, Executive
, KernelMode
, FALSE
, NULL
);
1207 Status
= IoStatusBlock
->Status
;
1210 /* Check driver status */
1211 if (NT_SUCCESS(Status
))
1213 /* Return the cylinder count */
1214 *ConventionalCylinders
= DiskGeometry
->Cylinders
.LowPart
;
1216 /* Make sure it's not larger then 1024 */
1217 if (DiskGeometry
->Cylinders
.LowPart
>= 1024)
1219 /* Otherwise, normalize the value */
1220 *ConventionalCylinders
= 1024;
1223 /* Calculate the disk size */
1224 *DiskSize
= DiskGeometry
->Cylinders
.QuadPart
*
1225 DiskGeometry
->TracksPerCylinder
*
1226 DiskGeometry
->SectorsPerTrack
*
1227 DiskGeometry
->BytesPerSector
;
1231 /* Free all the pointers */
1232 if (Event
) ExFreePoolWithTag(Event
, TAG_FILE_SYSTEM
);
1233 if (IoStatusBlock
) ExFreePoolWithTag(IoStatusBlock
, TAG_FILE_SYSTEM
);
1234 if (DiskGeometry
) ExFreePoolWithTag(DiskGeometry
, TAG_FILE_SYSTEM
);
1240 xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject
,
1241 IN ULONG SectorSize
,
1242 IN ULONG MbrTypeIdentifier
,
1243 OUT PVOID
*MbrBuffer
)
1245 LARGE_INTEGER Offset
;
1249 IO_STATUS_BLOCK IoStatusBlock
;
1251 PPARTITION_DESCRIPTOR PartitionDescriptor
;
1253 PIO_STACK_LOCATION IoStackLocation
;
1254 Offset
.QuadPart
= 0;
1256 /* Assume failure */
1259 /* Normalize the buffer size */
1260 BufferSize
= max(SectorSize
, 512);
1262 /* Allocate the buffer */
1263 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
1264 PAGE_SIZE
> BufferSize
?
1265 PAGE_SIZE
: BufferSize
,
1267 if (!Buffer
) return;
1269 /* Initialize the Event */
1270 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1273 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
1283 ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
1287 /* Make sure to override volume verification */
1288 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
1289 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
1291 /* Call the driver */
1292 Status
= IoCallDriver(DeviceObject
, Irp
);
1293 if (Status
== STATUS_PENDING
)
1295 /* Wait for completion */
1296 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1297 Status
= IoStatusBlock
.Status
;
1300 /* Check driver Status */
1301 if (NT_SUCCESS(Status
))
1303 /* Validate the MBR Signature */
1304 if (((PUSHORT
)Buffer
)[BOOT_SIGNATURE_OFFSET
] != BOOT_RECORD_SIGNATURE
)
1307 ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
1311 /* Get the partition entry */
1312 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1313 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1315 /* Make sure it's what the caller wanted */
1316 if (PartitionDescriptor
->PartitionType
!= MbrTypeIdentifier
)
1318 /* It's not, free our buffer */
1319 ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
1323 /* Check if this is a secondary entry */
1324 if (PartitionDescriptor
->PartitionType
== 0x54)
1326 /* Return our buffer, but at sector 63 */
1327 *(PULONG
)Buffer
= 63;
1328 *MbrBuffer
= Buffer
;
1330 else if (PartitionDescriptor
->PartitionType
== 0x55)
1332 /* EZ Drive, return the buffer directly */
1333 *MbrBuffer
= Buffer
;
1337 /* Otherwise crash on debug builds */
1338 ASSERT(PartitionDescriptor
->PartitionType
== 0x55);
1346 FstubFixupEfiPartition(IN PPARTITION_DESCRIPTOR PartitionDescriptor
,
1347 IN ULONGLONG MaxOffset
)
1349 ULONG PartitionMaxOffset
, PartitionLength
;
1352 /* Compute partition length (according to MBR entry) */
1353 PartitionMaxOffset
= GET_STARTING_SECTOR(PartitionDescriptor
) + GET_PARTITION_LENGTH(PartitionDescriptor
);
1354 /* In case the partition length goes beyond disk size... */
1355 if (PartitionMaxOffset
> MaxOffset
)
1357 /* Resize partition to its maximum real length */
1358 PartitionLength
= (ULONG
)(PartitionMaxOffset
- GET_STARTING_SECTOR(PartitionDescriptor
));
1359 SET_PARTITION_LENGTH(PartitionDescriptor
, PartitionLength
);
1365 xHalIoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject
,
1366 IN ULONG SectorSize
,
1367 IN BOOLEAN ReturnRecognizedPartitions
,
1368 IN OUT PDRIVE_LAYOUT_INFORMATION
*PartitionBuffer
)
1371 IO_STATUS_BLOCK IoStatusBlock
;
1373 PPARTITION_DESCRIPTOR PartitionDescriptor
;
1376 PPARTITION_INFORMATION PartitionInfo
;
1377 PUCHAR Buffer
= NULL
;
1378 ULONG BufferSize
= 2048, InputSize
;
1379 PDRIVE_LAYOUT_INFORMATION DriveLayoutInfo
= NULL
;
1380 LONG j
= -1, i
= -1, k
;
1381 DISK_GEOMETRY DiskGeometry
;
1382 LONGLONG EndSector
, MaxSector
, StartOffset
;
1383 ULONGLONG MaxOffset
;
1384 LARGE_INTEGER Offset
, VolumeOffset
;
1385 BOOLEAN IsPrimary
= TRUE
, IsEzDrive
= FALSE
, MbrFound
= FALSE
;
1386 BOOLEAN IsValid
, IsEmpty
= TRUE
;
1388 PIO_STACK_LOCATION IoStackLocation
;
1389 PBOOT_SECTOR_INFO BootSectorInfo
= (PBOOT_SECTOR_INFO
)Buffer
;
1390 UCHAR PartitionType
;
1391 LARGE_INTEGER HiddenSectors64
;
1392 VolumeOffset
.QuadPart
= Offset
.QuadPart
= 0;
1395 /* Allocate the buffer */
1396 *PartitionBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1399 if (!(*PartitionBuffer
)) return STATUS_INSUFFICIENT_RESOURCES
;
1401 /* Normalize the buffer size */
1402 InputSize
= max(512, SectorSize
);
1404 /* Check for EZ Drive */
1405 HalExamineMBR(DeviceObject
, InputSize
, 0x55, &MbrBuffer
);
1408 /* EZ Drive found, bias the offset */
1410 ExFreePoolWithTag(MbrBuffer
, TAG_FILE_SYSTEM
);
1411 Offset
.QuadPart
= 512;
1414 /* Get drive geometry */
1415 Status
= HalpGetFullGeometry(DeviceObject
, &DiskGeometry
, &MaxOffset
);
1416 if (!NT_SUCCESS(Status
))
1418 ExFreePoolWithTag(*PartitionBuffer
, TAG_FILE_SYSTEM
);
1419 *PartitionBuffer
= NULL
;
1423 /* Get the end and maximum sector */
1424 EndSector
= MaxOffset
;
1425 MaxSector
= MaxOffset
<< 1;
1426 DPRINT("FSTUB: MaxOffset = %#I64x, MaxSector = %#I64x\n",
1427 MaxOffset
, MaxSector
);
1429 /* Allocate our buffer */
1430 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, InputSize
, TAG_FILE_SYSTEM
);
1433 /* Fail, free the input buffer */
1434 ExFreePoolWithTag(*PartitionBuffer
, TAG_FILE_SYSTEM
);
1435 *PartitionBuffer
= NULL
;
1436 return STATUS_INSUFFICIENT_RESOURCES
;
1439 /* Start partition loop */
1442 /* Assume the partition is valid */
1445 /* Initialize the event */
1446 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1448 /* Clear the buffer and build the IRP */
1449 RtlZeroMemory(Buffer
, InputSize
);
1450 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
1460 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1464 /* Make sure to disable volume verification */
1465 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
1466 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
1468 /* Call the driver */
1469 Status
= IoCallDriver(DeviceObject
, Irp
);
1470 if (Status
== STATUS_PENDING
)
1472 /* Wait for completion */
1473 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1474 Status
= IoStatusBlock
.Status
;
1477 /* Normalize status code and check for failure */
1478 if (Status
== STATUS_NO_DATA_DETECTED
) Status
= STATUS_SUCCESS
;
1479 if (!NT_SUCCESS(Status
)) break;
1481 /* If we biased for EZ-Drive, unbias now */
1482 if (IsEzDrive
&& (Offset
.QuadPart
== 512)) Offset
.QuadPart
= 0;
1484 /* Make sure this is a valid MBR */
1485 if (((PUSHORT
)Buffer
)[BOOT_SIGNATURE_OFFSET
] != BOOT_RECORD_SIGNATURE
)
1487 /* It's not, fail */
1488 DPRINT1("FSTUB: (IoReadPartitionTable) No 0xaa55 found in "
1489 "partition table %d\n", j
+ 1);
1493 /* At this point we have a valid MBR */
1496 /* Check if we weren't given an offset */
1497 if (!Offset
.QuadPart
)
1499 /* Then read the signature off the disk */
1500 (*PartitionBuffer
)->Signature
= ((PULONG
)Buffer
)
1501 [PARTITION_TABLE_OFFSET
/ 2 - 1];
1504 /* Get the partition descriptor array */
1505 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1506 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1508 /* Start looping partitions */
1510 DPRINT("FSTUB: Partition Table %d:\n", j
);
1511 for (Entry
= 1, k
= 0; Entry
<= 4; Entry
++, PartitionDescriptor
++)
1513 /* Get the partition type */
1514 PartitionType
= PartitionDescriptor
->PartitionType
;
1516 /* Print debug messages */
1517 DPRINT("Partition Entry %d,%d: type %#x %s\n",
1521 (PartitionDescriptor
->ActiveFlag
) ? "Active" : "");
1522 DPRINT("\tOffset %#08lx for %#08lx Sectors\n",
1523 GET_STARTING_SECTOR(PartitionDescriptor
),
1524 GET_PARTITION_LENGTH(PartitionDescriptor
));
1526 /* Check whether we're facing a protective MBR */
1527 if (PartitionType
== EFI_PMBR_OSTYPE_EFI
)
1529 /* Partition length might be bigger than disk size */
1530 FstubFixupEfiPartition(PartitionDescriptor
,
1534 /* Make sure that the partition is valid, unless it's the first */
1535 if (!(HalpIsValidPartitionEntry(PartitionDescriptor
,
1537 MaxSector
)) && !(j
))
1539 /* It's invalid, so fail */
1544 /* Check if it's a container */
1545 if (IsContainerPartition(PartitionType
))
1547 /* Increase the count of containers */
1550 /* More then one table is invalid */
1551 DPRINT1("FSTUB: Multiple container partitions found in "
1552 "partition table %d\n - table is invalid\n",
1559 /* Check if the partition is supposedly empty */
1562 /* But check if it actually has a start and/or length */
1563 if ((GET_STARTING_SECTOR(PartitionDescriptor
)) ||
1564 (GET_PARTITION_LENGTH(PartitionDescriptor
)))
1566 /* So then it's not really empty */
1571 /* Check if the caller wanted only recognized partitions */
1572 if (ReturnRecognizedPartitions
)
1574 /* Then check if this one is unused, or a container */
1575 if ((PartitionType
== PARTITION_ENTRY_UNUSED
) ||
1576 IsContainerPartition(PartitionType
))
1578 /* Skip it, since the caller doesn't want it */
1583 /* Increase the structure count and check if they can fit */
1584 if ((sizeof(DRIVE_LAYOUT_INFORMATION
) +
1585 (++i
* sizeof(PARTITION_INFORMATION
))) >
1588 /* Allocate a new buffer that's twice as big */
1589 DriveLayoutInfo
= ExAllocatePoolWithTag(NonPagedPool
,
1592 if (!DriveLayoutInfo
)
1594 /* Out of memory, unto this extra structure */
1596 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1600 /* Copy the contents of the old buffer */
1601 RtlMoveMemory(DriveLayoutInfo
,
1605 /* Free the old buffer and set this one as the new one */
1606 ExFreePoolWithTag(*PartitionBuffer
, TAG_FILE_SYSTEM
);
1607 *PartitionBuffer
= DriveLayoutInfo
;
1609 /* Double the size */
1613 /* Now get the current structure being filled and initialize it */
1614 PartitionInfo
= &(*PartitionBuffer
)->PartitionEntry
[i
];
1615 PartitionInfo
->PartitionType
= PartitionType
;
1616 PartitionInfo
->RewritePartition
= FALSE
;
1618 /* Check if we're dealing with a partition that's in use */
1619 if (PartitionType
!= PARTITION_ENTRY_UNUSED
)
1621 /* Check if it's bootable */
1622 PartitionInfo
->BootIndicator
= PartitionDescriptor
->
1626 /* Check if its' a container */
1627 if (IsContainerPartition(PartitionType
))
1629 /* Then don't recognize it and use the volume offset */
1630 PartitionInfo
->RecognizedPartition
= FALSE
;
1631 StartOffset
= VolumeOffset
.QuadPart
;
1635 /* Then recognize it and use the partition offset */
1636 PartitionInfo
->RecognizedPartition
= TRUE
;
1637 StartOffset
= Offset
.QuadPart
;
1640 /* Get the starting offset */
1641 PartitionInfo
->StartingOffset
.QuadPart
=
1643 UInt32x32To64(GET_STARTING_SECTOR(PartitionDescriptor
),
1646 /* Calculate the number of hidden sectors */
1647 HiddenSectors64
.QuadPart
= (PartitionInfo
->
1648 StartingOffset
.QuadPart
-
1651 PartitionInfo
->HiddenSectors
= HiddenSectors64
.LowPart
;
1653 /* Get the partition length */
1654 PartitionInfo
->PartitionLength
.QuadPart
=
1655 UInt32x32To64(GET_PARTITION_LENGTH(PartitionDescriptor
),
1658 // BUGBUGBUG: The correct partition numbers seem to cause boot failures!!!
1659 // PartitionInfo->PartitionNumber = (!IsContainerPartition(PartitionType)) ? i : 0;
1660 PartitionInfo
->PartitionNumber
= i
+ 1;
1664 /* Otherwise, clear all the relevant fields */
1665 PartitionInfo
->BootIndicator
= FALSE
;
1666 PartitionInfo
->RecognizedPartition
= FALSE
;
1667 PartitionInfo
->StartingOffset
.QuadPart
= 0;
1668 PartitionInfo
->PartitionLength
.QuadPart
= 0;
1669 PartitionInfo
->HiddenSectors
= 0;
1671 PartitionInfo
->PartitionNumber
= 0;
1675 /* Finish debug log, and check for failure */
1677 if (!NT_SUCCESS(Status
)) break;
1679 /* Also check if we hit an invalid entry here */
1682 /* We did, so break out of the loop minus one entry */
1687 /* Reset the offset */
1688 Offset
.QuadPart
= 0;
1690 /* Go back to the descriptor array and loop it */
1691 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1692 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1693 for (Entry
= 1; Entry
<= 4; Entry
++, PartitionDescriptor
++)
1695 /* Check if this is a container partition, since we skipped them */
1696 if (IsContainerPartition(PartitionDescriptor
->PartitionType
))
1698 /* Get its offset */
1699 Offset
.QuadPart
= VolumeOffset
.QuadPart
+
1701 GET_STARTING_SECTOR(PartitionDescriptor
),
1704 /* If this is a primary partition, this is the volume offset */
1705 if (IsPrimary
) VolumeOffset
= Offset
;
1707 /* Also update the maximum sector */
1708 MaxSector
= GET_PARTITION_LENGTH(PartitionDescriptor
);
1709 DPRINT1("FSTUB: MaxSector now = %I64d\n", MaxSector
);
1714 /* Loop the next partitions, which are not primary anymore */
1716 } while (Offset
.HighPart
| Offset
.LowPart
);
1718 /* Check if this is a removable device that's probably a super-floppy */
1719 if ((DiskGeometry
.MediaType
== RemovableMedia
) &&
1724 /* Read the jump bytes to detect super-floppy */
1725 if ((BootSectorInfo
->JumpByte
[0] == 0xeb) ||
1726 (BootSectorInfo
->JumpByte
[0] == 0xe9))
1728 /* Super floppes don't have typical MBRs, so skip them */
1729 DPRINT1("FSTUB: Jump byte %#x found along with empty partition "
1730 "table - disk is a super floppy and has no valid MBR\n",
1731 BootSectorInfo
->JumpByte
);
1736 /* Check if we're still at partition -1 */
1739 /* The likely cause is the super floppy detection above */
1740 if ((MbrFound
) || (DiskGeometry
.MediaType
== RemovableMedia
))
1742 /* Print out debugging information */
1743 DPRINT1("FSTUB: Drive %#p has no valid MBR. Make it into a "
1746 DPRINT1("FSTUB: Drive has %I64d sectors and is %#016I64x "
1748 EndSector
, EndSector
* DiskGeometry
.BytesPerSector
);
1750 /* We should at least have some sectors */
1753 /* Get the entry we'll use */
1754 PartitionInfo
= &(*PartitionBuffer
)->PartitionEntry
[0];
1756 /* Fill it out with data for a super-floppy */
1757 PartitionInfo
->RewritePartition
= FALSE
;
1758 PartitionInfo
->RecognizedPartition
= TRUE
;
1759 PartitionInfo
->PartitionType
= PARTITION_FAT_16
;
1760 PartitionInfo
->BootIndicator
= FALSE
;
1761 PartitionInfo
->HiddenSectors
= 0;
1762 PartitionInfo
->StartingOffset
.QuadPart
= 0;
1763 PartitionInfo
->PartitionLength
.QuadPart
= (EndSector
*
1767 /* FIXME: REACTOS HACK */
1768 PartitionInfo
->PartitionNumber
= 0;
1770 /* Set the signature and set the count back to 0 */
1771 (*PartitionBuffer
)->Signature
= 1;
1777 /* Otherwise, this isn't a super floppy, so set an invalid count */
1782 /* Set the partition count */
1783 (*PartitionBuffer
)->PartitionCount
= ++i
;
1785 /* If we have no count, delete the signature */
1786 if (!i
) (*PartitionBuffer
)->Signature
= 0;
1788 /* Free the buffer and check for success */
1789 if (Buffer
) ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
1790 if (!NT_SUCCESS(Status
))
1792 ExFreePoolWithTag(*PartitionBuffer
, TAG_FILE_SYSTEM
);
1793 *PartitionBuffer
= NULL
;
1802 xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject
,
1803 IN ULONG SectorSize
,
1804 IN ULONG PartitionNumber
,
1805 IN ULONG PartitionType
)
1809 IO_STATUS_BLOCK IoStatusBlock
;
1811 LARGE_INTEGER Offset
, VolumeOffset
;
1812 PUCHAR Buffer
= NULL
;
1816 PPARTITION_DESCRIPTOR PartitionDescriptor
;
1817 BOOLEAN IsPrimary
= TRUE
, IsEzDrive
= FALSE
;
1819 PIO_STACK_LOCATION IoStackLocation
;
1820 VolumeOffset
.QuadPart
= Offset
.QuadPart
= 0;
1823 /* Normalize the buffer size */
1824 BufferSize
= max(512, SectorSize
);
1826 /* Check for EZ Drive */
1827 HalExamineMBR(DeviceObject
, BufferSize
, 0x55, &MbrBuffer
);
1830 /* EZ Drive found, bias the offset */
1832 ExFreePoolWithTag(MbrBuffer
, TAG_FILE_SYSTEM
);
1833 Offset
.QuadPart
= 512;
1836 /* Allocate our partition buffer */
1837 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, PAGE_SIZE
, TAG_FILE_SYSTEM
);
1838 if (!Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
1840 /* Initialize the event we'll use and loop partitions */
1841 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1844 /* Reset the event since we reuse it */
1845 KeResetEvent(&Event
);
1847 /* Build the read IRP */
1848 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
1858 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1862 /* Make sure to disable volume verification */
1863 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
1864 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
1866 /* Call the driver */
1867 Status
= IoCallDriver(DeviceObject
, Irp
);
1868 if (Status
== STATUS_PENDING
)
1870 /* Wait for completion */
1871 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1872 Status
= IoStatusBlock
.Status
;
1875 /* Check for failure */
1876 if (!NT_SUCCESS(Status
)) break;
1878 /* If we biased for EZ-Drive, unbias now */
1879 if (IsEzDrive
&& (Offset
.QuadPart
== 512)) Offset
.QuadPart
= 0;
1881 /* Make sure this is a valid MBR */
1882 if (((PUSHORT
)Buffer
)[BOOT_SIGNATURE_OFFSET
] != BOOT_RECORD_SIGNATURE
)
1884 /* It's not, fail */
1885 Status
= STATUS_BAD_MASTER_BOOT_RECORD
;
1889 /* Get the partition descriptors and loop them */
1890 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1891 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1892 for (Entry
= 1; Entry
<= 4; Entry
++, PartitionDescriptor
++)
1894 /* Check if it's unused or a container partition */
1895 if ((PartitionDescriptor
->PartitionType
==
1896 PARTITION_ENTRY_UNUSED
) ||
1897 (IsContainerPartition(PartitionDescriptor
->PartitionType
)))
1899 /* Go to the next one */
1903 /* It's a valid partition, so increase the partition count */
1904 if (++i
== PartitionNumber
)
1906 /* We found a match, set the type */
1907 PartitionDescriptor
->PartitionType
= (UCHAR
)PartitionType
;
1909 /* Reset the reusable event */
1910 KeResetEvent(&Event
);
1912 /* Build the write IRP */
1913 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
1923 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1927 /* Disable volume verification */
1928 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
1929 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
1931 /* Call the driver */
1932 Status
= IoCallDriver(DeviceObject
, Irp
);
1933 if (Status
== STATUS_PENDING
)
1935 /* Wait for completion */
1936 KeWaitForSingleObject(&Event
,
1941 Status
= IoStatusBlock
.Status
;
1944 /* We're done, break out of the loop */
1949 /* If we looped all the partitions, break out */
1950 if (Entry
<= NUM_PARTITION_TABLE_ENTRIES
) break;
1952 /* Nothing found yet, get the partition array again */
1953 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1954 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1955 for (Entry
= 1; Entry
<= 4; Entry
++, PartitionDescriptor
++)
1957 /* Check if this was a container partition (we skipped these) */
1958 if (IsContainerPartition(PartitionDescriptor
->PartitionType
))
1960 /* Update the partition offset */
1961 Offset
.QuadPart
= VolumeOffset
.QuadPart
+
1962 GET_STARTING_SECTOR(PartitionDescriptor
) *
1965 /* If this was the primary partition, update the volume too */
1966 if (IsPrimary
) VolumeOffset
= Offset
;
1971 /* Check if we already searched all the partitions */
1972 if (Entry
> NUM_PARTITION_TABLE_ENTRIES
)
1974 /* Then we failed to find a good MBR */
1975 Status
= STATUS_BAD_MASTER_BOOT_RECORD
;
1979 /* Loop the next partitions, which are not primary anymore */
1981 } while (i
< PartitionNumber
);
1983 /* Everything done, cleanup */
1984 if (Buffer
) ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
1990 xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject
,
1991 IN ULONG SectorSize
,
1992 IN ULONG SectorsPerTrack
,
1993 IN ULONG NumberOfHeads
,
1994 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer
)
1997 IO_STATUS_BLOCK IoStatusBlock
;
1999 NTSTATUS Status
= STATUS_SUCCESS
;
2003 PPARTITION_TABLE PartitionTable
;
2004 LARGE_INTEGER Offset
, NextOffset
, ExtendedOffset
, SectorOffset
;
2005 LARGE_INTEGER StartOffset
, PartitionLength
;
2008 BOOLEAN IsEzDrive
= FALSE
, IsSuperFloppy
= FALSE
, DoRewrite
= FALSE
, IsMbr
;
2009 ULONG ConventionalCylinders
;
2011 PDISK_LAYOUT DiskLayout
= (PDISK_LAYOUT
)PartitionBuffer
;
2013 UCHAR PartitionType
;
2014 PIO_STACK_LOCATION IoStackLocation
;
2015 PPARTITION_INFORMATION PartitionInfo
= PartitionBuffer
->PartitionEntry
;
2016 PPARTITION_INFORMATION TableEntry
;
2017 ExtendedOffset
.QuadPart
= NextOffset
.QuadPart
= Offset
.QuadPart
= 0;
2020 /* Normalize the buffer size */
2021 BufferSize
= max(512, SectorSize
);
2023 /* Get the partial drive geometry */
2024 xHalGetPartialGeometry(DeviceObject
, &ConventionalCylinders
, &DiskSize
);
2026 /* Check for EZ Drive */
2027 HalExamineMBR(DeviceObject
, BufferSize
, 0x55, &MbrBuffer
);
2030 /* EZ Drive found, bias the offset */
2032 ExFreePoolWithTag(MbrBuffer
, TAG_FILE_SYSTEM
);
2033 Offset
.QuadPart
= 512;
2036 /* Get the number of bits to shift to multiply by the sector size */
2037 for (k
= 0; k
< 32; k
++) if ((SectorSize
>> k
) == 1) break;
2039 /* Check if there's only one partition */
2040 if (PartitionBuffer
->PartitionCount
== 1)
2042 /* Check if it has no starting offset or hidden sectors */
2043 if (!(PartitionInfo
->StartingOffset
.QuadPart
) &&
2044 !(PartitionInfo
->HiddenSectors
))
2046 /* Then it's a super floppy */
2047 IsSuperFloppy
= TRUE
;
2049 /* Which also means it must be non-bootable FAT-16 */
2050 if ((PartitionInfo
->PartitionNumber
) ||
2051 (PartitionInfo
->PartitionType
!= PARTITION_FAT_16
) ||
2052 (PartitionInfo
->BootIndicator
))
2054 /* It's not, so we fail */
2055 return STATUS_INVALID_PARAMETER
;
2058 /* Check if it needs a rewrite, and disable EZ drive for sure */
2059 if (PartitionInfo
->RewritePartition
) DoRewrite
= TRUE
;
2064 /* Count the number of partition tables */
2065 DiskLayout
->TableCount
= (PartitionBuffer
->PartitionCount
+ 4 - 1) / 4;
2067 /* Allocate our partition buffer */
2068 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, PAGE_SIZE
, TAG_FILE_SYSTEM
);
2069 if (!Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
2071 /* Loop the entries */
2072 Entry
= (PPTE
)&Buffer
[PARTITION_TABLE_OFFSET
];
2073 for (i
= 0; i
< DiskLayout
->TableCount
; i
++)
2075 /* Set if this is the MBR partition */
2078 /* Initialize th event */
2079 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
2081 /* Build the read IRP */
2082 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
2092 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2096 /* Make sure to disable volume verification */
2097 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
2098 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
2100 /* Call the driver */
2101 Status
= IoCallDriver(DeviceObject
, Irp
);
2102 if (Status
== STATUS_PENDING
)
2104 /* Wait for completion */
2105 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
2106 Status
= IoStatusBlock
.Status
;
2109 /* Check for failure */
2110 if (!NT_SUCCESS(Status
)) break;
2112 /* If we biased for EZ-Drive, unbias now */
2113 if (IsEzDrive
&& (Offset
.QuadPart
== 512)) Offset
.QuadPart
= 0;
2115 /* Check if this is a normal disk */
2118 /* Set the boot record signature */
2119 Buffer
[BOOT_SIGNATURE_OFFSET
] = BOOT_RECORD_SIGNATURE
;
2121 /* By default, don't require a rewrite */
2124 /* Check if we don't have an offset */
2125 if (!Offset
.QuadPart
)
2127 /* Check if the signature doesn't match */
2128 if (((PULONG
)Buffer
)[PARTITION_TABLE_OFFSET
/ 2 - 1] !=
2129 PartitionBuffer
->Signature
)
2131 /* Then write the signature and now w need a rewrite */
2132 ((PULONG
)Buffer
)[PARTITION_TABLE_OFFSET
/ 2 - 1] =
2133 PartitionBuffer
->Signature
;
2138 /* Loop the partition table entries */
2139 PartitionTable
= &DiskLayout
->PartitionTable
[i
];
2140 for (j
= 0; j
< 4; j
++)
2142 /* Get the current entry and type */
2143 TableEntry
= &PartitionTable
->PartitionEntry
[j
];
2144 PartitionType
= TableEntry
->PartitionType
;
2146 /* Check if the entry needs a rewrite */
2147 if (TableEntry
->RewritePartition
)
2149 /* Then we need one too */
2152 /* Save the type and if it's a bootable partition */
2153 Entry
[j
].PartitionType
= TableEntry
->PartitionType
;
2154 Entry
[j
].ActiveFlag
= TableEntry
->BootIndicator
? 0x80 : 0;
2156 /* Make sure it's used */
2157 if (PartitionType
!= PARTITION_ENTRY_UNUSED
)
2159 /* Make sure it's not a container (unless primary) */
2160 if ((IsMbr
) || !(IsContainerPartition(PartitionType
)))
2162 /* Use the partition offset */
2163 StartOffset
.QuadPart
= Offset
.QuadPart
;
2167 /* Use the extended logical partition offset */
2168 StartOffset
.QuadPart
= ExtendedOffset
.QuadPart
;
2171 /* Set the sector offset */
2172 SectorOffset
.QuadPart
= TableEntry
->
2173 StartingOffset
.QuadPart
-
2174 StartOffset
.QuadPart
;
2176 /* Now calculate the starting sector */
2177 StartOffset
.QuadPart
= SectorOffset
.QuadPart
>> k
;
2178 Entry
[j
].StartingSector
= StartOffset
.LowPart
;
2180 /* As well as the length */
2181 PartitionLength
.QuadPart
= TableEntry
->PartitionLength
.
2183 Entry
[j
].PartitionLength
= PartitionLength
.LowPart
;
2185 /* Calculate the CHS values */
2186 HalpCalculateChsValues(&TableEntry
->StartingOffset
,
2187 &TableEntry
->PartitionLength
,
2191 ConventionalCylinders
,
2192 (PPARTITION_DESCRIPTOR
)
2197 /* Otherwise set up an empty entry */
2198 Entry
[j
].StartingSector
= 0;
2199 Entry
[j
].PartitionLength
= 0;
2200 Entry
[j
].StartingTrack
= 0;
2201 Entry
[j
].EndingTrack
= 0;
2202 Entry
[j
].StartingCylinder
= 0;
2203 Entry
[j
].EndingCylinder
= 0;
2207 /* Check if this is a container partition */
2208 if (IsContainerPartition(PartitionType
))
2210 /* Then update the offset to use */
2211 NextOffset
= TableEntry
->StartingOffset
;
2216 /* Check if we need to write back the buffer */
2219 /* We don't need to do this again */
2222 /* Initialize the event */
2223 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
2225 /* If we unbiased for EZ-Drive, rebias now */
2226 if ((IsEzDrive
) && !(Offset
.QuadPart
)) Offset
.QuadPart
= 512;
2228 /* Build the write IRP */
2229 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
2239 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2243 /* Make sure to disable volume verification */
2244 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
2245 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
2247 /* Call the driver */
2248 Status
= IoCallDriver(DeviceObject
, Irp
);
2249 if (Status
== STATUS_PENDING
)
2251 /* Wait for completion */
2252 KeWaitForSingleObject(&Event
,
2257 Status
= IoStatusBlock
.Status
;
2260 /* Check for failure */
2261 if (!NT_SUCCESS(Status
)) break;
2263 /* If we biased for EZ-Drive, unbias now */
2264 if (IsEzDrive
&& (Offset
.QuadPart
== 512)) Offset
.QuadPart
= 0;
2267 /* Update the partition offset and set the extended offset if needed */
2268 Offset
= NextOffset
;
2269 if (IsMbr
) ExtendedOffset
= NextOffset
;
2272 /* If we had a buffer, free it, then return status */
2273 if (Buffer
) ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
2277 /* PUBLIC FUNCTIONS **********************************************************/
2284 HalExamineMBR(IN PDEVICE_OBJECT DeviceObject
,
2285 IN ULONG SectorSize
,
2286 IN ULONG MbrTypeIdentifier
,
2287 OUT PVOID
*MbrBuffer
)
2289 HALDISPATCH
->HalExamineMBR(DeviceObject
,
2300 IoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject
,
2301 IN ULONG SectorSize
,
2302 IN BOOLEAN ReturnRecognizedPartitions
,
2303 IN OUT PDRIVE_LAYOUT_INFORMATION
*PartitionBuffer
)
2305 return HALDISPATCH
->HalIoReadPartitionTable(DeviceObject
,
2307 ReturnRecognizedPartitions
,
2316 IoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject
,
2317 IN ULONG SectorSize
,
2318 IN ULONG PartitionNumber
,
2319 IN ULONG PartitionType
)
2321 return HALDISPATCH
->HalIoSetPartitionInformation(DeviceObject
,
2332 IoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject
,
2333 IN ULONG SectorSize
,
2334 IN ULONG SectorsPerTrack
,
2335 IN ULONG NumberOfHeads
,
2336 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer
)
2338 return HALDISPATCH
->HalIoWritePartitionTable(DeviceObject
,
2350 IoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
2351 IN PSTRING NtDeviceName
,
2352 OUT PUCHAR NtSystemPath
,
2353 OUT PSTRING NtSystemPathString
)
2355 HALDISPATCH
->HalIoAssignDriveLetters(LoaderBlock
,
2358 NtSystemPathString
);