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 DIRECTORY_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
= ZwQueryDirectoryObject (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;
227 ZwClose(DirectoryHandle
);
229 ExFreePoolWithTag(DirectoryInfo
, TAG_FILE_SYSTEM
);
234 xHalpGetDiskNumberFromRDisk(ULONG RDisk
, PULONG DiskNumber
)
236 WCHAR NameBuffer
[80];
237 UNICODE_STRING ArcName
;
238 UNICODE_STRING LinkName
;
239 OBJECT_ATTRIBUTES ObjectAttributes
;
244 L
"\\ArcName\\multi(0)disk(0)rdisk(%lu)",
247 RtlInitUnicodeString(&ArcName
, NameBuffer
);
248 InitializeObjectAttributes(&ObjectAttributes
,
253 Status
= ZwOpenSymbolicLinkObject(&LinkHandle
,
254 SYMBOLIC_LINK_ALL_ACCESS
,
256 if (!NT_SUCCESS(Status
))
258 DPRINT1("ZwOpenSymbolicLinkObject failed for %wZ, status=%lx\n", &ArcName
, Status
);
262 LinkName
.Buffer
= NameBuffer
;
264 LinkName
.MaximumLength
= sizeof(NameBuffer
);
265 Status
= ZwQuerySymbolicLinkObject(LinkHandle
,
269 if (!NT_SUCCESS(Status
))
271 DPRINT1("ZwQuerySymbolicLinkObject failed, status=%lx\n", Status
);
274 if (LinkName
.Length
< sizeof(L
"\\Device\\Harddisk0\\Partition0") - sizeof(WCHAR
) ||
275 LinkName
.Length
>= sizeof(NameBuffer
))
277 return STATUS_UNSUCCESSFUL
;
280 NameBuffer
[LinkName
.Length
/ sizeof(WCHAR
)] = 0;
281 if (_wcsnicmp(NameBuffer
, L
"\\Device\\Harddisk", (sizeof(L
"\\Device\\Harddisk") - sizeof(WCHAR
)) / sizeof(WCHAR
)))
283 return STATUS_UNSUCCESSFUL
;
285 LinkName
.Buffer
+= (sizeof(L
"\\Device\\Harddisk") - sizeof(WCHAR
)) / sizeof(WCHAR
);
287 if (!iswdigit(*LinkName
.Buffer
))
289 return STATUS_UNSUCCESSFUL
;
292 while (iswdigit(*LinkName
.Buffer
))
294 *DiskNumber
= *DiskNumber
* 10 + *LinkName
.Buffer
- L
'0';
297 if (_wcsicmp(LinkName
.Buffer
, L
"\\Partition0"))
299 return STATUS_UNSUCCESSFUL
;
301 return STATUS_SUCCESS
;
306 xHalQueryDriveLayout(IN PUNICODE_STRING DeviceName
,
307 OUT PDRIVE_LAYOUT_INFORMATION
*LayoutInfo
)
309 IO_STATUS_BLOCK StatusBlock
;
310 DISK_GEOMETRY DiskGeometry
;
311 PDEVICE_OBJECT DeviceObject
= NULL
;
312 PFILE_OBJECT FileObject
;
317 DPRINT("xHalpQueryDriveLayout %wZ %p\n",
321 /* Get the drives sector size */
322 Status
= IoGetDeviceObjectPointer(DeviceName
,
323 FILE_READ_ATTRIBUTES
,
326 if (!NT_SUCCESS(Status
))
328 DPRINT("Status %x\n", Status
);
332 KeInitializeEvent(&Event
,
336 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
341 sizeof(DISK_GEOMETRY
),
347 ObDereferenceObject(FileObject
);
348 return(STATUS_INSUFFICIENT_RESOURCES
);
351 Status
= IoCallDriver(DeviceObject
,
353 if (Status
== STATUS_PENDING
)
355 KeWaitForSingleObject(&Event
,
360 Status
= StatusBlock
.Status
;
362 if (!NT_SUCCESS(Status
))
364 if (DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
366 DiskGeometry
.BytesPerSector
= 512;
370 ObDereferenceObject(FileObject
);
375 DPRINT("DiskGeometry.BytesPerSector: %lu\n",
376 DiskGeometry
.BytesPerSector
);
378 if (DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
380 PDRIVE_LAYOUT_INFORMATION Buffer
;
382 /* Allocate a partition list for a single entry. */
383 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
384 sizeof(DRIVE_LAYOUT_INFORMATION
), TAG_FILE_SYSTEM
);
387 RtlZeroMemory(Buffer
,
388 sizeof(DRIVE_LAYOUT_INFORMATION
));
389 Buffer
->PartitionCount
= 1;
390 *LayoutInfo
= Buffer
;
392 Status
= STATUS_SUCCESS
;
396 Status
= STATUS_UNSUCCESSFUL
;
401 /* Read the partition table */
402 Status
= IoReadPartitionTable(DeviceObject
,
403 DiskGeometry
.BytesPerSector
,
408 ObDereferenceObject(FileObject
);
415 xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
416 IN PSTRING NtDeviceName
,
417 OUT PUCHAR NtSystemPath
,
418 OUT PSTRING NtSystemPathString
)
420 PDRIVE_LAYOUT_INFORMATION
*LayoutArray
;
421 PCONFIGURATION_INFORMATION ConfigInfo
;
422 OBJECT_ATTRIBUTES ObjectAttributes
;
423 IO_STATUS_BLOCK StatusBlock
;
424 UNICODE_STRING UnicodeString1
;
425 UNICODE_STRING UnicodeString2
;
435 PKEY_VALUE_PARTIAL_INFORMATION PartialInformation
;
436 PREG_DISK_MOUNT_INFO DiskMountInfo
;
438 UNICODE_STRING BootDevice
;
440 Status
= RtlAnsiStringToUnicodeString(&BootDevice
,
444 DPRINT("xHalIoAssignDriveLetters()\n");
446 ConfigInfo
= IoGetConfigurationInformation();
448 RDiskCount
= xHalpGetRDiskCount();
450 DPRINT("RDiskCount %lu\n", RDiskCount
);
452 Buffer1
= ExAllocatePoolWithTag(PagedPool
,
455 if (!Buffer1
) return;
457 Buffer2
= ExAllocatePoolWithTag(PagedPool
,
462 ExFreePoolWithTag(Buffer1
, TAG_FILE_SYSTEM
);
466 PartialInformation
= ExAllocatePoolWithTag(PagedPool
,
467 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(REG_DISK_MOUNT_INFO
),
469 if (!PartialInformation
)
471 ExFreePoolWithTag(Buffer2
, TAG_FILE_SYSTEM
);
472 ExFreePoolWithTag(Buffer1
, TAG_FILE_SYSTEM
);
476 DiskMountInfo
= (PREG_DISK_MOUNT_INFO
) PartialInformation
->Data
;
478 /* Create or open the 'MountedDevices' key */
479 RtlInitUnicodeString(&UnicodeString1
, L
"\\Registry\\Machine\\SYSTEM\\MountedDevices");
480 InitializeObjectAttributes(&ObjectAttributes
,
482 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
485 Status
= ZwCreateKey(&hKey
,
490 REG_OPTION_NON_VOLATILE
,
492 if (!NT_SUCCESS(Status
))
495 DPRINT("ZwCreateKey failed for %wZ, status=%x\n", &UnicodeString1
, Status
);
498 /* Create PhysicalDrive links */
499 DPRINT("Physical disk drives: %lu\n", ConfigInfo
->DiskCount
);
500 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
502 swprintf(Buffer1
, L
"\\Device\\Harddisk%lu\\Partition0", i
);
503 RtlInitUnicodeString(&UnicodeString1
, Buffer1
);
505 InitializeObjectAttributes(&ObjectAttributes
,
511 Status
= ZwOpenFile(&FileHandle
,
512 FILE_READ_DATA
| SYNCHRONIZE
,
516 FILE_SYNCHRONOUS_IO_NONALERT
);
517 if (NT_SUCCESS(Status
))
521 swprintf(Buffer2
, L
"\\??\\PhysicalDrive%lu", i
);
522 RtlInitUnicodeString(&UnicodeString2
, Buffer2
);
524 DPRINT("Creating link: %S ==> %S\n",
528 IoCreateSymbolicLink(&UnicodeString2
,
533 /* Initialize layout array */
534 if (ConfigInfo
->DiskCount
== 0)
535 goto end_assign_disks
;
536 LayoutArray
= ExAllocatePoolWithTag(NonPagedPool
,
537 ConfigInfo
->DiskCount
* sizeof(PDRIVE_LAYOUT_INFORMATION
), TAG_FILE_SYSTEM
);
540 ExFreePoolWithTag(PartialInformation
, TAG_FILE_SYSTEM
);
541 ExFreePoolWithTag(Buffer2
, TAG_FILE_SYSTEM
);
542 ExFreePoolWithTag(Buffer1
, TAG_FILE_SYSTEM
);
543 if (hKey
) ObCloseHandle(hKey
, KernelMode
);
547 RtlZeroMemory(LayoutArray
,
548 ConfigInfo
->DiskCount
* sizeof(PDRIVE_LAYOUT_INFORMATION
));
549 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
551 swprintf(Buffer1
, L
"\\Device\\Harddisk%lu\\Partition0", i
);
552 RtlInitUnicodeString(&UnicodeString1
, Buffer1
);
554 Status
= xHalQueryDriveLayout(&UnicodeString1
, &LayoutArray
[i
]);
555 if (!NT_SUCCESS(Status
))
557 DbgPrint("xHalQueryDriveLayout() failed (Status = 0x%lx)\n",
559 LayoutArray
[i
] = NULL
;
562 /* We don't use the RewritePartition value while mounting the disks.
563 * We use this value for marking pre-assigned (registry) partitions.
565 for (j
= 0; j
< LayoutArray
[i
]->PartitionCount
; j
++)
567 LayoutArray
[i
]->PartitionEntry
[j
].RewritePartition
= FALSE
;
572 /* Dump layout array */
573 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
575 DPRINT("Harddisk %d:\n",
578 if (LayoutArray
[i
] == NULL
)
581 DPRINT("Logical partitions: %d\n",
582 LayoutArray
[i
]->PartitionCount
);
584 for (j
= 0; j
< LayoutArray
[i
]->PartitionCount
; j
++)
586 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%I64u count:%I64u\n",
588 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
,
589 LayoutArray
[i
]->PartitionEntry
[j
].BootIndicator
,
590 LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
,
591 LayoutArray
[i
]->PartitionEntry
[j
].StartingOffset
.QuadPart
,
592 LayoutArray
[i
]->PartitionEntry
[j
].PartitionLength
.QuadPart
);
597 /* Assign pre-assigned (registry) partitions */
600 for (k
= 2; k
< 26; k
++)
602 swprintf(Buffer1
, DiskMountString
, L
'A' + k
);
603 RtlInitUnicodeString(&UnicodeString1
, Buffer1
);
604 Status
= ZwQueryValueKey(hKey
,
606 KeyValuePartialInformation
,
608 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(REG_DISK_MOUNT_INFO
),
610 if (NT_SUCCESS(Status
) &&
611 PartialInformation
->Type
== REG_BINARY
&&
612 PartialInformation
->DataLength
== sizeof(REG_DISK_MOUNT_INFO
))
614 DPRINT("%wZ => %08x:%08x%08x\n", &UnicodeString1
, DiskMountInfo
->Signature
,
615 DiskMountInfo
->StartingOffset
.u
.HighPart
, DiskMountInfo
->StartingOffset
.u
.LowPart
);
617 BOOLEAN Found
= FALSE
;
618 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
620 DPRINT("%x\n", LayoutArray
[i
]->Signature
);
621 if (LayoutArray
[i
] &&
622 LayoutArray
[i
]->Signature
&&
623 LayoutArray
[i
]->Signature
== DiskMountInfo
->Signature
)
625 for (j
= 0; j
< LayoutArray
[i
]->PartitionCount
; j
++)
627 if (LayoutArray
[i
]->PartitionEntry
[j
].StartingOffset
.QuadPart
== DiskMountInfo
->StartingOffset
.QuadPart
)
629 if (IsRecognizedPartition(LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
) &&
630 LayoutArray
[i
]->PartitionEntry
[j
].RewritePartition
== FALSE
)
633 L
"\\Device\\Harddisk%lu\\Partition%lu",
635 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
);
636 RtlInitUnicodeString(&UnicodeString2
, Buffer2
);
639 DPRINT(" %wZ\n", &UnicodeString2
);
640 Found
= HalpAssignDrive(&UnicodeString2
,
642 DOSDEVICE_DRIVE_FIXED
,
643 DiskMountInfo
->Signature
,
644 DiskMountInfo
->StartingOffset
,
648 /* Mark the partition as assigned */
649 LayoutArray
[i
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
658 /* We didn't find a partition for this entry, remove them. */
659 Status
= ZwDeleteValueKey(hKey
, &UnicodeString1
);
666 /* Assign bootable partition on first harddisk */
667 DPRINT("Assigning bootable primary partition on first harddisk:\n");
670 Status
= xHalpGetDiskNumberFromRDisk(0, &DiskNumber
);
671 if (NT_SUCCESS(Status
) &&
672 DiskNumber
< ConfigInfo
->DiskCount
&&
673 LayoutArray
[DiskNumber
])
675 /* Search for bootable partition */
676 for (j
= 0; j
< NUM_PARTITION_TABLE_ENTRIES
&& j
< LayoutArray
[DiskNumber
]->PartitionCount
; j
++)
678 if ((LayoutArray
[DiskNumber
]->PartitionEntry
[j
].BootIndicator
!= FALSE
) &&
679 IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
))
681 if (LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
)
684 L
"\\Device\\Harddisk%lu\\Partition%lu",
686 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
687 RtlInitUnicodeString(&UnicodeString2
, Buffer2
);
690 DPRINT(" %wZ\n", &UnicodeString2
);
691 HalpAssignDrive(&UnicodeString2
,
693 DOSDEVICE_DRIVE_FIXED
,
694 LayoutArray
[DiskNumber
]->Signature
,
695 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
699 /* Mark the partition as assigned */
700 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
708 /* Assign remaining primary partitions */
709 DPRINT("Assigning remaining primary partitions:\n");
710 for (RDisk
= 0; RDisk
< RDiskCount
; RDisk
++)
712 Status
= xHalpGetDiskNumberFromRDisk(RDisk
, &DiskNumber
);
713 if (NT_SUCCESS(Status
) &&
714 DiskNumber
< ConfigInfo
->DiskCount
&&
715 LayoutArray
[DiskNumber
])
717 /* Search for primary partitions */
718 for (j
= 0; (j
< NUM_PARTITION_TABLE_ENTRIES
) && (j
< LayoutArray
[DiskNumber
]->PartitionCount
); j
++)
720 if (LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
&&
721 IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
))
724 L
"\\Device\\Harddisk%lu\\Partition%lu",
726 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
727 RtlInitUnicodeString(&UnicodeString2
, Buffer2
);
732 HalpAssignDrive(&UnicodeString2
,
734 DOSDEVICE_DRIVE_FIXED
,
735 LayoutArray
[DiskNumber
]->Signature
,
736 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
740 /* Mark the partition as assigned */
741 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
747 /* Assign extended (logical) partitions */
748 DPRINT("Assigning extended (logical) partitions:\n");
749 for (RDisk
= 0; RDisk
< RDiskCount
; RDisk
++)
751 Status
= xHalpGetDiskNumberFromRDisk(RDisk
, &DiskNumber
);
752 if (NT_SUCCESS(Status
) &&
753 DiskNumber
< ConfigInfo
->DiskCount
&&
754 LayoutArray
[DiskNumber
])
756 /* Search for extended partitions */
757 for (j
= NUM_PARTITION_TABLE_ENTRIES
; j
< LayoutArray
[DiskNumber
]->PartitionCount
; j
++)
759 if (IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
) &&
760 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
&&
761 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
!= 0)
764 L
"\\Device\\Harddisk%lu\\Partition%lu",
766 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
767 RtlInitUnicodeString(&UnicodeString2
, Buffer2
);
772 HalpAssignDrive(&UnicodeString2
,
774 DOSDEVICE_DRIVE_FIXED
,
775 LayoutArray
[DiskNumber
]->Signature
,
776 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
780 /* Mark the partition as assigned */
781 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
787 /* Assign remaining primary partitions without an arc-name */
788 DPRINT("Assigning remaining primary partitions:\n");
789 for (DiskNumber
= 0; DiskNumber
< ConfigInfo
->DiskCount
; DiskNumber
++)
791 if (LayoutArray
[DiskNumber
])
793 /* Search for primary partitions */
794 for (j
= 0; (j
< NUM_PARTITION_TABLE_ENTRIES
) && (j
< LayoutArray
[DiskNumber
]->PartitionCount
); j
++)
796 if (LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
&&
797 IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
))
800 L
"\\Device\\Harddisk%lu\\Partition%lu",
802 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
803 RtlInitUnicodeString(&UnicodeString2
, Buffer2
);
808 HalpAssignDrive(&UnicodeString2
,
810 DOSDEVICE_DRIVE_FIXED
,
811 LayoutArray
[DiskNumber
]->Signature
,
812 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
816 /* Mark the partition as assigned */
817 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
823 /* Assign extended (logical) partitions without an arc-name */
824 DPRINT("Assigning extended (logical) partitions:\n");
825 for (DiskNumber
= 0; DiskNumber
< ConfigInfo
->DiskCount
; DiskNumber
++)
827 if (LayoutArray
[DiskNumber
])
829 /* Search for extended partitions */
830 for (j
= NUM_PARTITION_TABLE_ENTRIES
; j
< LayoutArray
[DiskNumber
]->PartitionCount
; j
++)
832 if (IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
) &&
833 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
&&
834 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
!= 0)
837 L
"\\Device\\Harddisk%lu\\Partition%lu",
839 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
840 RtlInitUnicodeString(&UnicodeString2
, Buffer2
);
845 HalpAssignDrive(&UnicodeString2
,
847 DOSDEVICE_DRIVE_FIXED
,
848 LayoutArray
[DiskNumber
]->Signature
,
849 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
853 /* Mark the partition as assigned */
854 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
860 /* Assign removable disk drives */
861 DPRINT("Assigning removable disk drives:\n");
862 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
866 /* Search for virtual partitions */
867 if (LayoutArray
[i
]->PartitionCount
== 1 &&
868 LayoutArray
[i
]->PartitionEntry
[0].PartitionType
== 0)
870 swprintf(Buffer2
, L
"\\Device\\Harddisk%lu\\Partition1", i
);
871 RtlInitUnicodeString(&UnicodeString2
, Buffer2
);
876 HalpAssignDrive(&UnicodeString2
,
878 DOSDEVICE_DRIVE_REMOVABLE
,
880 RtlConvertLongToLargeInteger(0),
888 /* Free layout array */
889 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
891 if (LayoutArray
[i
] != NULL
)
892 ExFreePoolWithTag(LayoutArray
[i
], TAG_FILE_SYSTEM
);
894 ExFreePoolWithTag(LayoutArray
, TAG_FILE_SYSTEM
);
897 /* Assign floppy drives */
898 DPRINT("Floppy drives: %lu\n", ConfigInfo
->FloppyCount
);
899 for (i
= 0; i
< ConfigInfo
->FloppyCount
; i
++)
901 swprintf(Buffer1
, L
"\\Device\\Floppy%lu", i
);
902 RtlInitUnicodeString(&UnicodeString1
, Buffer1
);
904 /* Assign drive letters A: or B: or first free drive letter */
907 HalpAssignDrive(&UnicodeString1
,
908 (i
< 2) ? i
: AUTO_DRIVE
,
909 DOSDEVICE_DRIVE_REMOVABLE
,
911 RtlConvertLongToLargeInteger(0),
917 /* Assign cdrom drives */
918 DPRINT("CD-Rom drives: %lu\n", ConfigInfo
->CdRomCount
);
919 for (i
= 0; i
< ConfigInfo
->CdRomCount
; i
++)
921 swprintf(Buffer1
, L
"\\Device\\CdRom%lu", i
);
922 RtlInitUnicodeString(&UnicodeString1
, Buffer1
);
924 /* Assign first free drive letter */
925 DPRINT(" %wZ\n", &UnicodeString1
);
926 HalpAssignDrive(&UnicodeString1
,
928 DOSDEVICE_DRIVE_CDROM
,
930 RtlConvertLongToLargeInteger(0),
936 /* Anything else to do? */
938 ExFreePoolWithTag(PartialInformation
, TAG_FILE_SYSTEM
);
939 ExFreePoolWithTag(Buffer2
, TAG_FILE_SYSTEM
);
940 ExFreePoolWithTag(Buffer1
, TAG_FILE_SYSTEM
);
941 if (hKey
) ObCloseHandle(hKey
, KernelMode
);
946 /* PRIVATE FUNCTIONS *********************************************************/
950 HalpGetFullGeometry(IN PDEVICE_OBJECT DeviceObject
,
951 IN PDISK_GEOMETRY Geometry
,
952 OUT PULONGLONG RealSectorCount
)
955 IO_STATUS_BLOCK IoStatusBlock
;
958 PARTITION_INFORMATION PartitionInfo
;
961 /* Allocate a non-paged event */
962 Event
= ExAllocatePoolWithTag(NonPagedPool
,
965 if (!Event
) return STATUS_INSUFFICIENT_RESOURCES
;
968 KeInitializeEvent(Event
, NotificationEvent
, FALSE
);
971 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
976 sizeof(DISK_GEOMETRY
),
982 /* Fail, free the event */
983 ExFreePoolWithTag(Event
, TAG_FILE_SYSTEM
);
984 return STATUS_INSUFFICIENT_RESOURCES
;
987 /* Call the driver and check if it's pending */
988 Status
= IoCallDriver(DeviceObject
, Irp
);
989 if (Status
== STATUS_PENDING
)
991 /* Wait on the driver */
992 KeWaitForSingleObject(Event
, Executive
, KernelMode
, FALSE
, NULL
);
993 Status
= IoStatusBlock
.Status
;
996 /* Check if the driver returned success */
997 if(NT_SUCCESS(Status
))
999 /* Build another IRP */
1000 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO
,
1005 sizeof(PARTITION_INFORMATION
),
1011 /* Fail, free the event */
1012 ExFreePoolWithTag(Event
, TAG_FILE_SYSTEM
);
1013 return STATUS_INSUFFICIENT_RESOURCES
;
1017 KeClearEvent(Event
);
1019 /* Call the driver and check if it's pending */
1020 Status
= IoCallDriver(DeviceObject
, Irp
);
1021 if (Status
== STATUS_PENDING
)
1023 /* Wait on the driver */
1024 KeWaitForSingleObject(Event
, Executive
, KernelMode
, FALSE
, NULL
);
1025 Status
= IoStatusBlock
.Status
;
1028 /* Check if the driver returned success */
1029 if(NT_SUCCESS(Status
))
1031 /* Get the number of sectors */
1032 *RealSectorCount
= (PartitionInfo
.PartitionLength
.QuadPart
/
1033 Geometry
->BytesPerSector
);
1037 /* Free the event and return the Status */
1038 ExFreePoolWithTag(Event
, TAG_FILE_SYSTEM
);
1044 HalpIsValidPartitionEntry(IN PPARTITION_DESCRIPTOR Entry
,
1045 IN ULONGLONG MaxOffset
,
1046 IN ULONGLONG MaxSector
)
1048 ULONGLONG EndingSector
;
1051 /* Unused partitions are considered valid */
1052 if (Entry
->PartitionType
== PARTITION_ENTRY_UNUSED
) return TRUE
;
1054 /* Get the last sector of the partition */
1055 EndingSector
= GET_STARTING_SECTOR(Entry
) + GET_PARTITION_LENGTH(Entry
);
1057 /* Check if it's more then the maximum sector */
1058 if (EndingSector
> MaxSector
)
1060 /* Invalid partition */
1061 DPRINT1("FSTUB: entry is invalid\n");
1062 DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry
));
1063 DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry
));
1064 DPRINT1("FSTUB: end %#I64x\n", EndingSector
);
1065 DPRINT1("FSTUB: max %#I64x\n", MaxSector
);
1068 else if(GET_STARTING_SECTOR(Entry
) > MaxOffset
)
1070 /* Invalid partition */
1071 DPRINT1("FSTUB: entry is invalid\n");
1072 DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry
));
1073 DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry
));
1074 DPRINT1("FSTUB: end %#I64x\n", EndingSector
);
1075 DPRINT1("FSTUB: maxOffset %#I64x\n", MaxOffset
);
1079 /* It's fine, return success */
1085 HalpCalculateChsValues(IN PLARGE_INTEGER PartitionOffset
,
1086 IN PLARGE_INTEGER PartitionLength
,
1087 IN CCHAR ShiftCount
,
1088 IN ULONG SectorsPerTrack
,
1089 IN ULONG NumberOfTracks
,
1090 IN ULONG ConventionalCylinders
,
1091 OUT PPARTITION_DESCRIPTOR PartitionDescriptor
)
1093 LARGE_INTEGER FirstSector
, SectorCount
;
1094 ULONG LastSector
, Remainder
, SectorsPerCylinder
;
1095 ULONG StartingCylinder
, EndingCylinder
;
1096 ULONG StartingTrack
, EndingTrack
;
1097 ULONG StartingSector
, EndingSector
;
1100 /* Calculate the number of sectors for each cylinder */
1101 SectorsPerCylinder
= SectorsPerTrack
* NumberOfTracks
;
1103 /* Calculate the first sector, and the sector count */
1104 FirstSector
.QuadPart
= PartitionOffset
->QuadPart
>> ShiftCount
;
1105 SectorCount
.QuadPart
= PartitionLength
->QuadPart
>> ShiftCount
;
1107 /* Now calculate the last sector */
1108 LastSector
= FirstSector
.LowPart
+ SectorCount
.LowPart
- 1;
1110 /* Calculate the first and last cylinders */
1111 StartingCylinder
= FirstSector
.LowPart
/ SectorsPerCylinder
;
1112 EndingCylinder
= LastSector
/ SectorsPerCylinder
;
1114 /* Set the default number of cylinders */
1115 if (!ConventionalCylinders
) ConventionalCylinders
= 1024;
1117 /* Normalize the values */
1118 if (StartingCylinder
>= ConventionalCylinders
)
1120 /* Set the maximum to 1023 */
1121 StartingCylinder
= ConventionalCylinders
- 1;
1123 if (EndingCylinder
>= ConventionalCylinders
)
1125 /* Set the maximum to 1023 */
1126 EndingCylinder
= ConventionalCylinders
- 1;
1129 /* Calculate the starting head and sector that still remain */
1130 Remainder
= FirstSector
.LowPart
% SectorsPerCylinder
;
1131 StartingTrack
= Remainder
/ SectorsPerTrack
;
1132 StartingSector
= Remainder
% SectorsPerTrack
;
1134 /* Calculate the ending head and sector that still remain */
1135 Remainder
= LastSector
% SectorsPerCylinder
;
1136 EndingTrack
= Remainder
/ SectorsPerTrack
;
1137 EndingSector
= Remainder
% SectorsPerTrack
;
1139 /* Set cylinder data for the MSB */
1140 PartitionDescriptor
->StartingCylinderMsb
= (UCHAR
)StartingCylinder
;
1141 PartitionDescriptor
->EndingCylinderMsb
= (UCHAR
)EndingCylinder
;
1143 /* Set the track data */
1144 PartitionDescriptor
->StartingTrack
= (UCHAR
)StartingTrack
;
1145 PartitionDescriptor
->EndingTrack
= (UCHAR
)EndingTrack
;
1147 /* Update cylinder data for the LSB */
1148 StartingCylinder
= ((StartingSector
+ 1) & 0x3F) |
1149 ((StartingCylinder
>> 2) & 0xC0);
1150 EndingCylinder
= ((EndingSector
+ 1) & 0x3F) |
1151 ((EndingCylinder
>> 2) & 0xC0);
1153 /* Set the cylinder data for the LSB */
1154 PartitionDescriptor
->StartingCylinderLsb
= (UCHAR
)StartingCylinder
;
1155 PartitionDescriptor
->EndingCylinderLsb
= (UCHAR
)EndingCylinder
;
1160 xHalGetPartialGeometry(IN PDEVICE_OBJECT DeviceObject
,
1161 IN PULONG ConventionalCylinders
,
1162 IN PLONGLONG DiskSize
)
1164 PDISK_GEOMETRY DiskGeometry
= NULL
;
1165 PIO_STATUS_BLOCK IoStatusBlock
= NULL
;
1166 PKEVENT Event
= NULL
;
1171 *ConventionalCylinders
= 0;
1174 /* Allocate the structure in nonpaged pool */
1175 DiskGeometry
= ExAllocatePoolWithTag(NonPagedPool
,
1176 sizeof(DISK_GEOMETRY
),
1178 if (!DiskGeometry
) goto Cleanup
;
1180 /* Allocate the status block in nonpaged pool */
1181 IoStatusBlock
= ExAllocatePoolWithTag(NonPagedPool
,
1182 sizeof(IO_STATUS_BLOCK
),
1184 if (!IoStatusBlock
) goto Cleanup
;
1186 /* Allocate the event in nonpaged pool too */
1187 Event
= ExAllocatePoolWithTag(NonPagedPool
,
1190 if (!Event
) goto Cleanup
;
1192 /* Initialize the event */
1193 KeInitializeEvent(Event
, NotificationEvent
, FALSE
);
1196 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
1201 sizeof(DISK_GEOMETRY
),
1205 if (!Irp
) goto Cleanup
;
1207 /* Now call the driver */
1208 Status
= IoCallDriver(DeviceObject
, Irp
);
1209 if (Status
== STATUS_PENDING
)
1211 /* Wait for it to complete */
1212 KeWaitForSingleObject(Event
, Executive
, KernelMode
, FALSE
, NULL
);
1213 Status
= IoStatusBlock
->Status
;
1216 /* Check driver status */
1217 if (NT_SUCCESS(Status
))
1219 /* Return the cylinder count */
1220 *ConventionalCylinders
= DiskGeometry
->Cylinders
.LowPart
;
1222 /* Make sure it's not larger then 1024 */
1223 if (DiskGeometry
->Cylinders
.LowPart
>= 1024)
1225 /* Otherwise, normalize the value */
1226 *ConventionalCylinders
= 1024;
1229 /* Calculate the disk size */
1230 *DiskSize
= DiskGeometry
->Cylinders
.QuadPart
*
1231 DiskGeometry
->TracksPerCylinder
*
1232 DiskGeometry
->SectorsPerTrack
*
1233 DiskGeometry
->BytesPerSector
;
1237 /* Free all the pointers */
1238 if (Event
) ExFreePoolWithTag(Event
, TAG_FILE_SYSTEM
);
1239 if (IoStatusBlock
) ExFreePoolWithTag(IoStatusBlock
, TAG_FILE_SYSTEM
);
1240 if (DiskGeometry
) ExFreePoolWithTag(DiskGeometry
, TAG_FILE_SYSTEM
);
1246 xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject
,
1247 IN ULONG SectorSize
,
1248 IN ULONG MbrTypeIdentifier
,
1249 OUT PVOID
*MbrBuffer
)
1251 LARGE_INTEGER Offset
;
1255 IO_STATUS_BLOCK IoStatusBlock
;
1257 PPARTITION_DESCRIPTOR PartitionDescriptor
;
1259 PIO_STACK_LOCATION IoStackLocation
;
1260 Offset
.QuadPart
= 0;
1262 /* Assume failure */
1265 /* Normalize the buffer size */
1266 BufferSize
= max(SectorSize
, 512);
1268 /* Allocate the buffer */
1269 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
1270 PAGE_SIZE
> BufferSize
?
1271 PAGE_SIZE
: BufferSize
,
1273 if (!Buffer
) return;
1275 /* Initialize the Event */
1276 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1279 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
1289 ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
1293 /* Make sure to override volume verification */
1294 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
1295 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
1297 /* Call the driver */
1298 Status
= IoCallDriver(DeviceObject
, Irp
);
1299 if (Status
== STATUS_PENDING
)
1301 /* Wait for completion */
1302 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1303 Status
= IoStatusBlock
.Status
;
1306 /* Check driver Status */
1307 if (NT_SUCCESS(Status
))
1309 /* Validate the MBR Signature */
1310 if (((PUSHORT
)Buffer
)[BOOT_SIGNATURE_OFFSET
] != BOOT_RECORD_SIGNATURE
)
1313 ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
1317 /* Get the partition entry */
1318 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1319 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1321 /* Make sure it's what the caller wanted */
1322 if (PartitionDescriptor
->PartitionType
!= MbrTypeIdentifier
)
1324 /* It's not, free our buffer */
1325 ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
1329 /* Check if this is a secondary entry */
1330 if (PartitionDescriptor
->PartitionType
== 0x54)
1332 /* Return our buffer, but at sector 63 */
1333 *(PULONG
)Buffer
= 63;
1334 *MbrBuffer
= Buffer
;
1336 else if (PartitionDescriptor
->PartitionType
== 0x55)
1338 /* EZ Drive, return the buffer directly */
1339 *MbrBuffer
= Buffer
;
1343 /* Otherwise crash on debug builds */
1344 ASSERT(PartitionDescriptor
->PartitionType
== 0x55);
1352 FstubFixupEfiPartition(IN PPARTITION_DESCRIPTOR PartitionDescriptor
,
1353 IN ULONGLONG MaxOffset
)
1355 ULONG PartitionMaxOffset
, PartitionLength
;
1358 /* Compute partition length (according to MBR entry) */
1359 PartitionMaxOffset
= GET_STARTING_SECTOR(PartitionDescriptor
) + GET_PARTITION_LENGTH(PartitionDescriptor
);
1360 /* In case the partition length goes beyond disk size... */
1361 if (PartitionMaxOffset
> MaxOffset
)
1363 /* Resize partition to its maximum real length */
1364 PartitionLength
= (ULONG
)(PartitionMaxOffset
- GET_STARTING_SECTOR(PartitionDescriptor
));
1365 SET_PARTITION_LENGTH(PartitionDescriptor
, PartitionLength
);
1371 xHalIoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject
,
1372 IN ULONG SectorSize
,
1373 IN BOOLEAN ReturnRecognizedPartitions
,
1374 IN OUT PDRIVE_LAYOUT_INFORMATION
*PartitionBuffer
)
1377 IO_STATUS_BLOCK IoStatusBlock
;
1379 PPARTITION_DESCRIPTOR PartitionDescriptor
;
1382 PPARTITION_INFORMATION PartitionInfo
;
1383 PUCHAR Buffer
= NULL
;
1384 ULONG BufferSize
= 2048, InputSize
;
1385 PDRIVE_LAYOUT_INFORMATION DriveLayoutInfo
= NULL
;
1386 LONG j
= -1, i
= -1, k
;
1387 DISK_GEOMETRY DiskGeometry
;
1388 LONGLONG EndSector
, MaxSector
, StartOffset
;
1389 ULONGLONG MaxOffset
;
1390 LARGE_INTEGER Offset
, VolumeOffset
;
1391 BOOLEAN IsPrimary
= TRUE
, IsEzDrive
= FALSE
, MbrFound
= FALSE
;
1392 BOOLEAN IsValid
, IsEmpty
= TRUE
;
1394 PIO_STACK_LOCATION IoStackLocation
;
1395 UCHAR PartitionType
;
1396 LARGE_INTEGER HiddenSectors64
;
1397 VolumeOffset
.QuadPart
= Offset
.QuadPart
= 0;
1400 /* Allocate the buffer */
1401 *PartitionBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1404 if (!(*PartitionBuffer
)) return STATUS_INSUFFICIENT_RESOURCES
;
1406 /* Normalize the buffer size */
1407 InputSize
= max(512, SectorSize
);
1409 /* Check for EZ Drive */
1410 HalExamineMBR(DeviceObject
, InputSize
, 0x55, &MbrBuffer
);
1413 /* EZ Drive found, bias the offset */
1415 ExFreePoolWithTag(MbrBuffer
, TAG_FILE_SYSTEM
);
1416 Offset
.QuadPart
= 512;
1419 /* Get drive geometry */
1420 Status
= HalpGetFullGeometry(DeviceObject
, &DiskGeometry
, &MaxOffset
);
1421 if (!NT_SUCCESS(Status
))
1423 ExFreePoolWithTag(*PartitionBuffer
, TAG_FILE_SYSTEM
);
1424 *PartitionBuffer
= NULL
;
1428 /* Get the end and maximum sector */
1429 EndSector
= MaxOffset
;
1430 MaxSector
= MaxOffset
<< 1;
1431 DPRINT("FSTUB: MaxOffset = %#I64x, MaxSector = %#I64x\n",
1432 MaxOffset
, MaxSector
);
1434 /* Allocate our buffer */
1435 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, InputSize
, TAG_FILE_SYSTEM
);
1438 /* Fail, free the input buffer */
1439 ExFreePoolWithTag(*PartitionBuffer
, TAG_FILE_SYSTEM
);
1440 *PartitionBuffer
= NULL
;
1441 return STATUS_INSUFFICIENT_RESOURCES
;
1444 /* Start partition loop */
1447 /* Assume the partition is valid */
1450 /* Initialize the event */
1451 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1453 /* Clear the buffer and build the IRP */
1454 RtlZeroMemory(Buffer
, InputSize
);
1455 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
1465 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1469 /* Make sure to disable volume verification */
1470 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
1471 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
1473 /* Call the driver */
1474 Status
= IoCallDriver(DeviceObject
, Irp
);
1475 if (Status
== STATUS_PENDING
)
1477 /* Wait for completion */
1478 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1479 Status
= IoStatusBlock
.Status
;
1482 /* Normalize status code and check for failure */
1483 if (Status
== STATUS_NO_DATA_DETECTED
) Status
= STATUS_SUCCESS
;
1484 if (!NT_SUCCESS(Status
)) break;
1486 /* If we biased for EZ-Drive, unbias now */
1487 if (IsEzDrive
&& (Offset
.QuadPart
== 512)) Offset
.QuadPart
= 0;
1489 /* Make sure this is a valid MBR */
1490 if (((PUSHORT
)Buffer
)[BOOT_SIGNATURE_OFFSET
] != BOOT_RECORD_SIGNATURE
)
1492 /* It's not, fail */
1493 DPRINT1("FSTUB: (IoReadPartitionTable) No 0xaa55 found in "
1494 "partition table %d\n", j
+ 1);
1498 /* At this point we have a valid MBR */
1501 /* Check if we weren't given an offset */
1502 if (!Offset
.QuadPart
)
1504 /* Then read the signature off the disk */
1505 (*PartitionBuffer
)->Signature
= ((PULONG
)Buffer
)[PARTITION_TABLE_OFFSET
/ 2 - 1];
1508 /* Get the partition descriptor array */
1509 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1510 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1512 /* Start looping partitions */
1514 DPRINT("FSTUB: Partition Table %d:\n", j
);
1515 for (Entry
= 1, k
= 0; Entry
<= 4; Entry
++, PartitionDescriptor
++)
1517 /* Get the partition type */
1518 PartitionType
= PartitionDescriptor
->PartitionType
;
1520 /* Print debug messages */
1521 DPRINT("Partition Entry %d,%d: type %#x %s\n",
1525 (PartitionDescriptor
->ActiveFlag
) ? "Active" : "");
1526 DPRINT("\tOffset %#08lx for %#08lx Sectors\n",
1527 GET_STARTING_SECTOR(PartitionDescriptor
),
1528 GET_PARTITION_LENGTH(PartitionDescriptor
));
1530 /* Check whether we're facing a protective MBR */
1531 if (PartitionType
== EFI_PMBR_OSTYPE_EFI
)
1533 /* Partition length might be bigger than disk size */
1534 FstubFixupEfiPartition(PartitionDescriptor
,
1538 /* Make sure that the partition is valid, unless it's the first */
1539 if (!(HalpIsValidPartitionEntry(PartitionDescriptor
,
1541 MaxSector
)) && (j
== 0))
1543 /* It's invalid, so fail */
1548 /* Check if it's a container */
1549 if (IsContainerPartition(PartitionType
))
1551 /* Increase the count of containers */
1554 /* More then one table is invalid */
1555 DPRINT1("FSTUB: Multiple container partitions found in "
1556 "partition table %d\n - table is invalid\n",
1563 /* Check if the partition is supposedly empty */
1566 /* But check if it actually has a start and/or length */
1567 if ((GET_STARTING_SECTOR(PartitionDescriptor
)) ||
1568 (GET_PARTITION_LENGTH(PartitionDescriptor
)))
1570 /* So then it's not really empty */
1575 /* Check if the caller wanted only recognized partitions */
1576 if (ReturnRecognizedPartitions
)
1578 /* Then check if this one is unused, or a container */
1579 if ((PartitionType
== PARTITION_ENTRY_UNUSED
) ||
1580 IsContainerPartition(PartitionType
))
1582 /* Skip it, since the caller doesn't want it */
1587 /* Increase the structure count and check if they can fit */
1588 if ((sizeof(DRIVE_LAYOUT_INFORMATION
) +
1589 (++i
* sizeof(PARTITION_INFORMATION
))) >
1592 /* Allocate a new buffer that's twice as big */
1593 DriveLayoutInfo
= ExAllocatePoolWithTag(NonPagedPool
,
1596 if (!DriveLayoutInfo
)
1598 /* Out of memory, unto this extra structure */
1600 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1604 /* Copy the contents of the old buffer */
1605 RtlMoveMemory(DriveLayoutInfo
,
1609 /* Free the old buffer and set this one as the new one */
1610 ExFreePoolWithTag(*PartitionBuffer
, TAG_FILE_SYSTEM
);
1611 *PartitionBuffer
= DriveLayoutInfo
;
1613 /* Double the size */
1617 /* Now get the current structure being filled and initialize it */
1618 PartitionInfo
= &(*PartitionBuffer
)->PartitionEntry
[i
];
1619 PartitionInfo
->PartitionType
= PartitionType
;
1620 PartitionInfo
->RewritePartition
= FALSE
;
1622 /* Check if we're dealing with a partition that's in use */
1623 if (PartitionType
!= PARTITION_ENTRY_UNUSED
)
1625 /* Check if it's bootable */
1626 PartitionInfo
->BootIndicator
= PartitionDescriptor
->
1630 /* Check if its' a container */
1631 if (IsContainerPartition(PartitionType
))
1633 /* Then don't recognize it and use the volume offset */
1634 PartitionInfo
->RecognizedPartition
= FALSE
;
1635 StartOffset
= VolumeOffset
.QuadPart
;
1639 /* Then recognize it and use the partition offset */
1640 PartitionInfo
->RecognizedPartition
= TRUE
;
1641 StartOffset
= Offset
.QuadPart
;
1644 /* Get the starting offset */
1645 PartitionInfo
->StartingOffset
.QuadPart
=
1647 UInt32x32To64(GET_STARTING_SECTOR(PartitionDescriptor
),
1650 /* Calculate the number of hidden sectors */
1651 HiddenSectors64
.QuadPart
= (PartitionInfo
->
1652 StartingOffset
.QuadPart
-
1655 PartitionInfo
->HiddenSectors
= HiddenSectors64
.LowPart
;
1657 /* Get the partition length */
1658 PartitionInfo
->PartitionLength
.QuadPart
=
1659 UInt32x32To64(GET_PARTITION_LENGTH(PartitionDescriptor
),
1662 /* Get the partition number */
1663 PartitionInfo
->PartitionNumber
= (!IsContainerPartition(PartitionType
)) ? i
+ 1 : 0;
1667 /* Otherwise, clear all the relevant fields */
1668 PartitionInfo
->BootIndicator
= FALSE
;
1669 PartitionInfo
->RecognizedPartition
= FALSE
;
1670 PartitionInfo
->StartingOffset
.QuadPart
= 0;
1671 PartitionInfo
->PartitionLength
.QuadPart
= 0;
1672 PartitionInfo
->HiddenSectors
= 0;
1674 PartitionInfo
->PartitionNumber
= 0;
1678 /* Finish debug log, and check for failure */
1680 if (!NT_SUCCESS(Status
)) break;
1682 /* Also check if we hit an invalid entry here */
1685 /* We did, so break out of the loop minus one entry */
1690 /* Reset the offset */
1691 Offset
.QuadPart
= 0;
1693 /* Go back to the descriptor array and loop it */
1694 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1695 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1696 for (Entry
= 1; Entry
<= 4; Entry
++, PartitionDescriptor
++)
1698 /* Check if this is a container partition, since we skipped them */
1699 if (IsContainerPartition(PartitionDescriptor
->PartitionType
))
1701 /* Get its offset */
1702 Offset
.QuadPart
= VolumeOffset
.QuadPart
+
1704 GET_STARTING_SECTOR(PartitionDescriptor
),
1707 /* If this is a primary partition, this is the volume offset */
1708 if (IsPrimary
) VolumeOffset
= Offset
;
1710 /* Also update the maximum sector */
1711 MaxSector
= GET_PARTITION_LENGTH(PartitionDescriptor
);
1712 DPRINT1("FSTUB: MaxSector now = %I64d\n", MaxSector
);
1717 /* Loop the next partitions, which are not primary anymore */
1719 } while (Offset
.HighPart
| Offset
.LowPart
);
1721 /* Check if this is a removable device that's probably a super-floppy */
1722 if ((DiskGeometry
.MediaType
== RemovableMedia
) &&
1723 (j
== 0) && (MbrFound
) && (IsEmpty
))
1725 PBOOT_SECTOR_INFO BootSectorInfo
= (PBOOT_SECTOR_INFO
)Buffer
;
1727 /* Read the jump bytes to detect super-floppy */
1728 if ((BootSectorInfo
->JumpByte
[0] == 0xeb) ||
1729 (BootSectorInfo
->JumpByte
[0] == 0xe9))
1731 /* Super floppes don't have typical MBRs, so skip them */
1732 DPRINT1("FSTUB: Jump byte %#x found along with empty partition "
1733 "table - disk is a super floppy and has no valid MBR\n",
1734 BootSectorInfo
->JumpByte
);
1739 /* Check if we're still at partition -1 */
1742 /* The likely cause is the super floppy detection above */
1743 if ((MbrFound
) || (DiskGeometry
.MediaType
== RemovableMedia
))
1745 /* Print out debugging information */
1746 DPRINT1("FSTUB: Drive %#p has no valid MBR. Make it into a "
1749 DPRINT1("FSTUB: Drive has %I64d sectors and is %#016I64x "
1751 EndSector
, EndSector
* DiskGeometry
.BytesPerSector
);
1753 /* We should at least have some sectors */
1756 /* Get the entry we'll use */
1757 PartitionInfo
= &(*PartitionBuffer
)->PartitionEntry
[0];
1759 /* Fill it out with data for a super-floppy */
1760 PartitionInfo
->RewritePartition
= FALSE
;
1761 PartitionInfo
->RecognizedPartition
= TRUE
;
1762 PartitionInfo
->PartitionType
= PARTITION_FAT_16
;
1763 PartitionInfo
->BootIndicator
= FALSE
;
1764 PartitionInfo
->HiddenSectors
= 0;
1765 PartitionInfo
->StartingOffset
.QuadPart
= 0;
1766 PartitionInfo
->PartitionLength
.QuadPart
= (EndSector
*
1770 /* FIXME: REACTOS HACK */
1771 PartitionInfo
->PartitionNumber
= 0;
1773 /* Set the signature and set the count back to 0 */
1774 (*PartitionBuffer
)->Signature
= 1;
1780 /* Otherwise, this isn't a super floppy, so set an invalid count */
1785 /* Set the partition count */
1786 (*PartitionBuffer
)->PartitionCount
= ++i
;
1788 /* If we have no count, delete the signature */
1789 if (!i
) (*PartitionBuffer
)->Signature
= 0;
1791 /* Free the buffer and check for success */
1792 if (Buffer
) ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
1793 if (!NT_SUCCESS(Status
))
1795 ExFreePoolWithTag(*PartitionBuffer
, TAG_FILE_SYSTEM
);
1796 *PartitionBuffer
= NULL
;
1805 xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject
,
1806 IN ULONG SectorSize
,
1807 IN ULONG PartitionNumber
,
1808 IN ULONG PartitionType
)
1812 IO_STATUS_BLOCK IoStatusBlock
;
1814 LARGE_INTEGER Offset
, VolumeOffset
;
1815 PUCHAR Buffer
= NULL
;
1819 PPARTITION_DESCRIPTOR PartitionDescriptor
;
1820 BOOLEAN IsPrimary
= TRUE
, IsEzDrive
= FALSE
;
1822 PIO_STACK_LOCATION IoStackLocation
;
1823 VolumeOffset
.QuadPart
= Offset
.QuadPart
= 0;
1826 /* Normalize the buffer size */
1827 BufferSize
= max(512, SectorSize
);
1829 /* Check for EZ Drive */
1830 HalExamineMBR(DeviceObject
, BufferSize
, 0x55, &MbrBuffer
);
1833 /* EZ Drive found, bias the offset */
1835 ExFreePoolWithTag(MbrBuffer
, TAG_FILE_SYSTEM
);
1836 Offset
.QuadPart
= 512;
1839 /* Allocate our partition buffer */
1840 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, PAGE_SIZE
, TAG_FILE_SYSTEM
);
1841 if (!Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
1843 /* Initialize the event we'll use and loop partitions */
1844 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1847 /* Reset the event since we reuse it */
1848 KeClearEvent(&Event
);
1850 /* Build the read IRP */
1851 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
1861 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1865 /* Make sure to disable volume verification */
1866 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
1867 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
1869 /* Call the driver */
1870 Status
= IoCallDriver(DeviceObject
, Irp
);
1871 if (Status
== STATUS_PENDING
)
1873 /* Wait for completion */
1874 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1875 Status
= IoStatusBlock
.Status
;
1878 /* Check for failure */
1879 if (!NT_SUCCESS(Status
)) break;
1881 /* If we biased for EZ-Drive, unbias now */
1882 if (IsEzDrive
&& (Offset
.QuadPart
== 512)) Offset
.QuadPart
= 0;
1884 /* Make sure this is a valid MBR */
1885 if (((PUSHORT
)Buffer
)[BOOT_SIGNATURE_OFFSET
] != BOOT_RECORD_SIGNATURE
)
1887 /* It's not, fail */
1888 Status
= STATUS_BAD_MASTER_BOOT_RECORD
;
1892 /* Get the partition descriptors and loop them */
1893 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1894 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1895 for (Entry
= 1; Entry
<= 4; Entry
++, PartitionDescriptor
++)
1897 /* Check if it's unused or a container partition */
1898 if ((PartitionDescriptor
->PartitionType
==
1899 PARTITION_ENTRY_UNUSED
) ||
1900 (IsContainerPartition(PartitionDescriptor
->PartitionType
)))
1902 /* Go to the next one */
1906 /* It's a valid partition, so increase the partition count */
1907 if (++i
== PartitionNumber
)
1909 /* We found a match, set the type */
1910 PartitionDescriptor
->PartitionType
= (UCHAR
)PartitionType
;
1912 /* Reset the reusable event */
1913 KeClearEvent(&Event
);
1915 /* Build the write IRP */
1916 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
1926 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1930 /* Disable volume verification */
1931 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
1932 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
1934 /* Call the driver */
1935 Status
= IoCallDriver(DeviceObject
, Irp
);
1936 if (Status
== STATUS_PENDING
)
1938 /* Wait for completion */
1939 KeWaitForSingleObject(&Event
,
1944 Status
= IoStatusBlock
.Status
;
1947 /* We're done, break out of the loop */
1952 /* If we looped all the partitions, break out */
1953 if (Entry
<= NUM_PARTITION_TABLE_ENTRIES
) break;
1955 /* Nothing found yet, get the partition array again */
1956 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1957 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1958 for (Entry
= 1; Entry
<= 4; Entry
++, PartitionDescriptor
++)
1960 /* Check if this was a container partition (we skipped these) */
1961 if (IsContainerPartition(PartitionDescriptor
->PartitionType
))
1963 /* Update the partition offset */
1964 Offset
.QuadPart
= VolumeOffset
.QuadPart
+
1965 GET_STARTING_SECTOR(PartitionDescriptor
) *
1968 /* If this was the primary partition, update the volume too */
1969 if (IsPrimary
) VolumeOffset
= Offset
;
1974 /* Check if we already searched all the partitions */
1975 if (Entry
> NUM_PARTITION_TABLE_ENTRIES
)
1977 /* Then we failed to find a good MBR */
1978 Status
= STATUS_BAD_MASTER_BOOT_RECORD
;
1982 /* Loop the next partitions, which are not primary anymore */
1984 } while (i
< PartitionNumber
);
1986 /* Everything done, cleanup */
1987 if (Buffer
) ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
1993 xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject
,
1994 IN ULONG SectorSize
,
1995 IN ULONG SectorsPerTrack
,
1996 IN ULONG NumberOfHeads
,
1997 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer
)
2000 IO_STATUS_BLOCK IoStatusBlock
;
2002 NTSTATUS Status
= STATUS_SUCCESS
;
2006 PPARTITION_TABLE PartitionTable
;
2007 LARGE_INTEGER Offset
, NextOffset
, ExtendedOffset
, SectorOffset
;
2008 LARGE_INTEGER StartOffset
, PartitionLength
;
2011 BOOLEAN IsEzDrive
= FALSE
, IsSuperFloppy
= FALSE
, DoRewrite
= FALSE
, IsMbr
;
2012 ULONG ConventionalCylinders
;
2014 PDISK_LAYOUT DiskLayout
= (PDISK_LAYOUT
)PartitionBuffer
;
2016 UCHAR PartitionType
;
2017 PIO_STACK_LOCATION IoStackLocation
;
2018 PPARTITION_INFORMATION PartitionInfo
= PartitionBuffer
->PartitionEntry
;
2019 PPARTITION_INFORMATION TableEntry
;
2020 ExtendedOffset
.QuadPart
= NextOffset
.QuadPart
= Offset
.QuadPart
= 0;
2023 /* Normalize the buffer size */
2024 BufferSize
= max(512, SectorSize
);
2026 /* Get the partial drive geometry */
2027 xHalGetPartialGeometry(DeviceObject
, &ConventionalCylinders
, &DiskSize
);
2029 /* Check for EZ Drive */
2030 HalExamineMBR(DeviceObject
, BufferSize
, 0x55, &MbrBuffer
);
2033 /* EZ Drive found, bias the offset */
2035 ExFreePoolWithTag(MbrBuffer
, TAG_FILE_SYSTEM
);
2036 Offset
.QuadPart
= 512;
2039 /* Get the number of bits to shift to multiply by the sector size */
2040 for (k
= 0; k
< 32; k
++) if ((SectorSize
>> k
) == 1) break;
2042 /* Check if there's only one partition */
2043 if (PartitionBuffer
->PartitionCount
== 1)
2045 /* Check if it has no starting offset or hidden sectors */
2046 if (!(PartitionInfo
->StartingOffset
.QuadPart
) &&
2047 !(PartitionInfo
->HiddenSectors
))
2049 /* Then it's a super floppy */
2050 IsSuperFloppy
= TRUE
;
2052 /* Which also means it must be non-bootable FAT-16 */
2053 if ((PartitionInfo
->PartitionNumber
) ||
2054 (PartitionInfo
->PartitionType
!= PARTITION_FAT_16
) ||
2055 (PartitionInfo
->BootIndicator
))
2057 /* It's not, so we fail */
2058 return STATUS_INVALID_PARAMETER
;
2061 /* Check if it needs a rewrite, and disable EZ drive for sure */
2062 if (PartitionInfo
->RewritePartition
) DoRewrite
= TRUE
;
2067 /* Count the number of partition tables */
2068 DiskLayout
->TableCount
= (PartitionBuffer
->PartitionCount
+ 4 - 1) / 4;
2070 /* Allocate our partition buffer */
2071 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, PAGE_SIZE
, TAG_FILE_SYSTEM
);
2072 if (!Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
2074 /* Loop the entries */
2075 Entry
= (PPTE
)&Buffer
[PARTITION_TABLE_OFFSET
];
2076 for (i
= 0; i
< DiskLayout
->TableCount
; i
++)
2078 /* Set if this is the MBR partition */
2081 /* Initialize th event */
2082 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
2084 /* Build the read IRP */
2085 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
2095 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2099 /* Make sure to disable volume verification */
2100 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
2101 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
2103 /* Call the driver */
2104 Status
= IoCallDriver(DeviceObject
, Irp
);
2105 if (Status
== STATUS_PENDING
)
2107 /* Wait for completion */
2108 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
2109 Status
= IoStatusBlock
.Status
;
2112 /* Check for failure */
2113 if (!NT_SUCCESS(Status
)) break;
2115 /* If we biased for EZ-Drive, unbias now */
2116 if (IsEzDrive
&& (Offset
.QuadPart
== 512)) Offset
.QuadPart
= 0;
2118 /* Check if this is a normal disk */
2121 /* Set the boot record signature */
2122 Buffer
[BOOT_SIGNATURE_OFFSET
] = BOOT_RECORD_SIGNATURE
;
2124 /* By default, don't require a rewrite */
2127 /* Check if we don't have an offset */
2128 if (!Offset
.QuadPart
)
2130 /* Check if the signature doesn't match */
2131 if (((PULONG
)Buffer
)[PARTITION_TABLE_OFFSET
/ 2 - 1] !=
2132 PartitionBuffer
->Signature
)
2134 /* Then write the signature and now we need a rewrite */
2135 ((PULONG
)Buffer
)[PARTITION_TABLE_OFFSET
/ 2 - 1] =
2136 PartitionBuffer
->Signature
;
2141 /* Loop the partition table entries */
2142 PartitionTable
= &DiskLayout
->PartitionTable
[i
];
2143 for (j
= 0; j
< 4; j
++)
2145 /* Get the current entry and type */
2146 TableEntry
= &PartitionTable
->PartitionEntry
[j
];
2147 PartitionType
= TableEntry
->PartitionType
;
2149 /* Check if the entry needs a rewrite */
2150 if (TableEntry
->RewritePartition
)
2152 /* Then we need one too */
2155 /* Save the type and if it's a bootable partition */
2156 Entry
[j
].PartitionType
= TableEntry
->PartitionType
;
2157 Entry
[j
].ActiveFlag
= TableEntry
->BootIndicator
? 0x80 : 0;
2159 /* Make sure it's used */
2160 if (PartitionType
!= PARTITION_ENTRY_UNUSED
)
2162 /* Make sure it's not a container (unless primary) */
2163 if ((IsMbr
) || !(IsContainerPartition(PartitionType
)))
2165 /* Use the partition offset */
2166 StartOffset
.QuadPart
= Offset
.QuadPart
;
2170 /* Use the extended logical partition offset */
2171 StartOffset
.QuadPart
= ExtendedOffset
.QuadPart
;
2174 /* Set the sector offset */
2175 SectorOffset
.QuadPart
= TableEntry
->
2176 StartingOffset
.QuadPart
-
2177 StartOffset
.QuadPart
;
2179 /* Now calculate the starting sector */
2180 StartOffset
.QuadPart
= SectorOffset
.QuadPart
>> k
;
2181 Entry
[j
].StartingSector
= StartOffset
.LowPart
;
2183 /* As well as the length */
2184 PartitionLength
.QuadPart
= TableEntry
->PartitionLength
.
2186 Entry
[j
].PartitionLength
= PartitionLength
.LowPart
;
2188 /* Calculate the CHS values */
2189 HalpCalculateChsValues(&TableEntry
->StartingOffset
,
2190 &TableEntry
->PartitionLength
,
2194 ConventionalCylinders
,
2195 (PPARTITION_DESCRIPTOR
)
2200 /* Otherwise set up an empty entry */
2201 Entry
[j
].StartingSector
= 0;
2202 Entry
[j
].PartitionLength
= 0;
2203 Entry
[j
].StartingTrack
= 0;
2204 Entry
[j
].EndingTrack
= 0;
2205 Entry
[j
].StartingCylinder
= 0;
2206 Entry
[j
].EndingCylinder
= 0;
2210 /* Check if this is a container partition */
2211 if (IsContainerPartition(PartitionType
))
2213 /* Then update the offset to use */
2214 NextOffset
= TableEntry
->StartingOffset
;
2219 /* Check if we need to write back the buffer */
2222 /* We don't need to do this again */
2225 /* Initialize the event */
2226 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
2228 /* If we unbiased for EZ-Drive, rebias now */
2229 if ((IsEzDrive
) && !(Offset
.QuadPart
)) Offset
.QuadPart
= 512;
2231 /* Build the write IRP */
2232 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
2242 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2246 /* Make sure to disable volume verification */
2247 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
2248 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
2250 /* Call the driver */
2251 Status
= IoCallDriver(DeviceObject
, Irp
);
2252 if (Status
== STATUS_PENDING
)
2254 /* Wait for completion */
2255 KeWaitForSingleObject(&Event
,
2260 Status
= IoStatusBlock
.Status
;
2263 /* Check for failure */
2264 if (!NT_SUCCESS(Status
)) break;
2266 /* If we biased for EZ-Drive, unbias now */
2267 if (IsEzDrive
&& (Offset
.QuadPart
== 512)) Offset
.QuadPart
= 0;
2270 /* Update the partition offset and set the extended offset if needed */
2271 Offset
= NextOffset
;
2272 if (IsMbr
) ExtendedOffset
= NextOffset
;
2275 /* If we had a buffer, free it, then return status */
2276 if (Buffer
) ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
2280 /* PUBLIC FUNCTIONS **********************************************************/
2287 HalExamineMBR(IN PDEVICE_OBJECT DeviceObject
,
2288 IN ULONG SectorSize
,
2289 IN ULONG MbrTypeIdentifier
,
2290 OUT PVOID
*MbrBuffer
)
2292 HALDISPATCH
->HalExamineMBR(DeviceObject
,
2303 IoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject
,
2304 IN ULONG SectorSize
,
2305 IN BOOLEAN ReturnRecognizedPartitions
,
2306 IN OUT PDRIVE_LAYOUT_INFORMATION
*PartitionBuffer
)
2308 return HALDISPATCH
->HalIoReadPartitionTable(DeviceObject
,
2310 ReturnRecognizedPartitions
,
2319 IoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject
,
2320 IN ULONG SectorSize
,
2321 IN ULONG PartitionNumber
,
2322 IN ULONG PartitionType
)
2324 return HALDISPATCH
->HalIoSetPartitionInformation(DeviceObject
,
2335 IoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject
,
2336 IN ULONG SectorSize
,
2337 IN ULONG SectorsPerTrack
,
2338 IN ULONG NumberOfHeads
,
2339 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer
)
2341 return HALDISPATCH
->HalIoWritePartitionTable(DeviceObject
,
2353 IoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
2354 IN PSTRING NtDeviceName
,
2355 OUT PUCHAR NtSystemPath
,
2356 OUT PSTRING NtSystemPathString
)
2358 HALDISPATCH
->HalIoAssignDriveLetters(LoaderBlock
,
2361 NtSystemPathString
);