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 %d\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: %d\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 %d\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: %d\n", ConfigInfo
->DiskCount
);
497 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
500 L
"\\Device\\Harddisk%d\\Partition0",
502 RtlInitUnicodeString(&UnicodeString1
,
505 InitializeObjectAttributes(&ObjectAttributes
,
511 Status
= ZwOpenFile(&FileHandle
,
512 FILE_READ_DATA
| SYNCHRONIZE
,
516 FILE_SYNCHRONOUS_IO_NONALERT
);
517 if (NT_SUCCESS(Status
))
522 L
"\\??\\PhysicalDrive%d",
524 RtlInitUnicodeString(&UnicodeString2
,
527 DPRINT("Creating link: %S ==> %S\n",
531 IoCreateSymbolicLink(&UnicodeString2
,
536 /* Initialize layout array */
537 if (ConfigInfo
->DiskCount
== 0)
538 goto end_assign_disks
;
539 LayoutArray
= ExAllocatePoolWithTag(NonPagedPool
,
540 ConfigInfo
->DiskCount
* sizeof(PDRIVE_LAYOUT_INFORMATION
), TAG_FILE_SYSTEM
);
543 ExFreePoolWithTag(PartialInformation
, TAG_FILE_SYSTEM
);
544 ExFreePoolWithTag(Buffer2
, TAG_FILE_SYSTEM
);
545 ExFreePoolWithTag(Buffer1
, TAG_FILE_SYSTEM
);
546 if (hKey
) ObCloseHandle(hKey
, KernelMode
);
550 RtlZeroMemory(LayoutArray
,
551 ConfigInfo
->DiskCount
* sizeof(PDRIVE_LAYOUT_INFORMATION
));
552 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
555 L
"\\Device\\Harddisk%d\\Partition0",
557 RtlInitUnicodeString(&UnicodeString1
,
560 Status
= xHalQueryDriveLayout(&UnicodeString1
,
562 if (!NT_SUCCESS(Status
))
564 DbgPrint("xHalQueryDriveLayout() failed (Status = 0x%lx)\n",
566 LayoutArray
[i
] = NULL
;
569 /* We don't use the RewritePartition value while mounting the disks.
570 * We use this value for marking pre-assigned (registry) partitions.
572 for (j
= 0; j
< LayoutArray
[i
]->PartitionCount
; j
++)
574 LayoutArray
[i
]->PartitionEntry
[j
].RewritePartition
= FALSE
;
579 /* Dump layout array */
580 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
582 DPRINT("Harddisk %d:\n",
585 if (LayoutArray
[i
] == NULL
)
588 DPRINT("Logical partitions: %d\n",
589 LayoutArray
[i
]->PartitionCount
);
591 for (j
= 0; j
< LayoutArray
[i
]->PartitionCount
; j
++)
593 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%I64u count:%I64u\n",
595 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
,
596 LayoutArray
[i
]->PartitionEntry
[j
].BootIndicator
,
597 LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
,
598 LayoutArray
[i
]->PartitionEntry
[j
].StartingOffset
.QuadPart
,
599 LayoutArray
[i
]->PartitionEntry
[j
].PartitionLength
.QuadPart
);
604 /* Assign pre-assigned (registry) partitions */
607 for (k
= 2; k
< 26; k
++)
609 swprintf(Buffer1
, DiskMountString
, L
'A' + k
);
610 RtlInitUnicodeString(&UnicodeString1
, Buffer1
);
611 Status
= ZwQueryValueKey(hKey
,
613 KeyValuePartialInformation
,
615 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(REG_DISK_MOUNT_INFO
),
617 if (NT_SUCCESS(Status
) &&
618 PartialInformation
->Type
== REG_BINARY
&&
619 PartialInformation
->DataLength
== sizeof(REG_DISK_MOUNT_INFO
))
621 DPRINT("%wZ => %08x:%08x%08x\n", &UnicodeString1
, DiskMountInfo
->Signature
,
622 DiskMountInfo
->StartingOffset
.u
.HighPart
, DiskMountInfo
->StartingOffset
.u
.LowPart
);
624 BOOLEAN Found
= FALSE
;
625 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
627 DPRINT("%x\n", LayoutArray
[i
]->Signature
);
628 if (LayoutArray
[i
] &&
629 LayoutArray
[i
]->Signature
&&
630 LayoutArray
[i
]->Signature
== DiskMountInfo
->Signature
)
632 for (j
= 0; j
< LayoutArray
[i
]->PartitionCount
; j
++)
634 if (LayoutArray
[i
]->PartitionEntry
[j
].StartingOffset
.QuadPart
== DiskMountInfo
->StartingOffset
.QuadPart
)
636 if (IsRecognizedPartition(LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
) &&
637 LayoutArray
[i
]->PartitionEntry
[j
].RewritePartition
== FALSE
)
640 L
"\\Device\\Harddisk%d\\Partition%d",
642 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
);
643 RtlInitUnicodeString(&UnicodeString2
,
647 DPRINT(" %wZ\n", &UnicodeString2
);
648 Found
= HalpAssignDrive(&UnicodeString2
,
650 DOSDEVICE_DRIVE_FIXED
,
651 DiskMountInfo
->Signature
,
652 DiskMountInfo
->StartingOffset
,
656 /* Mark the partition as assigned */
657 LayoutArray
[i
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
666 /* We didn't find a partition for this entry, remove them. */
667 Status
= ZwDeleteValueKey(hKey
, &UnicodeString1
);
674 /* Assign bootable partition on first harddisk */
675 DPRINT("Assigning bootable primary partition on first harddisk:\n");
678 Status
= xHalpGetDiskNumberFromRDisk(0, &DiskNumber
);
679 if (NT_SUCCESS(Status
) &&
680 DiskNumber
< ConfigInfo
->DiskCount
&&
681 LayoutArray
[DiskNumber
])
683 /* Search for bootable partition */
684 for (j
= 0; j
< NUM_PARTITION_TABLE_ENTRIES
&& j
< LayoutArray
[DiskNumber
]->PartitionCount
; j
++)
686 if ((LayoutArray
[DiskNumber
]->PartitionEntry
[j
].BootIndicator
== TRUE
) &&
687 IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
))
689 if (LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
)
692 L
"\\Device\\Harddisk%lu\\Partition%d",
694 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
695 RtlInitUnicodeString(&UnicodeString2
,
699 DPRINT(" %wZ\n", &UnicodeString2
);
700 HalpAssignDrive(&UnicodeString2
,
702 DOSDEVICE_DRIVE_FIXED
,
703 LayoutArray
[DiskNumber
]->Signature
,
704 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
708 /* Mark the partition as assigned */
709 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
717 /* Assign remaining primary partitions */
718 DPRINT("Assigning remaining primary partitions:\n");
719 for (RDisk
= 0; RDisk
< RDiskCount
; RDisk
++)
721 Status
= xHalpGetDiskNumberFromRDisk(RDisk
, &DiskNumber
);
722 if (NT_SUCCESS(Status
) &&
723 DiskNumber
< ConfigInfo
->DiskCount
&&
724 LayoutArray
[DiskNumber
])
726 /* Search for primary partitions */
727 for (j
= 0; (j
< NUM_PARTITION_TABLE_ENTRIES
) && (j
< LayoutArray
[DiskNumber
]->PartitionCount
); j
++)
729 if (LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
&&
730 IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
))
733 L
"\\Device\\Harddisk%d\\Partition%d",
735 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
736 RtlInitUnicodeString(&UnicodeString2
,
742 HalpAssignDrive(&UnicodeString2
,
744 DOSDEVICE_DRIVE_FIXED
,
745 LayoutArray
[DiskNumber
]->Signature
,
746 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
750 /* Mark the partition as assigned */
751 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
757 /* Assign extended (logical) partitions */
758 DPRINT("Assigning extended (logical) partitions:\n");
759 for (RDisk
= 0; RDisk
< RDiskCount
; RDisk
++)
761 Status
= xHalpGetDiskNumberFromRDisk(RDisk
, &DiskNumber
);
762 if (NT_SUCCESS(Status
) &&
763 DiskNumber
< ConfigInfo
->DiskCount
&&
764 LayoutArray
[DiskNumber
])
766 /* Search for extended partitions */
767 for (j
= NUM_PARTITION_TABLE_ENTRIES
; j
< LayoutArray
[DiskNumber
]->PartitionCount
; j
++)
769 if (IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
) &&
770 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
&&
771 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
!= 0)
774 L
"\\Device\\Harddisk%d\\Partition%d",
776 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
777 RtlInitUnicodeString(&UnicodeString2
,
783 HalpAssignDrive(&UnicodeString2
,
785 DOSDEVICE_DRIVE_FIXED
,
786 LayoutArray
[DiskNumber
]->Signature
,
787 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
791 /* Mark the partition as assigned */
792 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
798 /* Assign remaining primary partitions without an arc-name */
799 DPRINT("Assigning remaining primary partitions:\n");
800 for (DiskNumber
= 0; DiskNumber
< ConfigInfo
->DiskCount
; DiskNumber
++)
802 if (LayoutArray
[DiskNumber
])
804 /* Search for primary partitions */
805 for (j
= 0; (j
< NUM_PARTITION_TABLE_ENTRIES
) && (j
< LayoutArray
[DiskNumber
]->PartitionCount
); j
++)
807 if (LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
&&
808 IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
))
811 L
"\\Device\\Harddisk%d\\Partition%d",
813 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
814 RtlInitUnicodeString(&UnicodeString2
,
820 HalpAssignDrive(&UnicodeString2
,
822 DOSDEVICE_DRIVE_FIXED
,
823 LayoutArray
[DiskNumber
]->Signature
,
824 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
828 /* Mark the partition as assigned */
829 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
835 /* Assign extended (logical) partitions without an arc-name */
836 DPRINT("Assigning extended (logical) partitions:\n");
837 for (DiskNumber
= 0; DiskNumber
< ConfigInfo
->DiskCount
; DiskNumber
++)
839 if (LayoutArray
[DiskNumber
])
841 /* Search for extended partitions */
842 for (j
= NUM_PARTITION_TABLE_ENTRIES
; j
< LayoutArray
[DiskNumber
]->PartitionCount
; j
++)
844 if (IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
) &&
845 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
&&
846 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
!= 0)
849 L
"\\Device\\Harddisk%d\\Partition%d",
851 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
852 RtlInitUnicodeString(&UnicodeString2
,
858 HalpAssignDrive(&UnicodeString2
,
860 DOSDEVICE_DRIVE_FIXED
,
861 LayoutArray
[DiskNumber
]->Signature
,
862 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
866 /* Mark the partition as assigned */
867 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
873 /* Assign removable disk drives */
874 DPRINT("Assigning removable disk drives:\n");
875 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
879 /* Search for virtual partitions */
880 if (LayoutArray
[i
]->PartitionCount
== 1 &&
881 LayoutArray
[i
]->PartitionEntry
[0].PartitionType
== 0)
884 L
"\\Device\\Harddisk%d\\Partition1",
886 RtlInitUnicodeString(&UnicodeString2
,
892 HalpAssignDrive(&UnicodeString2
,
894 DOSDEVICE_DRIVE_REMOVABLE
,
896 RtlConvertLongToLargeInteger(0),
904 /* Free layout array */
905 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
907 if (LayoutArray
[i
] != NULL
)
908 ExFreePoolWithTag(LayoutArray
[i
], TAG_FILE_SYSTEM
);
910 ExFreePoolWithTag(LayoutArray
, TAG_FILE_SYSTEM
);
913 /* Assign floppy drives */
914 DPRINT("Floppy drives: %d\n", ConfigInfo
->FloppyCount
);
915 for (i
= 0; i
< ConfigInfo
->FloppyCount
; i
++)
918 L
"\\Device\\Floppy%d",
920 RtlInitUnicodeString(&UnicodeString1
,
923 /* Assign drive letters A: or B: or first free drive letter */
926 HalpAssignDrive(&UnicodeString1
,
927 (i
< 2) ? i
: AUTO_DRIVE
,
928 DOSDEVICE_DRIVE_REMOVABLE
,
930 RtlConvertLongToLargeInteger(0),
936 /* Assign cdrom drives */
937 DPRINT("CD-Rom drives: %d\n", ConfigInfo
->CdRomCount
);
938 for (i
= 0; i
< ConfigInfo
->CdRomCount
; i
++)
941 L
"\\Device\\CdRom%d",
943 RtlInitUnicodeString(&UnicodeString1
,
946 /* Assign first free drive letter */
947 DPRINT(" %wZ\n", &UnicodeString1
);
948 HalpAssignDrive(&UnicodeString1
,
950 DOSDEVICE_DRIVE_CDROM
,
952 RtlConvertLongToLargeInteger(0),
958 /* Anything else to do? */
960 ExFreePoolWithTag(PartialInformation
, TAG_FILE_SYSTEM
);
961 ExFreePoolWithTag(Buffer2
, TAG_FILE_SYSTEM
);
962 ExFreePoolWithTag(Buffer1
, TAG_FILE_SYSTEM
);
963 if (hKey
) ObCloseHandle(hKey
, KernelMode
);
968 /* PRIVATE FUNCTIONS *********************************************************/
972 HalpGetFullGeometry(IN PDEVICE_OBJECT DeviceObject
,
973 IN PDISK_GEOMETRY Geometry
,
974 OUT PULONGLONG RealSectorCount
)
977 IO_STATUS_BLOCK IoStatusBlock
;
980 PARTITION_INFORMATION PartitionInfo
;
983 /* Allocate a non-paged event */
984 Event
= ExAllocatePoolWithTag(NonPagedPool
,
987 if (!Event
) return STATUS_INSUFFICIENT_RESOURCES
;
990 KeInitializeEvent(Event
, NotificationEvent
, FALSE
);
993 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
998 sizeof(DISK_GEOMETRY
),
1004 /* Fail, free the event */
1005 ExFreePoolWithTag(Event
, TAG_FILE_SYSTEM
);
1006 return STATUS_INSUFFICIENT_RESOURCES
;
1009 /* Call the driver and check if it's pending */
1010 Status
= IoCallDriver(DeviceObject
, Irp
);
1011 if (Status
== STATUS_PENDING
)
1013 /* Wait on the driver */
1014 KeWaitForSingleObject(Event
, Executive
, KernelMode
, FALSE
, NULL
);
1015 Status
= IoStatusBlock
.Status
;
1018 /* Check if the driver returned success */
1019 if(NT_SUCCESS(Status
))
1021 /* Build another IRP */
1022 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO
,
1027 sizeof(PARTITION_INFORMATION
),
1033 /* Fail, free the event */
1034 ExFreePoolWithTag(Event
, TAG_FILE_SYSTEM
);
1035 return STATUS_INSUFFICIENT_RESOURCES
;
1038 /* Call the driver and check if it's pending */
1039 Status
= IoCallDriver(DeviceObject
, Irp
);
1040 if (Status
== STATUS_PENDING
)
1042 /* Wait on the driver */
1043 KeWaitForSingleObject(Event
, Executive
, KernelMode
, FALSE
, NULL
);
1044 Status
= IoStatusBlock
.Status
;
1047 /* Check if the driver returned success */
1048 if(NT_SUCCESS(Status
))
1050 /* Get the number of sectors */
1051 *RealSectorCount
= (PartitionInfo
.PartitionLength
.QuadPart
/
1052 Geometry
->BytesPerSector
);
1056 /* Free the event and return the Status */
1057 ExFreePoolWithTag(Event
, TAG_FILE_SYSTEM
);
1063 HalpIsValidPartitionEntry(IN PPARTITION_DESCRIPTOR Entry
,
1064 IN ULONGLONG MaxOffset
,
1065 IN ULONGLONG MaxSector
)
1067 ULONGLONG EndingSector
;
1070 /* Unused partitions are considered valid */
1071 if (Entry
->PartitionType
== PARTITION_ENTRY_UNUSED
) return TRUE
;
1073 /* Get the last sector of the partition */
1074 EndingSector
= GET_STARTING_SECTOR(Entry
) + GET_PARTITION_LENGTH(Entry
);
1076 /* Check if it's more then the maximum sector */
1077 if (EndingSector
> MaxSector
)
1079 /* Invalid partition */
1080 DPRINT1("FSTUB: entry is invalid\n");
1081 DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry
));
1082 DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry
));
1083 DPRINT1("FSTUB: end %#I64x\n", EndingSector
);
1084 DPRINT1("FSTUB: max %#I64x\n", MaxSector
);
1087 else if(GET_STARTING_SECTOR(Entry
) > MaxOffset
)
1089 /* Invalid partition */
1090 DPRINT1("FSTUB: entry is invalid\n");
1091 DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry
));
1092 DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry
));
1093 DPRINT1("FSTUB: end %#I64x\n", EndingSector
);
1094 DPRINT1("FSTUB: maxOffset %#I64x\n", MaxOffset
);
1098 /* It's fine, return success */
1104 HalpCalculateChsValues(IN PLARGE_INTEGER PartitionOffset
,
1105 IN PLARGE_INTEGER PartitionLength
,
1106 IN CCHAR ShiftCount
,
1107 IN ULONG SectorsPerTrack
,
1108 IN ULONG NumberOfTracks
,
1109 IN ULONG ConventionalCylinders
,
1110 OUT PPARTITION_DESCRIPTOR PartitionDescriptor
)
1112 LARGE_INTEGER FirstSector
, SectorCount
;
1113 ULONG LastSector
, Remainder
, SectorsPerCylinder
;
1114 ULONG StartingCylinder
, EndingCylinder
;
1115 ULONG StartingTrack
, EndingTrack
;
1116 ULONG StartingSector
, EndingSector
;
1119 /* Calculate the number of sectors for each cylinder */
1120 SectorsPerCylinder
= SectorsPerTrack
* NumberOfTracks
;
1122 /* Calculate the first sector, and the sector count */
1123 FirstSector
.QuadPart
= PartitionOffset
->QuadPart
>> ShiftCount
;
1124 SectorCount
.QuadPart
= PartitionLength
->QuadPart
>> ShiftCount
;
1126 /* Now calculate the last sector */
1127 LastSector
= FirstSector
.LowPart
+ SectorCount
.LowPart
- 1;
1129 /* Calculate the first and last cylinders */
1130 StartingCylinder
= FirstSector
.LowPart
/ SectorsPerCylinder
;
1131 EndingCylinder
= LastSector
/ SectorsPerCylinder
;
1133 /* Set the default number of cylinders */
1134 if (!ConventionalCylinders
) ConventionalCylinders
= 1024;
1136 /* Normalize the values */
1137 if (StartingCylinder
>= ConventionalCylinders
)
1139 /* Set the maximum to 1023 */
1140 StartingCylinder
= ConventionalCylinders
- 1;
1142 if (EndingCylinder
>= ConventionalCylinders
)
1144 /* Set the maximum to 1023 */
1145 EndingCylinder
= ConventionalCylinders
- 1;
1148 /* Calculate the starting head and sector that still remain */
1149 Remainder
= FirstSector
.LowPart
% SectorsPerCylinder
;
1150 StartingTrack
= Remainder
/ SectorsPerTrack
;
1151 StartingSector
= Remainder
% SectorsPerTrack
;
1153 /* Calculate the ending head and sector that still remain */
1154 Remainder
= LastSector
% SectorsPerCylinder
;
1155 EndingTrack
= Remainder
/ SectorsPerTrack
;
1156 EndingSector
= Remainder
% SectorsPerTrack
;
1158 /* Set cylinder data for the MSB */
1159 PartitionDescriptor
->StartingCylinderMsb
= (UCHAR
)StartingCylinder
;
1160 PartitionDescriptor
->EndingCylinderMsb
= (UCHAR
)EndingCylinder
;
1162 /* Set the track data */
1163 PartitionDescriptor
->StartingTrack
= (UCHAR
)StartingTrack
;
1164 PartitionDescriptor
->EndingTrack
= (UCHAR
)EndingTrack
;
1166 /* Update cylinder data for the LSB */
1167 StartingCylinder
= ((StartingSector
+ 1) & 0x3F) |
1168 ((StartingCylinder
>> 2) & 0xC0);
1169 EndingCylinder
= ((EndingSector
+ 1) & 0x3F) |
1170 ((EndingCylinder
>> 2) & 0xC0);
1172 /* Set the cylinder data for the LSB */
1173 PartitionDescriptor
->StartingCylinderLsb
= (UCHAR
)StartingCylinder
;
1174 PartitionDescriptor
->EndingCylinderLsb
= (UCHAR
)EndingCylinder
;
1179 xHalGetPartialGeometry(IN PDEVICE_OBJECT DeviceObject
,
1180 IN PULONG ConventionalCylinders
,
1181 IN PLONGLONG DiskSize
)
1183 PDISK_GEOMETRY DiskGeometry
= NULL
;
1184 PIO_STATUS_BLOCK IoStatusBlock
= NULL
;
1185 PKEVENT Event
= NULL
;
1190 *ConventionalCylinders
= 0;
1193 /* Allocate the structure in nonpaged pool */
1194 DiskGeometry
= ExAllocatePoolWithTag(NonPagedPool
,
1195 sizeof(DISK_GEOMETRY
),
1197 if (!DiskGeometry
) goto Cleanup
;
1199 /* Allocate the status block in nonpaged pool */
1200 IoStatusBlock
= ExAllocatePoolWithTag(NonPagedPool
,
1201 sizeof(IO_STATUS_BLOCK
),
1203 if (!IoStatusBlock
) goto Cleanup
;
1205 /* Allocate the event in nonpaged pool too */
1206 Event
= ExAllocatePoolWithTag(NonPagedPool
,
1209 if (!Event
) goto Cleanup
;
1211 /* Initialize the event */
1212 KeInitializeEvent(Event
, NotificationEvent
, FALSE
);
1215 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
1220 sizeof(DISK_GEOMETRY
),
1224 if (!Irp
) goto Cleanup
;
1226 /* Now call the driver */
1227 Status
= IoCallDriver(DeviceObject
, Irp
);
1228 if (Status
== STATUS_PENDING
)
1230 /* Wait for it to complete */
1231 KeWaitForSingleObject(Event
, Executive
, KernelMode
, FALSE
, NULL
);
1232 Status
= IoStatusBlock
->Status
;
1235 /* Check driver status */
1236 if (NT_SUCCESS(Status
))
1238 /* Return the cylinder count */
1239 *ConventionalCylinders
= DiskGeometry
->Cylinders
.LowPart
;
1241 /* Make sure it's not larger then 1024 */
1242 if (DiskGeometry
->Cylinders
.LowPart
>= 1024)
1244 /* Otherwise, normalize the value */
1245 *ConventionalCylinders
= 1024;
1248 /* Calculate the disk size */
1249 *DiskSize
= DiskGeometry
->Cylinders
.QuadPart
*
1250 DiskGeometry
->TracksPerCylinder
*
1251 DiskGeometry
->SectorsPerTrack
*
1252 DiskGeometry
->BytesPerSector
;
1256 /* Free all the pointers */
1257 if (Event
) ExFreePoolWithTag(Event
, TAG_FILE_SYSTEM
);
1258 if (IoStatusBlock
) ExFreePoolWithTag(IoStatusBlock
, TAG_FILE_SYSTEM
);
1259 if (DiskGeometry
) ExFreePoolWithTag(DiskGeometry
, TAG_FILE_SYSTEM
);
1265 xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject
,
1266 IN ULONG SectorSize
,
1267 IN ULONG MbrTypeIdentifier
,
1268 OUT PVOID
*MbrBuffer
)
1270 LARGE_INTEGER Offset
;
1274 IO_STATUS_BLOCK IoStatusBlock
;
1276 PPARTITION_DESCRIPTOR PartitionDescriptor
;
1278 PIO_STACK_LOCATION IoStackLocation
;
1279 Offset
.QuadPart
= 0;
1281 /* Assume failure */
1284 /* Normalize the buffer size */
1285 BufferSize
= max(SectorSize
, 512);
1287 /* Allocate the buffer */
1288 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
1289 PAGE_SIZE
> BufferSize
?
1290 PAGE_SIZE
: BufferSize
,
1292 if (!Buffer
) return;
1294 /* Initialize the Event */
1295 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1298 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
1308 ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
1312 /* Make sure to override volume verification */
1313 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
1314 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
1316 /* Call the driver */
1317 Status
= IoCallDriver(DeviceObject
, Irp
);
1318 if (Status
== STATUS_PENDING
)
1320 /* Wait for completion */
1321 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1322 Status
= IoStatusBlock
.Status
;
1325 /* Check driver Status */
1326 if (NT_SUCCESS(Status
))
1328 /* Validate the MBR Signature */
1329 if (((PUSHORT
)Buffer
)[BOOT_SIGNATURE_OFFSET
] != BOOT_RECORD_SIGNATURE
)
1332 ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
1336 /* Get the partition entry */
1337 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1338 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1340 /* Make sure it's what the caller wanted */
1341 if (PartitionDescriptor
->PartitionType
!= MbrTypeIdentifier
)
1343 /* It's not, free our buffer */
1344 ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
1348 /* Check if this is a secondary entry */
1349 if (PartitionDescriptor
->PartitionType
== 0x54)
1351 /* Return our buffer, but at sector 63 */
1352 *(PULONG
)Buffer
= 63;
1353 *MbrBuffer
= Buffer
;
1355 else if (PartitionDescriptor
->PartitionType
== 0x55)
1357 /* EZ Drive, return the buffer directly */
1358 *MbrBuffer
= Buffer
;
1362 /* Otherwise crash on debug builds */
1363 ASSERT(PartitionDescriptor
->PartitionType
== 0x55);
1371 FstubFixupEfiPartition(IN PPARTITION_DESCRIPTOR PartitionDescriptor
,
1372 IN ULONGLONG MaxOffset
)
1374 ULONG PartitionMaxOffset
, PartitionLength
;
1377 /* Compute partition length (according to MBR entry) */
1378 PartitionMaxOffset
= GET_STARTING_SECTOR(PartitionDescriptor
) + GET_PARTITION_LENGTH(PartitionDescriptor
);
1379 /* In case the partition length goes beyond disk size... */
1380 if (PartitionMaxOffset
> MaxOffset
)
1382 /* Resize partition to its maximum real length */
1383 PartitionLength
= (ULONG
)(PartitionMaxOffset
- GET_STARTING_SECTOR(PartitionDescriptor
));
1384 SET_PARTITION_LENGTH(PartitionDescriptor
, PartitionLength
);
1390 xHalIoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject
,
1391 IN ULONG SectorSize
,
1392 IN BOOLEAN ReturnRecognizedPartitions
,
1393 IN OUT PDRIVE_LAYOUT_INFORMATION
*PartitionBuffer
)
1396 IO_STATUS_BLOCK IoStatusBlock
;
1398 PPARTITION_DESCRIPTOR PartitionDescriptor
;
1401 PPARTITION_INFORMATION PartitionInfo
;
1402 PUCHAR Buffer
= NULL
;
1403 ULONG BufferSize
= 2048, InputSize
;
1404 PDRIVE_LAYOUT_INFORMATION DriveLayoutInfo
= NULL
;
1405 LONG j
= -1, i
= -1, k
;
1406 DISK_GEOMETRY DiskGeometry
;
1407 LONGLONG EndSector
, MaxSector
, StartOffset
;
1408 ULONGLONG MaxOffset
;
1409 LARGE_INTEGER Offset
, VolumeOffset
;
1410 BOOLEAN IsPrimary
= TRUE
, IsEzDrive
= FALSE
, MbrFound
= FALSE
;
1411 BOOLEAN IsValid
, IsEmpty
= TRUE
;
1413 PIO_STACK_LOCATION IoStackLocation
;
1414 PBOOT_SECTOR_INFO BootSectorInfo
= (PBOOT_SECTOR_INFO
)Buffer
;
1415 UCHAR PartitionType
;
1416 LARGE_INTEGER HiddenSectors64
;
1417 VolumeOffset
.QuadPart
= Offset
.QuadPart
= 0;
1420 /* Allocate the buffer */
1421 *PartitionBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1424 if (!(*PartitionBuffer
)) return STATUS_INSUFFICIENT_RESOURCES
;
1426 /* Normalize the buffer size */
1427 InputSize
= max(512, SectorSize
);
1429 /* Check for EZ Drive */
1430 HalExamineMBR(DeviceObject
, InputSize
, 0x55, &MbrBuffer
);
1433 /* EZ Drive found, bias the offset */
1435 ExFreePoolWithTag(MbrBuffer
, TAG_FILE_SYSTEM
);
1436 Offset
.QuadPart
= 512;
1439 /* Get drive geometry */
1440 Status
= HalpGetFullGeometry(DeviceObject
, &DiskGeometry
, &MaxOffset
);
1441 if (!NT_SUCCESS(Status
))
1443 ExFreePoolWithTag(*PartitionBuffer
, TAG_FILE_SYSTEM
);
1444 *PartitionBuffer
= NULL
;
1448 /* Get the end and maximum sector */
1449 EndSector
= MaxOffset
;
1450 MaxSector
= MaxOffset
<< 1;
1451 DPRINT("FSTUB: MaxOffset = %#I64x, MaxSector = %#I64x\n",
1452 MaxOffset
, MaxSector
);
1454 /* Allocate our buffer */
1455 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, InputSize
, TAG_FILE_SYSTEM
);
1458 /* Fail, free the input buffer */
1459 ExFreePoolWithTag(*PartitionBuffer
, TAG_FILE_SYSTEM
);
1460 *PartitionBuffer
= NULL
;
1461 return STATUS_INSUFFICIENT_RESOURCES
;
1464 /* Start partition loop */
1467 /* Assume the partition is valid */
1470 /* Initialize the event */
1471 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1473 /* Clear the buffer and build the IRP */
1474 RtlZeroMemory(Buffer
, InputSize
);
1475 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
1485 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1489 /* Make sure to disable volume verification */
1490 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
1491 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
1493 /* Call the driver */
1494 Status
= IoCallDriver(DeviceObject
, Irp
);
1495 if (Status
== STATUS_PENDING
)
1497 /* Wait for completion */
1498 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1499 Status
= IoStatusBlock
.Status
;
1502 /* Normalize status code and check for failure */
1503 if (Status
== STATUS_NO_DATA_DETECTED
) Status
= STATUS_SUCCESS
;
1504 if (!NT_SUCCESS(Status
)) break;
1506 /* If we biased for EZ-Drive, unbias now */
1507 if (IsEzDrive
&& (Offset
.QuadPart
== 512)) Offset
.QuadPart
= 0;
1509 /* Make sure this is a valid MBR */
1510 if (((PUSHORT
)Buffer
)[BOOT_SIGNATURE_OFFSET
] != BOOT_RECORD_SIGNATURE
)
1512 /* It's not, fail */
1513 DPRINT1("FSTUB: (IoReadPartitionTable) No 0xaa55 found in "
1514 "partition table %d\n", j
+ 1);
1518 /* At this point we have a valid MBR */
1521 /* Check if we weren't given an offset */
1522 if (!Offset
.QuadPart
)
1524 /* Then read the signature off the disk */
1525 (*PartitionBuffer
)->Signature
= ((PULONG
)Buffer
)
1526 [PARTITION_TABLE_OFFSET
/ 2 - 1];
1529 /* Get the partition descriptor array */
1530 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1531 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1533 /* Start looping partitions */
1535 DPRINT("FSTUB: Partition Table %d:\n", j
);
1536 for (Entry
= 1, k
= 0; Entry
<= 4; Entry
++, PartitionDescriptor
++)
1538 /* Get the partition type */
1539 PartitionType
= PartitionDescriptor
->PartitionType
;
1541 /* Print debug messages */
1542 DPRINT("Partition Entry %d,%d: type %#x %s\n",
1546 (PartitionDescriptor
->ActiveFlag
) ? "Active" : "");
1547 DPRINT("\tOffset %#08lx for %#08lx Sectors\n",
1548 GET_STARTING_SECTOR(PartitionDescriptor
),
1549 GET_PARTITION_LENGTH(PartitionDescriptor
));
1551 /* Check whether we're facing a protective MBR */
1552 if (PartitionType
== EFI_PMBR_OSTYPE_EFI
)
1554 /* Partition length might be bigger than disk size */
1555 FstubFixupEfiPartition(PartitionDescriptor
,
1559 /* Make sure that the partition is valid, unless it's the first */
1560 if (!(HalpIsValidPartitionEntry(PartitionDescriptor
,
1562 MaxSector
)) && !(j
))
1564 /* It's invalid, so fail */
1569 /* Check if it's a container */
1570 if (IsContainerPartition(PartitionType
))
1572 /* Increase the count of containers */
1575 /* More then one table is invalid */
1576 DPRINT1("FSTUB: Multiple container partitions found in "
1577 "partition table %d\n - table is invalid\n",
1584 /* Check if the partition is supposedly empty */
1587 /* But check if it actually has a start and/or length */
1588 if ((GET_STARTING_SECTOR(PartitionDescriptor
)) ||
1589 (GET_PARTITION_LENGTH(PartitionDescriptor
)))
1591 /* So then it's not really empty */
1596 /* Check if the caller wanted only recognized partitions */
1597 if (ReturnRecognizedPartitions
)
1599 /* Then check if this one is unused, or a container */
1600 if ((PartitionType
== PARTITION_ENTRY_UNUSED
) ||
1601 IsContainerPartition(PartitionType
))
1603 /* Skip it, since the caller doesn't want it */
1608 /* Increase the structure count and check if they can fit */
1609 if ((sizeof(DRIVE_LAYOUT_INFORMATION
) +
1610 (++i
* sizeof(PARTITION_INFORMATION
))) >
1613 /* Allocate a new buffer that's twice as big */
1614 DriveLayoutInfo
= ExAllocatePoolWithTag(NonPagedPool
,
1617 if (!DriveLayoutInfo
)
1619 /* Out of memory, unto this extra structure */
1621 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1625 /* Copy the contents of the old buffer */
1626 RtlMoveMemory(DriveLayoutInfo
,
1630 /* Free the old buffer and set this one as the new one */
1631 ExFreePoolWithTag(*PartitionBuffer
, TAG_FILE_SYSTEM
);
1632 *PartitionBuffer
= DriveLayoutInfo
;
1634 /* Double the size */
1638 /* Now get the current structure being filled and initialize it */
1639 PartitionInfo
= &(*PartitionBuffer
)->PartitionEntry
[i
];
1640 PartitionInfo
->PartitionType
= PartitionType
;
1641 PartitionInfo
->RewritePartition
= FALSE
;
1643 /* Check if we're dealing with a partition that's in use */
1644 if (PartitionType
!= PARTITION_ENTRY_UNUSED
)
1646 /* Check if it's bootable */
1647 PartitionInfo
->BootIndicator
= PartitionDescriptor
->
1651 /* Check if its' a container */
1652 if (IsContainerPartition(PartitionType
))
1654 /* Then don't recognize it and use the volume offset */
1655 PartitionInfo
->RecognizedPartition
= FALSE
;
1656 StartOffset
= VolumeOffset
.QuadPart
;
1660 /* Then recognize it and use the partition offset */
1661 PartitionInfo
->RecognizedPartition
= TRUE
;
1662 StartOffset
= Offset
.QuadPart
;
1665 /* Get the starting offset */
1666 PartitionInfo
->StartingOffset
.QuadPart
=
1668 UInt32x32To64(GET_STARTING_SECTOR(PartitionDescriptor
),
1671 /* Calculate the number of hidden sectors */
1672 HiddenSectors64
.QuadPart
= (PartitionInfo
->
1673 StartingOffset
.QuadPart
-
1676 PartitionInfo
->HiddenSectors
= HiddenSectors64
.LowPart
;
1678 /* Get the partition length */
1679 PartitionInfo
->PartitionLength
.QuadPart
=
1680 UInt32x32To64(GET_PARTITION_LENGTH(PartitionDescriptor
),
1683 /* FIXME: REACTOS HACK */
1684 PartitionInfo
->PartitionNumber
= i
+ 1;
1688 /* Otherwise, clear all the relevant fields */
1689 PartitionInfo
->BootIndicator
= FALSE
;
1690 PartitionInfo
->RecognizedPartition
= FALSE
;
1691 PartitionInfo
->StartingOffset
.QuadPart
= 0;
1692 PartitionInfo
->PartitionLength
.QuadPart
= 0;
1693 PartitionInfo
->HiddenSectors
= 0;
1695 /* FIXME: REACTOS HACK */
1696 PartitionInfo
->PartitionNumber
= 0;
1700 /* Finish debug log, and check for failure */
1702 if (!NT_SUCCESS(Status
)) break;
1704 /* Also check if we hit an invalid entry here */
1707 /* We did, so break out of the loop minus one entry */
1712 /* Reset the offset */
1713 Offset
.QuadPart
= 0;
1715 /* Go back to the descriptor array and loop it */
1716 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1717 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1718 for (Entry
= 1; Entry
<= 4; Entry
++, PartitionDescriptor
++)
1720 /* Check if this is a container partition, since we skipped them */
1721 if (IsContainerPartition(PartitionDescriptor
->PartitionType
))
1723 /* Get its offset */
1724 Offset
.QuadPart
= VolumeOffset
.QuadPart
+
1726 GET_STARTING_SECTOR(PartitionDescriptor
),
1729 /* If this is a primary partition, this is the volume offset */
1730 if (IsPrimary
) VolumeOffset
= Offset
;
1732 /* Also update the maximum sector */
1733 MaxSector
= GET_PARTITION_LENGTH(PartitionDescriptor
);
1734 DPRINT1("FSTUB: MaxSector now = %#08lx\n", MaxSector
);
1739 /* Loop the next partitions, which are not primary anymore */
1741 } while (Offset
.HighPart
| Offset
.LowPart
);
1743 /* Check if this is a removable device that's probably a super-floppy */
1744 if ((DiskGeometry
.MediaType
== RemovableMedia
) &&
1749 /* Read the jump bytes to detect super-floppy */
1750 if ((BootSectorInfo
->JumpByte
[0] == 0xeb) ||
1751 (BootSectorInfo
->JumpByte
[0] == 0xe9))
1753 /* Super floppes don't have typical MBRs, so skip them */
1754 DPRINT1("FSTUB: Jump byte %#x found along with empty partition "
1755 "table - disk is a super floppy and has no valid MBR\n",
1756 BootSectorInfo
->JumpByte
);
1761 /* Check if we're still at partition -1 */
1764 /* The likely cause is the super floppy detection above */
1765 if ((MbrFound
) || (DiskGeometry
.MediaType
== RemovableMedia
))
1767 /* Print out debugging information */
1768 DPRINT1("FSTUB: Drive %#p has no valid MBR. Make it into a "
1771 DPRINT1("FSTUB: Drive has %#08lx sectors and is %#016I64x "
1773 EndSector
, EndSector
* DiskGeometry
.BytesPerSector
);
1775 /* We should at least have some sectors */
1778 /* Get the entry we'll use */
1779 PartitionInfo
= &(*PartitionBuffer
)->PartitionEntry
[0];
1781 /* Fill it out with data for a super-floppy */
1782 PartitionInfo
->RewritePartition
= FALSE
;
1783 PartitionInfo
->RecognizedPartition
= TRUE
;
1784 PartitionInfo
->PartitionType
= PARTITION_FAT_16
;
1785 PartitionInfo
->BootIndicator
= FALSE
;
1786 PartitionInfo
->HiddenSectors
= 0;
1787 PartitionInfo
->StartingOffset
.QuadPart
= 0;
1788 PartitionInfo
->PartitionLength
.QuadPart
= (EndSector
*
1792 /* FIXME: REACTOS HACK */
1793 PartitionInfo
->PartitionNumber
= 0;
1795 /* Set the signature and set the count back to 0 */
1796 (*PartitionBuffer
)->Signature
= 1;
1802 /* Otherwise, this isn't a super floppy, so set an invalid count */
1807 /* Set the partition count */
1808 (*PartitionBuffer
)->PartitionCount
= ++i
;
1810 /* If we have no count, delete the signature */
1811 if (!i
) (*PartitionBuffer
)->Signature
= 0;
1813 /* Free the buffer and check for success */
1814 if (Buffer
) ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
1815 if (!NT_SUCCESS(Status
)) ExFreePoolWithTag(*PartitionBuffer
, TAG_FILE_SYSTEM
);
1823 xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject
,
1824 IN ULONG SectorSize
,
1825 IN ULONG PartitionNumber
,
1826 IN ULONG PartitionType
)
1830 IO_STATUS_BLOCK IoStatusBlock
;
1832 LARGE_INTEGER Offset
, VolumeOffset
;
1833 PUCHAR Buffer
= NULL
;
1837 PPARTITION_DESCRIPTOR PartitionDescriptor
;
1838 BOOLEAN IsPrimary
= TRUE
, IsEzDrive
= FALSE
;
1840 PIO_STACK_LOCATION IoStackLocation
;
1841 VolumeOffset
.QuadPart
= Offset
.QuadPart
= 0;
1844 /* Normalize the buffer size */
1845 BufferSize
= max(512, SectorSize
);
1847 /* Check for EZ Drive */
1848 HalExamineMBR(DeviceObject
, BufferSize
, 0x55, &MbrBuffer
);
1851 /* EZ Drive found, bias the offset */
1853 ExFreePoolWithTag(MbrBuffer
, TAG_FILE_SYSTEM
);
1854 Offset
.QuadPart
= 512;
1857 /* Allocate our partition buffer */
1858 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, PAGE_SIZE
, TAG_FILE_SYSTEM
);
1859 if (!Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
1861 /* Initialize the event we'll use and loop partitions */
1862 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1865 /* Reset the event since we reuse it */
1866 KeResetEvent(&Event
);
1868 /* Build the read IRP */
1869 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
1879 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1883 /* Make sure to disable volume verification */
1884 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
1885 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
1887 /* Call the driver */
1888 Status
= IoCallDriver(DeviceObject
, Irp
);
1889 if (Status
== STATUS_PENDING
)
1891 /* Wait for completion */
1892 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1893 Status
= IoStatusBlock
.Status
;
1896 /* Check for failure */
1897 if (!NT_SUCCESS(Status
)) break;
1899 /* If we biased for EZ-Drive, unbias now */
1900 if (IsEzDrive
&& (Offset
.QuadPart
== 512)) Offset
.QuadPart
= 0;
1902 /* Make sure this is a valid MBR */
1903 if (((PUSHORT
)Buffer
)[BOOT_SIGNATURE_OFFSET
] != BOOT_RECORD_SIGNATURE
)
1905 /* It's not, fail */
1906 Status
= STATUS_BAD_MASTER_BOOT_RECORD
;
1910 /* Get the partition descriptors and loop them */
1911 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1912 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1913 for (Entry
= 1; Entry
<= 4; Entry
++, PartitionDescriptor
++)
1915 /* Check if it's unused or a container partition */
1916 if ((PartitionDescriptor
->PartitionType
==
1917 PARTITION_ENTRY_UNUSED
) ||
1918 (IsContainerPartition(PartitionDescriptor
->PartitionType
)))
1920 /* Go to the next one */
1924 /* It's a valid partition, so increase the partition count */
1925 if (++i
== PartitionNumber
)
1927 /* We found a match, set the type */
1928 PartitionDescriptor
->PartitionType
= (UCHAR
)PartitionType
;
1930 /* Reset the reusable event */
1931 KeResetEvent(&Event
);
1933 /* Build the write IRP */
1934 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
1944 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1948 /* Disable volume verification */
1949 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
1950 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
1952 /* Call the driver */
1953 Status
= IoCallDriver(DeviceObject
, Irp
);
1954 if (Status
== STATUS_PENDING
)
1956 /* Wait for completion */
1957 KeWaitForSingleObject(&Event
,
1962 Status
= IoStatusBlock
.Status
;
1965 /* We're done, break out of the loop */
1970 /* If we looped all the partitions, break out */
1971 if (Entry
<= NUM_PARTITION_TABLE_ENTRIES
) break;
1973 /* Nothing found yet, get the partition array again */
1974 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1975 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1976 for (Entry
= 1; Entry
<= 4; Entry
++, PartitionDescriptor
++)
1978 /* Check if this was a container partition (we skipped these) */
1979 if (IsContainerPartition(PartitionDescriptor
->PartitionType
))
1981 /* Update the partition offset */
1982 Offset
.QuadPart
= VolumeOffset
.QuadPart
+
1983 GET_STARTING_SECTOR(PartitionDescriptor
) *
1986 /* If this was the primary partition, update the volume too */
1987 if (IsPrimary
) VolumeOffset
= Offset
;
1992 /* Check if we already searched all the partitions */
1993 if (Entry
> NUM_PARTITION_TABLE_ENTRIES
)
1995 /* Then we failed to find a good MBR */
1996 Status
= STATUS_BAD_MASTER_BOOT_RECORD
;
2000 /* Loop the next partitions, which are not primary anymore */
2002 } while (i
< PartitionNumber
);
2004 /* Everything done, cleanup */
2005 if (Buffer
) ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
2011 xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject
,
2012 IN ULONG SectorSize
,
2013 IN ULONG SectorsPerTrack
,
2014 IN ULONG NumberOfHeads
,
2015 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer
)
2018 IO_STATUS_BLOCK IoStatusBlock
;
2020 NTSTATUS Status
= STATUS_SUCCESS
;
2024 PPARTITION_TABLE PartitionTable
;
2025 LARGE_INTEGER Offset
, NextOffset
, ExtendedOffset
, SectorOffset
;
2026 LARGE_INTEGER StartOffset
, PartitionLength
;
2029 BOOLEAN IsEzDrive
= FALSE
, IsSuperFloppy
= FALSE
, DoRewrite
= FALSE
, IsMbr
;
2030 ULONG ConventionalCylinders
;
2032 PDISK_LAYOUT DiskLayout
= (PDISK_LAYOUT
)PartitionBuffer
;
2034 UCHAR PartitionType
;
2035 PIO_STACK_LOCATION IoStackLocation
;
2036 PPARTITION_INFORMATION PartitionInfo
= PartitionBuffer
->PartitionEntry
;
2037 PPARTITION_INFORMATION TableEntry
;
2038 ExtendedOffset
.QuadPart
= NextOffset
.QuadPart
= Offset
.QuadPart
= 0;
2041 /* Normalize the buffer size */
2042 BufferSize
= max(512, SectorSize
);
2044 /* Get the partial drive geometry */
2045 xHalGetPartialGeometry(DeviceObject
, &ConventionalCylinders
, &DiskSize
);
2047 /* Check for EZ Drive */
2048 HalExamineMBR(DeviceObject
, BufferSize
, 0x55, &MbrBuffer
);
2051 /* EZ Drive found, bias the offset */
2053 ExFreePoolWithTag(MbrBuffer
, TAG_FILE_SYSTEM
);
2054 Offset
.QuadPart
= 512;
2057 /* Get the number of bits to shift to multiply by the sector size */
2058 for (k
= 0; k
< 32; k
++) if ((SectorSize
>> k
) == 1) break;
2060 /* Check if there's only one partition */
2061 if (PartitionBuffer
->PartitionCount
== 1)
2063 /* Check if it has no starting offset or hidden sectors */
2064 if (!(PartitionInfo
->StartingOffset
.QuadPart
) &&
2065 !(PartitionInfo
->HiddenSectors
))
2067 /* Then it's a super floppy */
2068 IsSuperFloppy
= TRUE
;
2070 /* Which also means it must be non-bootable FAT-16 */
2071 if ((PartitionInfo
->PartitionNumber
) ||
2072 (PartitionInfo
->PartitionType
!= PARTITION_FAT_16
) ||
2073 (PartitionInfo
->BootIndicator
))
2075 /* It's not, so we fail */
2076 return STATUS_INVALID_PARAMETER
;
2079 /* Check if it needs a rewrite, and disable EZ drive for sure */
2080 if (PartitionInfo
->RewritePartition
) DoRewrite
= TRUE
;
2085 /* Count the number of partition tables */
2086 DiskLayout
->TableCount
= (PartitionBuffer
->PartitionCount
+ 4 - 1) / 4;
2088 /* Allocate our partition buffer */
2089 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, PAGE_SIZE
, TAG_FILE_SYSTEM
);
2090 if (!Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
2092 /* Loop the entries */
2093 Entry
= (PPTE
)&Buffer
[PARTITION_TABLE_OFFSET
];
2094 for (i
= 0; i
< DiskLayout
->TableCount
; i
++)
2096 /* Set if this is the MBR partition */
2099 /* Initialize th event */
2100 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
2102 /* Build the read IRP */
2103 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
2113 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2117 /* Make sure to disable volume verification */
2118 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
2119 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
2121 /* Call the driver */
2122 Status
= IoCallDriver(DeviceObject
, Irp
);
2123 if (Status
== STATUS_PENDING
)
2125 /* Wait for completion */
2126 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
2127 Status
= IoStatusBlock
.Status
;
2130 /* Check for failure */
2131 if (!NT_SUCCESS(Status
)) break;
2133 /* If we biased for EZ-Drive, unbias now */
2134 if (IsEzDrive
&& (Offset
.QuadPart
== 512)) Offset
.QuadPart
= 0;
2136 /* Check if this is a normal disk */
2139 /* Set the boot record signature */
2140 Buffer
[BOOT_SIGNATURE_OFFSET
] = BOOT_RECORD_SIGNATURE
;
2142 /* By default, don't require a rewrite */
2145 /* Check if we don't have an offset */
2146 if (!Offset
.QuadPart
)
2148 /* Check if the signature doesn't match */
2149 if (((PULONG
)Buffer
)[PARTITION_TABLE_OFFSET
/ 2 - 1] !=
2150 PartitionBuffer
->Signature
)
2152 /* Then write the signature and now w need a rewrite */
2153 ((PULONG
)Buffer
)[PARTITION_TABLE_OFFSET
/ 2 - 1] =
2154 PartitionBuffer
->Signature
;
2159 /* Loop the partition table entries */
2160 PartitionTable
= &DiskLayout
->PartitionTable
[i
];
2161 for (j
= 0; j
< 4; j
++)
2163 /* Get the current entry and type */
2164 TableEntry
= &PartitionTable
->PartitionEntry
[j
];
2165 PartitionType
= TableEntry
->PartitionType
;
2167 /* Check if the entry needs a rewrite */
2168 if (TableEntry
->RewritePartition
)
2170 /* Then we need one too */
2173 /* Save the type and if it's a bootable partition */
2174 Entry
[j
].PartitionType
= TableEntry
->PartitionType
;
2175 Entry
[j
].ActiveFlag
= TableEntry
->BootIndicator
? 0x80 : 0;
2177 /* Make sure it's used */
2178 if (PartitionType
!= PARTITION_ENTRY_UNUSED
)
2180 /* Make sure it's not a container (unless primary) */
2181 if ((IsMbr
) || !(IsContainerPartition(PartitionType
)))
2183 /* Use the partition offset */
2184 StartOffset
.QuadPart
= Offset
.QuadPart
;
2188 /* Use the extended logical partition offset */
2189 StartOffset
.QuadPart
= ExtendedOffset
.QuadPart
;
2192 /* Set the sector offset */
2193 SectorOffset
.QuadPart
= TableEntry
->
2194 StartingOffset
.QuadPart
-
2195 StartOffset
.QuadPart
;
2197 /* Now calculate the starting sector */
2198 StartOffset
.QuadPart
= SectorOffset
.QuadPart
>> k
;
2199 Entry
[j
].StartingSector
= StartOffset
.LowPart
;
2201 /* As well as the length */
2202 PartitionLength
.QuadPart
= TableEntry
->PartitionLength
.
2204 Entry
[j
].PartitionLength
= PartitionLength
.LowPart
;
2206 /* Calculate the CHS values */
2207 HalpCalculateChsValues(&TableEntry
->StartingOffset
,
2208 &TableEntry
->PartitionLength
,
2212 ConventionalCylinders
,
2213 (PPARTITION_DESCRIPTOR
)
2218 /* Otherwise set up an empty entry */
2219 Entry
[j
].StartingSector
= 0;
2220 Entry
[j
].PartitionLength
= 0;
2221 Entry
[j
].StartingTrack
= 0;
2222 Entry
[j
].EndingTrack
= 0;
2223 Entry
[j
].StartingCylinder
= 0;
2224 Entry
[j
].EndingCylinder
= 0;
2228 /* Check if this is a container partition */
2229 if (IsContainerPartition(PartitionType
))
2231 /* Then update the offset to use */
2232 NextOffset
= TableEntry
->StartingOffset
;
2237 /* Check if we need to write back the buffer */
2240 /* We don't need to do this again */
2243 /* Initialize the event */
2244 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
2246 /* If we unbiased for EZ-Drive, rebias now */
2247 if ((IsEzDrive
) && !(Offset
.QuadPart
)) Offset
.QuadPart
= 512;
2249 /* Build the write IRP */
2250 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
2260 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2264 /* Make sure to disable volume verification */
2265 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
2266 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
2268 /* Call the driver */
2269 Status
= IoCallDriver(DeviceObject
, Irp
);
2270 if (Status
== STATUS_PENDING
)
2272 /* Wait for completion */
2273 KeWaitForSingleObject(&Event
,
2278 Status
= IoStatusBlock
.Status
;
2281 /* Check for failure */
2282 if (!NT_SUCCESS(Status
)) break;
2284 /* If we biased for EZ-Drive, unbias now */
2285 if (IsEzDrive
&& (Offset
.QuadPart
== 512)) Offset
.QuadPart
= 0;
2288 /* Update the partition offset and set the extended offset if needed */
2289 Offset
= NextOffset
;
2290 if (IsMbr
) ExtendedOffset
= NextOffset
;
2293 /* If we had a buffer, free it, then return status */
2294 if (Buffer
) ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
2298 /* PUBLIC FUNCTIONS **********************************************************/
2305 HalExamineMBR(IN PDEVICE_OBJECT DeviceObject
,
2306 IN ULONG SectorSize
,
2307 IN ULONG MbrTypeIdentifier
,
2308 OUT PVOID
*MbrBuffer
)
2310 HALDISPATCH
->HalExamineMBR(DeviceObject
,
2321 IoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject
,
2322 IN ULONG SectorSize
,
2323 IN BOOLEAN ReturnRecognizedPartitions
,
2324 IN OUT PDRIVE_LAYOUT_INFORMATION
*PartitionBuffer
)
2326 return HALDISPATCH
->HalIoReadPartitionTable(DeviceObject
,
2328 ReturnRecognizedPartitions
,
2337 IoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject
,
2338 IN ULONG SectorSize
,
2339 IN ULONG PartitionNumber
,
2340 IN ULONG PartitionType
)
2342 return HALDISPATCH
->HalIoSetPartitionInformation(DeviceObject
,
2353 IoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject
,
2354 IN ULONG SectorSize
,
2355 IN ULONG SectorsPerTrack
,
2356 IN ULONG NumberOfHeads
,
2357 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer
)
2359 return HALDISPATCH
->HalIoWritePartitionTable(DeviceObject
,
2371 IoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
2372 IN PSTRING NtDeviceName
,
2373 OUT PUCHAR NtSystemPath
,
2374 OUT PSTRING NtSystemPathString
)
2376 HALDISPATCH
->HalIoAssignDriveLetters(LoaderBlock
,
2379 NtSystemPathString
);