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
29 typedef struct _REG_DISK_MOUNT_INFO
32 LARGE_INTEGER StartingOffset
;
33 } REG_DISK_MOUNT_INFO
, *PREG_DISK_MOUNT_INFO
;
37 typedef enum _DISK_MANAGER
45 HalpAssignDrive(IN PUNICODE_STRING PartitionName
,
49 IN LARGE_INTEGER StartingOffset
,
51 IN PUNICODE_STRING BootDevice
,
52 OUT PUCHAR NtSystemPath
)
54 WCHAR DriveNameBuffer
[16];
55 UNICODE_STRING DriveName
;
58 REG_DISK_MOUNT_INFO DiskMountInfo
;
60 DPRINT("HalpAssignDrive()\n");
62 if ((DriveNumber
!= AUTO_DRIVE
) && (DriveNumber
< 26))
64 /* Force assignment */
65 if ((ObSystemDeviceMap
->DriveMap
& (1 << DriveNumber
)) != 0)
67 DbgPrint("Drive letter already used!\n");
73 /* Automatic assignment */
74 DriveNumber
= AUTO_DRIVE
;
76 for (i
= 2; i
< 26; i
++)
78 if ((ObSystemDeviceMap
->DriveMap
& (1 << i
)) == 0)
85 if (DriveNumber
== AUTO_DRIVE
)
87 DbgPrint("No drive letter available!\n");
92 DPRINT("DriveNumber %d\n", DriveNumber
);
94 /* Update the System Device Map */
95 ObSystemDeviceMap
->DriveMap
|= (1 << DriveNumber
);
96 ObSystemDeviceMap
->DriveType
[DriveNumber
] = DriveType
;
98 /* Build drive name */
99 swprintf(DriveNameBuffer
,
102 RtlInitUnicodeString(&DriveName
,
105 DPRINT(" %wZ ==> %wZ\n",
109 /* Create symbolic link */
110 Status
= IoCreateSymbolicLink(&DriveName
,
114 DriveType
== DOSDEVICE_DRIVE_FIXED
&&
117 DiskMountInfo
.Signature
= Signature
;
118 DiskMountInfo
.StartingOffset
= StartingOffset
;
119 swprintf(DriveNameBuffer
, DiskMountString
, L
'A' + DriveNumber
);
120 RtlInitUnicodeString(&DriveName
, DriveNameBuffer
);
122 Status
= ZwSetValueKey(hKey
,
127 sizeof(DiskMountInfo
));
128 if (!NT_SUCCESS(Status
))
130 DPRINT1("ZwCreateValueKey failed for %wZ, status=%x\n", &DriveName
, Status
);
134 /* Check if this is a boot partition */
135 if (RtlCompareUnicodeString(PartitionName
, BootDevice
, FALSE
) == 0)
137 /* Set NtSystemPath to that partition's disk letter */
138 *NtSystemPath
= (UCHAR
)('A' + DriveNumber
);
145 xHalpGetRDiskCount(VOID
)
148 UNICODE_STRING ArcName
;
149 PWCHAR ArcNameBuffer
;
150 OBJECT_ATTRIBUTES ObjectAttributes
;
151 HANDLE DirectoryHandle
;
152 POBJECT_DIRECTORY_INFORMATION DirectoryInfo
;
157 BOOLEAN First
= TRUE
;
160 DirectoryInfo
= ExAllocatePool(PagedPool
, 2 * PAGE_SIZE
);
161 if (DirectoryInfo
== NULL
)
166 RtlInitUnicodeString(&ArcName
, L
"\\ArcName");
167 InitializeObjectAttributes(&ObjectAttributes
,
173 Status
= ZwOpenDirectoryObject (&DirectoryHandle
,
174 SYMBOLIC_LINK_ALL_ACCESS
,
176 if (!NT_SUCCESS(Status
))
178 DPRINT1("ZwOpenDirectoryObject for %wZ failed, status=%lx\n", &ArcName
, Status
);
179 ExFreePool(DirectoryInfo
);
185 while (NT_SUCCESS(Status
))
187 Status
= NtQueryDirectoryObject (DirectoryHandle
,
195 if (NT_SUCCESS(Status
))
198 while (DirectoryInfo
[Count
].Name
.Buffer
)
200 DPRINT("Count %x\n", Count
);
201 DirectoryInfo
[Count
].Name
.Buffer
[DirectoryInfo
[Count
].Name
.Length
/ sizeof(WCHAR
)] = 0;
202 ArcNameBuffer
= DirectoryInfo
[Count
].Name
.Buffer
;
203 if (DirectoryInfo
[Count
].Name
.Length
>= sizeof(L
"multi(0)disk(0)rdisk(0)") - sizeof(WCHAR
) &&
204 !_wcsnicmp(ArcNameBuffer
, L
"multi(0)disk(0)rdisk(", (sizeof(L
"multi(0)disk(0)rdisk(") - sizeof(WCHAR
)) / sizeof(WCHAR
)))
206 DPRINT("%S\n", ArcNameBuffer
);
207 ArcNameBuffer
+= (sizeof(L
"multi(0)disk(0)rdisk(") - sizeof(WCHAR
)) / sizeof(WCHAR
);
209 while (iswdigit(*ArcNameBuffer
))
211 CurrentRDisk
= CurrentRDisk
* 10 + *ArcNameBuffer
- L
'0';
214 if (!_wcsicmp(ArcNameBuffer
, L
")") &&
215 CurrentRDisk
>= RDiskCount
)
217 RDiskCount
= CurrentRDisk
+ 1;
224 ExFreePool(DirectoryInfo
);
229 xHalpGetDiskNumberFromRDisk(ULONG RDisk
, PULONG DiskNumber
)
231 WCHAR NameBuffer
[80];
232 UNICODE_STRING ArcName
;
233 UNICODE_STRING LinkName
;
234 OBJECT_ATTRIBUTES ObjectAttributes
;
239 L
"\\ArcName\\multi(0)disk(0)rdisk(%lu)",
242 RtlInitUnicodeString(&ArcName
, NameBuffer
);
243 InitializeObjectAttributes(&ObjectAttributes
,
248 Status
= ZwOpenSymbolicLinkObject(&LinkHandle
,
249 SYMBOLIC_LINK_ALL_ACCESS
,
251 if (!NT_SUCCESS(Status
))
253 DPRINT1("ZwOpenSymbolicLinkObject failed for %wZ, status=%lx\n", &ArcName
, Status
);
257 LinkName
.Buffer
= NameBuffer
;
259 LinkName
.MaximumLength
= sizeof(NameBuffer
);
260 Status
= ZwQuerySymbolicLinkObject(LinkHandle
,
264 if (!NT_SUCCESS(Status
))
266 DPRINT1("ZwQuerySymbolicLinkObject failed, status=%lx\n", Status
);
269 if (LinkName
.Length
< sizeof(L
"\\Device\\Harddisk0\\Partition0") - sizeof(WCHAR
) ||
270 LinkName
.Length
>= sizeof(NameBuffer
))
272 return STATUS_UNSUCCESSFUL
;
275 NameBuffer
[LinkName
.Length
/ sizeof(WCHAR
)] = 0;
276 if (_wcsnicmp(NameBuffer
, L
"\\Device\\Harddisk", (sizeof(L
"\\Device\\Harddisk") - sizeof(WCHAR
)) / sizeof(WCHAR
)))
278 return STATUS_UNSUCCESSFUL
;
280 LinkName
.Buffer
+= (sizeof(L
"\\Device\\Harddisk") - sizeof(WCHAR
)) / sizeof(WCHAR
);
282 if (!iswdigit(*LinkName
.Buffer
))
284 return STATUS_UNSUCCESSFUL
;
287 while (iswdigit(*LinkName
.Buffer
))
289 *DiskNumber
= *DiskNumber
* 10 + *LinkName
.Buffer
- L
'0';
292 if (_wcsicmp(LinkName
.Buffer
, L
"\\Partition0"))
294 return STATUS_UNSUCCESSFUL
;
296 return STATUS_SUCCESS
;
301 xHalQueryDriveLayout(IN PUNICODE_STRING DeviceName
,
302 OUT PDRIVE_LAYOUT_INFORMATION
*LayoutInfo
)
304 IO_STATUS_BLOCK StatusBlock
;
305 DISK_GEOMETRY DiskGeometry
;
306 PDEVICE_OBJECT DeviceObject
= NULL
;
307 PFILE_OBJECT FileObject
;
312 DPRINT("xHalpQueryDriveLayout %wZ %p\n",
316 /* Get the drives sector size */
317 Status
= IoGetDeviceObjectPointer(DeviceName
,
318 FILE_READ_ATTRIBUTES
,
321 if (!NT_SUCCESS(Status
))
323 DPRINT("Status %x\n", Status
);
327 KeInitializeEvent(&Event
,
331 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
336 sizeof(DISK_GEOMETRY
),
342 ObDereferenceObject(FileObject
);
343 return(STATUS_INSUFFICIENT_RESOURCES
);
346 Status
= IoCallDriver(DeviceObject
,
348 if (Status
== STATUS_PENDING
)
350 KeWaitForSingleObject(&Event
,
355 Status
= StatusBlock
.Status
;
357 if (!NT_SUCCESS(Status
))
359 if (DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
361 DiskGeometry
.BytesPerSector
= 512;
365 ObDereferenceObject(FileObject
);
370 DPRINT("DiskGeometry.BytesPerSector: %d\n",
371 DiskGeometry
.BytesPerSector
);
373 if (DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
375 PDRIVE_LAYOUT_INFORMATION Buffer
;
377 /* Allocate a partition list for a single entry. */
378 Buffer
= ExAllocatePool(NonPagedPool
,
379 sizeof(DRIVE_LAYOUT_INFORMATION
));
382 RtlZeroMemory(Buffer
,
383 sizeof(DRIVE_LAYOUT_INFORMATION
));
384 Buffer
->PartitionCount
= 1;
385 *LayoutInfo
= Buffer
;
387 Status
= STATUS_SUCCESS
;
391 Status
= STATUS_UNSUCCESSFUL
;
396 /* Read the partition table */
397 Status
= IoReadPartitionTable(DeviceObject
,
398 DiskGeometry
.BytesPerSector
,
403 ObDereferenceObject(FileObject
);
410 xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
411 IN PSTRING NtDeviceName
,
412 OUT PUCHAR NtSystemPath
,
413 OUT PSTRING NtSystemPathString
)
415 PDRIVE_LAYOUT_INFORMATION
*LayoutArray
;
416 PCONFIGURATION_INFORMATION ConfigInfo
;
417 OBJECT_ATTRIBUTES ObjectAttributes
;
418 IO_STATUS_BLOCK StatusBlock
;
419 UNICODE_STRING UnicodeString1
;
420 UNICODE_STRING UnicodeString2
;
430 PKEY_VALUE_PARTIAL_INFORMATION PartialInformation
;
431 PREG_DISK_MOUNT_INFO DiskMountInfo
;
433 UNICODE_STRING BootDevice
;
435 Status
= RtlAnsiStringToUnicodeString(&BootDevice
,
439 DPRINT("xHalIoAssignDriveLetters()\n");
441 ConfigInfo
= IoGetConfigurationInformation();
443 RDiskCount
= xHalpGetRDiskCount();
445 DPRINT("RDiskCount %d\n", RDiskCount
);
447 Buffer1
= (PWSTR
)ExAllocatePool(PagedPool
,
449 Buffer2
= (PWSTR
)ExAllocatePool(PagedPool
,
452 PartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)ExAllocatePool(PagedPool
,
453 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(REG_DISK_MOUNT_INFO
));
455 if (!Buffer1
|| !Buffer2
|| !PartialInformation
) return;
457 DiskMountInfo
= (PREG_DISK_MOUNT_INFO
) PartialInformation
->Data
;
459 /* Open or Create the 'MountedDevices' key */
460 RtlInitUnicodeString(&UnicodeString1
, L
"\\Registry\\Machine\\SYSTEM\\MountedDevices");
461 InitializeObjectAttributes(&ObjectAttributes
,
463 OBJ_CASE_INSENSITIVE
,
466 Status
= ZwOpenKey(&hKey
,
469 if (!NT_SUCCESS(Status
))
471 Status
= ZwCreateKey(&hKey
,
476 REG_OPTION_NON_VOLATILE
,
479 if (!NT_SUCCESS(Status
))
482 DPRINT("ZwCreateKey failed for %wZ, status=%x\n", &UnicodeString1
, Status
);
485 /* Create PhysicalDrive links */
486 DPRINT("Physical disk drives: %d\n", ConfigInfo
->DiskCount
);
487 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
490 L
"\\Device\\Harddisk%d\\Partition0",
492 RtlInitUnicodeString(&UnicodeString1
,
495 InitializeObjectAttributes(&ObjectAttributes
,
501 Status
= ZwOpenFile(&FileHandle
,
502 FILE_READ_DATA
| SYNCHRONIZE
,
506 FILE_SYNCHRONOUS_IO_NONALERT
);
507 if (NT_SUCCESS(Status
))
512 L
"\\??\\PhysicalDrive%d",
514 RtlInitUnicodeString(&UnicodeString2
,
517 DPRINT("Creating link: %S ==> %S\n",
521 IoCreateSymbolicLink(&UnicodeString2
,
526 /* Initialize layout array */
527 if (ConfigInfo
->DiskCount
== 0)
528 goto end_assign_disks
;
529 LayoutArray
= ExAllocatePool(NonPagedPool
,
530 ConfigInfo
->DiskCount
* sizeof(PDRIVE_LAYOUT_INFORMATION
));
533 ExFreePool(PartialInformation
);
536 if (hKey
) ZwClose(hKey
);
539 RtlZeroMemory(LayoutArray
,
540 ConfigInfo
->DiskCount
* sizeof(PDRIVE_LAYOUT_INFORMATION
));
541 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
544 L
"\\Device\\Harddisk%d\\Partition0",
546 RtlInitUnicodeString(&UnicodeString1
,
549 Status
= xHalQueryDriveLayout(&UnicodeString1
,
551 if (!NT_SUCCESS(Status
))
553 DbgPrint("xHalQueryDriveLayout() failed (Status = 0x%lx)\n",
555 LayoutArray
[i
] = NULL
;
558 /* We don't use the RewritePartition value while mounting the disks.
559 * We use this value for marking pre-assigned (registry) partitions.
561 for (j
= 0; j
< LayoutArray
[i
]->PartitionCount
; j
++)
563 LayoutArray
[i
]->PartitionEntry
[j
].RewritePartition
= FALSE
;
568 /* Dump layout array */
569 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
571 DPRINT("Harddisk %d:\n",
574 if (LayoutArray
[i
] == NULL
)
577 DPRINT("Logical partitions: %d\n",
578 LayoutArray
[i
]->PartitionCount
);
580 for (j
= 0; j
< LayoutArray
[i
]->PartitionCount
; j
++)
582 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%I64u count:%I64u\n",
584 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
,
585 LayoutArray
[i
]->PartitionEntry
[j
].BootIndicator
,
586 LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
,
587 LayoutArray
[i
]->PartitionEntry
[j
].StartingOffset
.QuadPart
,
588 LayoutArray
[i
]->PartitionEntry
[j
].PartitionLength
.QuadPart
);
593 /* Assign pre-assigned (registry) partitions */
596 for (k
= 2; k
< 26; k
++)
598 swprintf(Buffer1
, DiskMountString
, L
'A' + k
);
599 RtlInitUnicodeString(&UnicodeString1
, Buffer1
);
600 Status
= ZwQueryValueKey(hKey
,
602 KeyValuePartialInformation
,
604 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(REG_DISK_MOUNT_INFO
),
606 if (NT_SUCCESS(Status
) &&
607 PartialInformation
->Type
== REG_BINARY
&&
608 PartialInformation
->DataLength
== sizeof(REG_DISK_MOUNT_INFO
))
610 DPRINT("%wZ => %08x:%08x%08x\n", &UnicodeString1
, DiskMountInfo
->Signature
,
611 DiskMountInfo
->StartingOffset
.u
.HighPart
, DiskMountInfo
->StartingOffset
.u
.LowPart
);
613 BOOLEAN Found
= FALSE
;
614 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
616 DPRINT("%x\n", LayoutArray
[i
]->Signature
);
617 if (LayoutArray
[i
] &&
618 LayoutArray
[i
]->Signature
&&
619 LayoutArray
[i
]->Signature
== DiskMountInfo
->Signature
)
621 for (j
= 0; j
< LayoutArray
[i
]->PartitionCount
; j
++)
623 if (LayoutArray
[i
]->PartitionEntry
[j
].StartingOffset
.QuadPart
== DiskMountInfo
->StartingOffset
.QuadPart
)
625 if (IsRecognizedPartition(LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
) &&
626 LayoutArray
[i
]->PartitionEntry
[j
].RewritePartition
== FALSE
)
629 L
"\\Device\\Harddisk%d\\Partition%d",
631 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
);
632 RtlInitUnicodeString(&UnicodeString2
,
636 DPRINT(" %wZ\n", &UnicodeString2
);
637 Found
= HalpAssignDrive(&UnicodeString2
,
639 DOSDEVICE_DRIVE_FIXED
,
640 DiskMountInfo
->Signature
,
641 DiskMountInfo
->StartingOffset
,
645 /* Mark the partition as assigned */
646 LayoutArray
[i
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
655 /* We didn't find a partition for this entry, remove them. */
656 Status
= ZwDeleteValueKey(hKey
, &UnicodeString1
);
663 /* Assign bootable partition on first harddisk */
664 DPRINT("Assigning bootable primary partition on first harddisk:\n");
667 Status
= xHalpGetDiskNumberFromRDisk(0, &DiskNumber
);
668 if (NT_SUCCESS(Status
) &&
669 DiskNumber
< ConfigInfo
->DiskCount
&&
670 LayoutArray
[DiskNumber
])
672 /* Search for bootable partition */
673 for (j
= 0; j
< NUM_PARTITION_TABLE_ENTRIES
&& j
< LayoutArray
[DiskNumber
]->PartitionCount
; j
++)
675 if ((LayoutArray
[DiskNumber
]->PartitionEntry
[j
].BootIndicator
== TRUE
) &&
676 IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
))
678 if (LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
)
681 L
"\\Device\\Harddisk%lu\\Partition%d",
683 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
684 RtlInitUnicodeString(&UnicodeString2
,
688 DPRINT(" %wZ\n", &UnicodeString2
);
689 HalpAssignDrive(&UnicodeString2
,
691 DOSDEVICE_DRIVE_FIXED
,
692 LayoutArray
[DiskNumber
]->Signature
,
693 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
697 /* Mark the partition as assigned */
698 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
706 /* Assign remaining primary partitions */
707 DPRINT("Assigning remaining primary partitions:\n");
708 for (RDisk
= 0; RDisk
< RDiskCount
; RDisk
++)
710 Status
= xHalpGetDiskNumberFromRDisk(RDisk
, &DiskNumber
);
711 if (NT_SUCCESS(Status
) &&
712 DiskNumber
< ConfigInfo
->DiskCount
&&
713 LayoutArray
[DiskNumber
])
715 /* Search for primary partitions */
716 for (j
= 0; (j
< NUM_PARTITION_TABLE_ENTRIES
) && (j
< LayoutArray
[DiskNumber
]->PartitionCount
); j
++)
718 if (LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
&&
719 IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
))
722 L
"\\Device\\Harddisk%d\\Partition%d",
724 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
725 RtlInitUnicodeString(&UnicodeString2
,
731 HalpAssignDrive(&UnicodeString2
,
733 DOSDEVICE_DRIVE_FIXED
,
734 LayoutArray
[DiskNumber
]->Signature
,
735 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
739 /* Mark the partition as assigned */
740 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
746 /* Assign extended (logical) partitions */
747 DPRINT("Assigning extended (logical) partitions:\n");
748 for (RDisk
= 0; RDisk
< RDiskCount
; RDisk
++)
750 Status
= xHalpGetDiskNumberFromRDisk(RDisk
, &DiskNumber
);
751 if (NT_SUCCESS(Status
) &&
752 DiskNumber
< ConfigInfo
->DiskCount
&&
753 LayoutArray
[DiskNumber
])
755 /* Search for extended partitions */
756 for (j
= NUM_PARTITION_TABLE_ENTRIES
; j
< LayoutArray
[DiskNumber
]->PartitionCount
; j
++)
758 if (IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
) &&
759 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
&&
760 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
!= 0)
763 L
"\\Device\\Harddisk%d\\Partition%d",
765 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
766 RtlInitUnicodeString(&UnicodeString2
,
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%d\\Partition%d",
802 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
803 RtlInitUnicodeString(&UnicodeString2
,
809 HalpAssignDrive(&UnicodeString2
,
811 DOSDEVICE_DRIVE_FIXED
,
812 LayoutArray
[DiskNumber
]->Signature
,
813 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
817 /* Mark the partition as assigned */
818 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
824 /* Assign extended (logical) partitions without an arc-name */
825 DPRINT("Assigning extended (logical) partitions:\n");
826 for (DiskNumber
= 0; DiskNumber
< ConfigInfo
->DiskCount
; DiskNumber
++)
828 if (LayoutArray
[DiskNumber
])
830 /* Search for extended partitions */
831 for (j
= NUM_PARTITION_TABLE_ENTRIES
; j
< LayoutArray
[DiskNumber
]->PartitionCount
; j
++)
833 if (IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
) &&
834 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
&&
835 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
!= 0)
838 L
"\\Device\\Harddisk%d\\Partition%d",
840 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
841 RtlInitUnicodeString(&UnicodeString2
,
847 HalpAssignDrive(&UnicodeString2
,
849 DOSDEVICE_DRIVE_FIXED
,
850 LayoutArray
[DiskNumber
]->Signature
,
851 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
855 /* Mark the partition as assigned */
856 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
862 /* Assign removable disk drives */
863 DPRINT("Assigning removable disk drives:\n");
864 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
868 /* Search for virtual partitions */
869 if (LayoutArray
[i
]->PartitionCount
== 1 &&
870 LayoutArray
[i
]->PartitionEntry
[0].PartitionType
== 0)
873 L
"\\Device\\Harddisk%d\\Partition1",
875 RtlInitUnicodeString(&UnicodeString2
,
881 HalpAssignDrive(&UnicodeString2
,
883 DOSDEVICE_DRIVE_REMOVABLE
,
885 RtlConvertLongToLargeInteger(0),
893 /* Free layout array */
894 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
896 if (LayoutArray
[i
] != NULL
)
897 ExFreePool(LayoutArray
[i
]);
899 ExFreePool(LayoutArray
);
902 /* Assign floppy drives */
903 DPRINT("Floppy drives: %d\n", ConfigInfo
->FloppyCount
);
904 for (i
= 0; i
< ConfigInfo
->FloppyCount
; i
++)
907 L
"\\Device\\Floppy%d",
909 RtlInitUnicodeString(&UnicodeString1
,
912 /* Assign drive letters A: or B: or first free drive letter */
915 HalpAssignDrive(&UnicodeString1
,
916 (i
< 2) ? i
: AUTO_DRIVE
,
917 DOSDEVICE_DRIVE_REMOVABLE
,
919 RtlConvertLongToLargeInteger(0),
925 /* Assign cdrom drives */
926 DPRINT("CD-Rom drives: %d\n", ConfigInfo
->CdRomCount
);
927 for (i
= 0; i
< ConfigInfo
->CdRomCount
; i
++)
930 L
"\\Device\\CdRom%d",
932 RtlInitUnicodeString(&UnicodeString1
,
935 /* Assign first free drive letter */
936 DPRINT(" %wZ\n", &UnicodeString1
);
937 HalpAssignDrive(&UnicodeString1
,
939 DOSDEVICE_DRIVE_CDROM
,
941 RtlConvertLongToLargeInteger(0),
947 /* Anything else to do? */
949 ExFreePool(PartialInformation
);
960 /* PRIVATE FUNCTIONS *********************************************************/
964 HalpGetFullGeometry(IN PDEVICE_OBJECT DeviceObject
,
965 IN PDISK_GEOMETRY Geometry
,
966 OUT PULONGLONG RealSectorCount
)
969 IO_STATUS_BLOCK IoStatusBlock
;
972 PARTITION_INFORMATION PartitionInfo
;
975 /* Allocate a non-paged event */
976 Event
= ExAllocatePoolWithTag(NonPagedPool
,
979 if (!Event
) return STATUS_INSUFFICIENT_RESOURCES
;
982 KeInitializeEvent(Event
, NotificationEvent
, FALSE
);
985 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
990 sizeof(DISK_GEOMETRY
),
996 /* Fail, free the event */
997 ExFreePoolWithTag(Event
, TAG_FILE_SYSTEM
);
998 return STATUS_INSUFFICIENT_RESOURCES
;
1001 /* Call the driver and check if it's pending */
1002 Status
= IoCallDriver(DeviceObject
, Irp
);
1003 if (Status
== STATUS_PENDING
)
1005 /* Wait on the driver */
1006 KeWaitForSingleObject(Event
, Executive
, KernelMode
, FALSE
, NULL
);
1007 Status
= IoStatusBlock
.Status
;
1010 /* Check if the driver returned success */
1011 if(NT_SUCCESS(Status
))
1013 /* Build another IRP */
1014 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO
,
1019 sizeof(PARTITION_INFORMATION
),
1025 /* Fail, free the event */
1026 ExFreePoolWithTag(Event
, TAG_FILE_SYSTEM
);
1027 return STATUS_INSUFFICIENT_RESOURCES
;
1030 /* Call the driver and check if it's pending */
1031 Status
= IoCallDriver(DeviceObject
, Irp
);
1032 if (Status
== STATUS_PENDING
)
1034 /* Wait on the driver */
1035 KeWaitForSingleObject(Event
, Executive
, KernelMode
, FALSE
, NULL
);
1036 Status
= IoStatusBlock
.Status
;
1039 /* Check if the driver returned success */
1040 if(NT_SUCCESS(Status
))
1042 /* Get the number of sectors */
1043 *RealSectorCount
= (PartitionInfo
.PartitionLength
.QuadPart
/
1044 Geometry
->BytesPerSector
);
1048 /* Free the event and return the Status */
1049 ExFreePoolWithTag(Event
, TAG_FILE_SYSTEM
);
1055 HalpIsValidPartitionEntry(IN PPARTITION_DESCRIPTOR Entry
,
1056 IN ULONGLONG MaxOffset
,
1057 IN ULONGLONG MaxSector
)
1059 ULONGLONG EndingSector
;
1062 /* Unused partitions are considered valid */
1063 if (Entry
->PartitionType
== PARTITION_ENTRY_UNUSED
) return TRUE
;
1065 /* Get the last sector of the partition */
1066 EndingSector
= GET_STARTING_SECTOR(Entry
) + GET_PARTITION_LENGTH(Entry
);
1068 /* Check if it's more then the maximum sector */
1069 if (EndingSector
> MaxSector
)
1071 /* Invalid partition */
1072 DPRINT1("FSTUB: entry is invalid\n");
1073 DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry
));
1074 DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry
));
1075 DPRINT1("FSTUB: end %#I64x\n", EndingSector
);
1076 DPRINT1("FSTUB: max %#I64x\n", MaxSector
);
1079 else if(GET_STARTING_SECTOR(Entry
) > MaxOffset
)
1081 /* Invalid partition */
1082 DPRINT1("FSTUB: entry is invalid\n");
1083 DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry
));
1084 DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry
));
1085 DPRINT1("FSTUB: end %#I64x\n", EndingSector
);
1086 DPRINT1("FSTUB: maxOffset %#I64x\n", MaxOffset
);
1090 /* It's fine, return success */
1096 HalpCalculateChsValues(IN PLARGE_INTEGER PartitionOffset
,
1097 IN PLARGE_INTEGER PartitionLength
,
1098 IN CCHAR ShiftCount
,
1099 IN ULONG SectorsPerTrack
,
1100 IN ULONG NumberOfTracks
,
1101 IN ULONG ConventionalCylinders
,
1102 OUT PPARTITION_DESCRIPTOR PartitionDescriptor
)
1104 LARGE_INTEGER FirstSector
, SectorCount
;
1105 ULONG LastSector
, Remainder
, SectorsPerCylinder
;
1106 ULONG StartingCylinder
, EndingCylinder
;
1107 ULONG StartingTrack
, EndingTrack
;
1108 ULONG StartingSector
, EndingSector
;
1111 /* Calculate the number of sectors for each cylinder */
1112 SectorsPerCylinder
= SectorsPerTrack
* NumberOfTracks
;
1114 /* Calculate the first sector, and the sector count */
1115 FirstSector
.QuadPart
= PartitionOffset
->QuadPart
>> ShiftCount
;
1116 SectorCount
.QuadPart
= PartitionLength
->QuadPart
>> ShiftCount
;
1118 /* Now calculate the last sector */
1119 LastSector
= FirstSector
.LowPart
+ SectorCount
.LowPart
- 1;
1121 /* Calculate the first and last cylinders */
1122 StartingCylinder
= FirstSector
.LowPart
/ SectorsPerCylinder
;
1123 EndingCylinder
= LastSector
/ SectorsPerCylinder
;
1125 /* Set the default number of cylinders */
1126 if (!ConventionalCylinders
) ConventionalCylinders
= 1024;
1128 /* Normalize the values */
1129 if (StartingCylinder
>= ConventionalCylinders
)
1131 /* Set the maximum to 1023 */
1132 StartingCylinder
= ConventionalCylinders
- 1;
1134 if (EndingCylinder
>= ConventionalCylinders
)
1136 /* Set the maximum to 1023 */
1137 EndingCylinder
= ConventionalCylinders
- 1;
1140 /* Calculate the starting head and sector that still remain */
1141 Remainder
= FirstSector
.LowPart
% SectorsPerCylinder
;
1142 StartingTrack
= Remainder
/ SectorsPerTrack
;
1143 StartingSector
= Remainder
% SectorsPerTrack
;
1145 /* Calculate the ending head and sector that still remain */
1146 Remainder
= LastSector
% SectorsPerCylinder
;
1147 EndingTrack
= Remainder
/ SectorsPerTrack
;
1148 EndingSector
= Remainder
% SectorsPerTrack
;
1150 /* Set cylinder data for the MSB */
1151 PartitionDescriptor
->StartingCylinderMsb
= (UCHAR
)StartingCylinder
;
1152 PartitionDescriptor
->EndingCylinderMsb
= (UCHAR
)EndingCylinder
;
1154 /* Set the track data */
1155 PartitionDescriptor
->StartingTrack
= (UCHAR
)StartingTrack
;
1156 PartitionDescriptor
->EndingTrack
= (UCHAR
)EndingTrack
;
1158 /* Update cylinder data for the LSB */
1159 StartingCylinder
= ((StartingSector
+ 1) & 0x3F) |
1160 ((StartingCylinder
>> 2) & 0xC0);
1161 EndingCylinder
= ((EndingSector
+ 1) & 0x3F) |
1162 ((EndingCylinder
>> 2) & 0xC0);
1164 /* Set the cylinder data for the LSB */
1165 PartitionDescriptor
->StartingCylinderLsb
= (UCHAR
)StartingCylinder
;
1166 PartitionDescriptor
->EndingCylinderLsb
= (UCHAR
)EndingCylinder
;
1171 xHalGetPartialGeometry(IN PDEVICE_OBJECT DeviceObject
,
1172 IN PULONG ConventionalCylinders
,
1173 IN PLONGLONG DiskSize
)
1175 PDISK_GEOMETRY DiskGeometry
= NULL
;
1176 PIO_STATUS_BLOCK IoStatusBlock
= NULL
;
1177 PKEVENT Event
= NULL
;
1182 *ConventionalCylinders
= 0;
1185 /* Allocate the structure in nonpaged pool */
1186 DiskGeometry
= ExAllocatePoolWithTag(NonPagedPool
,
1187 sizeof(DISK_GEOMETRY
),
1189 if (!DiskGeometry
) goto Cleanup
;
1191 /* Allocate the status block in nonpaged pool */
1192 IoStatusBlock
= ExAllocatePoolWithTag(NonPagedPool
,
1193 sizeof(IO_STATUS_BLOCK
),
1195 if (!IoStatusBlock
) goto Cleanup
;
1197 /* Allocate the event in nonpaged pool too */
1198 Event
= ExAllocatePoolWithTag(NonPagedPool
,
1201 if (!Event
) goto Cleanup
;
1203 /* Initialize the event */
1204 KeInitializeEvent(Event
, NotificationEvent
, FALSE
);
1207 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
1212 sizeof(DISK_GEOMETRY
),
1216 if (!Irp
) goto Cleanup
;
1218 /* Now call the driver */
1219 Status
= IoCallDriver(DeviceObject
, Irp
);
1220 if (Status
== STATUS_PENDING
)
1222 /* Wait for it to complete */
1223 KeWaitForSingleObject(Event
, Executive
, KernelMode
, FALSE
, NULL
);
1224 Status
= IoStatusBlock
->Status
;
1227 /* Check driver status */
1228 if (NT_SUCCESS(Status
))
1230 /* Return the cylinder count */
1231 *ConventionalCylinders
= DiskGeometry
->Cylinders
.LowPart
;
1233 /* Make sure it's not larger then 1024 */
1234 if (DiskGeometry
->Cylinders
.LowPart
>= 1024)
1236 /* Otherwise, normalize the value */
1237 *ConventionalCylinders
= 1024;
1240 /* Calculate the disk size */
1241 *DiskSize
= DiskGeometry
->Cylinders
.QuadPart
*
1242 DiskGeometry
->TracksPerCylinder
*
1243 DiskGeometry
->SectorsPerTrack
*
1244 DiskGeometry
->BytesPerSector
;
1248 /* Free all the pointers */
1249 if (Event
) ExFreePoolWithTag(Event
, TAG_FILE_SYSTEM
);
1250 if (IoStatusBlock
) ExFreePool(IoStatusBlock
);
1251 if (DiskGeometry
) ExFreePool(DiskGeometry
);
1257 xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject
,
1258 IN ULONG SectorSize
,
1259 IN ULONG MbrTypeIdentifier
,
1260 OUT PVOID
*MbrBuffer
)
1262 LARGE_INTEGER Offset
;
1266 IO_STATUS_BLOCK IoStatusBlock
;
1268 PPARTITION_DESCRIPTOR PartitionDescriptor
;
1270 PIO_STACK_LOCATION IoStackLocation
;
1271 Offset
.QuadPart
= 0;
1273 /* Assume failure */
1276 /* Normalize the buffer size */
1277 BufferSize
= max(SectorSize
, 512);
1279 /* Allocate the buffer */
1280 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
1281 PAGE_SIZE
> BufferSize
?
1282 PAGE_SIZE
: BufferSize
,
1284 if (!Buffer
) return;
1286 /* Initialize the Event */
1287 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1290 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
1300 ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
1304 /* Make sure to override volume verification */
1305 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
1306 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
1308 /* Call the driver */
1309 Status
= IoCallDriver(DeviceObject
, Irp
);
1310 if (Status
== STATUS_PENDING
)
1312 /* Wait for completion */
1313 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1314 Status
= IoStatusBlock
.Status
;
1317 /* Check driver Status */
1318 if (NT_SUCCESS(Status
))
1320 /* Validate the MBR Signature */
1321 if (((PUSHORT
)Buffer
)[BOOT_SIGNATURE_OFFSET
] != BOOT_RECORD_SIGNATURE
)
1324 ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
1328 /* Get the partition entry */
1329 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1330 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1332 /* Make sure it's what the caller wanted */
1333 if (PartitionDescriptor
->PartitionType
!= MbrTypeIdentifier
)
1335 /* It's not, free our buffer */
1336 ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
1340 /* Check if this is a secondary entry */
1341 if (PartitionDescriptor
->PartitionType
== 0x54)
1343 /* Return our buffer, but at sector 63 */
1344 *(PULONG
)Buffer
= 63;
1345 *MbrBuffer
= Buffer
;
1347 else if (PartitionDescriptor
->PartitionType
== 0x55)
1349 /* EZ Drive, return the buffer directly */
1350 *MbrBuffer
= Buffer
;
1354 /* Otherwise crash on debug builds */
1355 ASSERT(PartitionDescriptor
->PartitionType
== 0x55);
1363 xHalIoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject
,
1364 IN ULONG SectorSize
,
1365 IN BOOLEAN ReturnRecognizedPartitions
,
1366 IN OUT PDRIVE_LAYOUT_INFORMATION
*PartitionBuffer
)
1369 IO_STATUS_BLOCK IoStatusBlock
;
1371 PPARTITION_DESCRIPTOR PartitionDescriptor
;
1374 PPARTITION_INFORMATION PartitionInfo
;
1375 PUCHAR Buffer
= NULL
;
1376 ULONG BufferSize
= 2048, InputSize
;
1377 PDRIVE_LAYOUT_INFORMATION DriveLayoutInfo
= NULL
;
1378 LONG j
= -1, i
= -1, k
;
1379 DISK_GEOMETRY DiskGeometry
;
1380 LONGLONG EndSector
, MaxSector
, StartOffset
;
1381 ULONGLONG MaxOffset
;
1382 LARGE_INTEGER Offset
, VolumeOffset
;
1383 BOOLEAN IsPrimary
= TRUE
, IsEzDrive
= FALSE
, MbrFound
= FALSE
;
1384 BOOLEAN IsValid
, IsEmpty
= TRUE
;
1386 PIO_STACK_LOCATION IoStackLocation
;
1387 PBOOT_SECTOR_INFO BootSectorInfo
= (PBOOT_SECTOR_INFO
)Buffer
;
1388 UCHAR PartitionType
;
1389 LARGE_INTEGER HiddenSectors64
;
1390 VolumeOffset
.QuadPart
= Offset
.QuadPart
= 0;
1393 /* Allocate the buffer */
1394 *PartitionBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1397 if (!(*PartitionBuffer
)) return STATUS_INSUFFICIENT_RESOURCES
;
1399 /* Normalize the buffer size */
1400 InputSize
= max(512, SectorSize
);
1402 /* Check for EZ Drive */
1403 HalExamineMBR(DeviceObject
, InputSize
, 0x55, &MbrBuffer
);
1406 /* EZ Drive found, bias the offset */
1408 ExFreePool(MbrBuffer
);
1409 Offset
.QuadPart
= 512;
1412 /* Get drive geometry */
1413 Status
= HalpGetFullGeometry(DeviceObject
, &DiskGeometry
, &MaxOffset
);
1414 if (!NT_SUCCESS(Status
))
1416 ExFreePoolWithTag(*PartitionBuffer
, TAG_FILE_SYSTEM
);
1417 *PartitionBuffer
= NULL
;
1421 /* Get the end and maximum sector */
1422 EndSector
= MaxOffset
;
1423 MaxSector
= MaxOffset
<< 1;
1424 DPRINT("FSTUB: MaxOffset = %#I64x, MaxSector = %#I64x\n",
1425 MaxOffset
, MaxSector
);
1427 /* Allocate our buffer */
1428 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, PAGE_SIZE
, TAG_FILE_SYSTEM
);
1431 /* Fail, free the input buffer */
1432 ExFreePoolWithTag(*PartitionBuffer
, TAG_FILE_SYSTEM
);
1433 *PartitionBuffer
= NULL
;
1434 return STATUS_INSUFFICIENT_RESOURCES
;
1437 /* Start partition loop */
1440 /* Assume the partition is valid */
1443 /* Initialize the event */
1444 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1446 /* Clear the buffer and build the IRP */
1447 RtlZeroMemory(Buffer
, InputSize
);
1448 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
1458 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1462 /* Make sure to disable volume verification */
1463 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
1464 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
1466 /* Call the driver */
1467 Status
= IoCallDriver(DeviceObject
, Irp
);
1468 if (Status
== STATUS_PENDING
)
1470 /* Wait for completion */
1471 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1472 Status
= IoStatusBlock
.Status
;
1475 /* Normalize status code and check for failure */
1476 if (Status
== STATUS_NO_DATA_DETECTED
) Status
= STATUS_SUCCESS
;
1477 if (!NT_SUCCESS(Status
)) break;
1479 /* If we biased for EZ-Drive, unbias now */
1480 if (IsEzDrive
&& (Offset
.QuadPart
== 512)) Offset
.QuadPart
= 0;
1482 /* Make sure this is a valid MBR */
1483 if (((PUSHORT
)Buffer
)[BOOT_SIGNATURE_OFFSET
] != BOOT_RECORD_SIGNATURE
)
1485 /* It's not, fail */
1486 DPRINT1("FSTUB: (IoReadPartitionTable) No 0xaa55 found in "
1487 "partition table %d\n", j
+ 1);
1491 /* At this point we have a valid MBR */
1494 /* Check if we weren't given an offset */
1495 if (!Offset
.QuadPart
)
1497 /* Then read the signature off the disk */
1498 (*PartitionBuffer
)->Signature
= ((PULONG
)Buffer
)
1499 [PARTITION_TABLE_OFFSET
/ 2 - 1];
1502 /* Get the partition descriptor array */
1503 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1504 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1506 /* Get the partition type */
1507 PartitionType
= PartitionDescriptor
->PartitionType
;
1509 /* Start looping partitions */
1511 DPRINT("FSTUB: Partition Table %d:\n", j
);
1512 for (Entry
= 1, k
= 0; Entry
<= 4; Entry
++, PartitionDescriptor
++)
1514 /* Get the partition type */
1515 PartitionType
= PartitionDescriptor
->PartitionType
;
1517 /* Print debug messages */
1518 DPRINT("Partition Entry %d,%d: type %#x %s\n",
1522 (PartitionDescriptor
->ActiveFlag
) ? "Active" : "");
1523 DPRINT("\tOffset %#08lx for %#08lx Sectors\n",
1524 GET_STARTING_SECTOR(PartitionDescriptor
),
1525 GET_PARTITION_LENGTH(PartitionDescriptor
));
1527 /* Make sure that the partition is valid, unless it's the first */
1528 if (!(HalpIsValidPartitionEntry(PartitionDescriptor
,
1530 MaxSector
)) && !(j
))
1532 /* It's invalid, so fail */
1537 /* Check if it's a container */
1538 if (IsContainerPartition(PartitionType
))
1540 /* Increase the count of containers */
1543 /* More then one table is invalid */
1544 DPRINT1("FSTUB: Multiple container partitions found in "
1545 "partition table %d\n - table is invalid\n",
1552 /* Check if the partition is supposedly empty */
1555 /* But check if it actually has a start and/or length */
1556 if ((GET_STARTING_SECTOR(PartitionDescriptor
)) ||
1557 (GET_PARTITION_LENGTH(PartitionDescriptor
)))
1559 /* So then it's not really empty */
1564 /* Check if the caller wanted only recognized partitions */
1565 if (ReturnRecognizedPartitions
)
1567 /* Then check if this one is unused, or a container */
1568 if ((PartitionType
== PARTITION_ENTRY_UNUSED
) ||
1569 IsContainerPartition(PartitionType
))
1571 /* Skip it, since the caller doesn't want it */
1576 /* Increase the structure count and check if they can fit */
1577 if ((sizeof(DRIVE_LAYOUT_INFORMATION
) +
1578 (++i
* sizeof(PARTITION_INFORMATION
))) >
1581 /* Allocate a new buffer that's twice as big */
1582 DriveLayoutInfo
= ExAllocatePoolWithTag(NonPagedPool
,
1585 if (!DriveLayoutInfo
)
1587 /* Out of memory, unto this extra structure */
1589 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1593 /* Copy the contents of the old buffer */
1594 RtlMoveMemory(DriveLayoutInfo
,
1598 /* Free the old buffer and set this one as the new one */
1599 ExFreePoolWithTag(*PartitionBuffer
, TAG_FILE_SYSTEM
);
1600 *PartitionBuffer
= DriveLayoutInfo
;
1602 /* Double the size */
1606 /* Now get the current structure being filled and initialize it */
1607 PartitionInfo
= &(*PartitionBuffer
)->PartitionEntry
[i
];
1608 PartitionInfo
->PartitionType
= PartitionType
;
1609 PartitionInfo
->RewritePartition
= FALSE
;
1611 /* Check if we're dealing with a partition that's in use */
1612 if (PartitionType
!= PARTITION_ENTRY_UNUSED
)
1614 /* Check if it's bootable */
1615 PartitionInfo
->BootIndicator
= PartitionDescriptor
->
1619 /* Check if its' a container */
1620 if (IsContainerPartition(PartitionType
))
1622 /* Then don't recognize it and use the volume offset */
1623 PartitionInfo
->RecognizedPartition
= FALSE
;
1624 StartOffset
= VolumeOffset
.QuadPart
;
1628 /* Then recognize it and use the partition offset */
1629 PartitionInfo
->RecognizedPartition
= TRUE
;
1630 StartOffset
= Offset
.QuadPart
;
1633 /* Get the starting offset */
1634 PartitionInfo
->StartingOffset
.QuadPart
=
1636 UInt32x32To64(GET_STARTING_SECTOR(PartitionDescriptor
),
1639 /* Calculate the number of hidden sectors */
1640 HiddenSectors64
.QuadPart
= (PartitionInfo
->
1641 StartingOffset
.QuadPart
-
1644 PartitionInfo
->HiddenSectors
= HiddenSectors64
.LowPart
;
1646 /* Get the partition length */
1647 PartitionInfo
->PartitionLength
.QuadPart
=
1648 UInt32x32To64(GET_PARTITION_LENGTH(PartitionDescriptor
),
1651 /* FIXME: REACTOS HACK */
1652 PartitionInfo
->PartitionNumber
= i
+ 1;
1656 /* Otherwise, clear all the relevant fields */
1657 PartitionInfo
->BootIndicator
= FALSE
;
1658 PartitionInfo
->RecognizedPartition
= FALSE
;
1659 PartitionInfo
->StartingOffset
.QuadPart
= 0;
1660 PartitionInfo
->PartitionLength
.QuadPart
= 0;
1661 PartitionInfo
->HiddenSectors
= 0;
1663 /* FIXME: REACTOS HACK */
1664 PartitionInfo
->PartitionNumber
= 0;
1668 /* Finish debug log, and check for failure */
1670 if (!NT_SUCCESS(Status
)) break;
1672 /* Also check if we hit an invalid entry here */
1675 /* We did, so break out of the loop minus one entry */
1680 /* Reset the offset */
1681 Offset
.QuadPart
= 0;
1683 /* Go back to the descriptor array and loop it */
1684 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1685 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1686 for (Entry
= 1; Entry
<= 4; Entry
++, PartitionDescriptor
++)
1688 /* Check if this is a container partition, since we skipped them */
1689 if (IsContainerPartition(PartitionDescriptor
->PartitionType
))
1691 /* Get its offset */
1692 Offset
.QuadPart
= VolumeOffset
.QuadPart
+
1694 GET_STARTING_SECTOR(PartitionDescriptor
),
1697 /* If this is a primary partition, this is the volume offset */
1698 if (IsPrimary
) VolumeOffset
= Offset
;
1700 /* Also update the maximum sector */
1701 MaxSector
= GET_PARTITION_LENGTH(PartitionDescriptor
);
1702 DPRINT1("FSTUB: MaxSector now = %#08lx\n", MaxSector
);
1707 /* Loop the next partitions, which are not primary anymore */
1709 } while (Offset
.HighPart
| Offset
.LowPart
);
1711 /* Check if this is a removable device that's probably a super-floppy */
1712 if ((DiskGeometry
.MediaType
== RemovableMedia
) &&
1717 /* Read the jump bytes to detect super-floppy */
1718 if ((BootSectorInfo
->JumpByte
[0] == 0xeb) ||
1719 (BootSectorInfo
->JumpByte
[0] == 0xe9))
1721 /* Super floppes don't have typical MBRs, so skip them */
1722 DPRINT1("FSTUB: Jump byte %#x found along with empty partition "
1723 "table - disk is a super floppy and has no valid MBR\n",
1724 BootSectorInfo
->JumpByte
);
1729 /* Check if we're still at partition -1 */
1732 /* The likely cause is the super floppy detection above */
1733 if ((MbrFound
) || (DiskGeometry
.MediaType
== RemovableMedia
))
1735 /* Print out debugging information */
1736 DPRINT1("FSTUB: Drive %#p has no valid MBR. Make it into a "
1739 DPRINT1("FSTUB: Drive has %#08lx sectors and is %#016I64x "
1741 EndSector
, EndSector
* DiskGeometry
.BytesPerSector
);
1743 /* We should at least have some sectors */
1746 /* Get the entry we'll use */
1747 PartitionInfo
= &(*PartitionBuffer
)->PartitionEntry
[0];
1749 /* Fill it out with data for a super-floppy */
1750 PartitionInfo
->RewritePartition
= FALSE
;
1751 PartitionInfo
->RecognizedPartition
= TRUE
;
1752 PartitionInfo
->PartitionType
= PARTITION_FAT_16
;
1753 PartitionInfo
->BootIndicator
= FALSE
;
1754 PartitionInfo
->HiddenSectors
= 0;
1755 PartitionInfo
->StartingOffset
.QuadPart
= 0;
1756 PartitionInfo
->PartitionLength
.QuadPart
= (EndSector
*
1760 /* FIXME: REACTOS HACK */
1761 PartitionInfo
->PartitionNumber
= 0;
1763 /* Set the signature and set the count back to 0 */
1764 (*PartitionBuffer
)->Signature
= 1;
1770 /* Otherwise, this isn't a super floppy, so set an invalid count */
1775 /* Set the partition count */
1776 (*PartitionBuffer
)->PartitionCount
= ++i
;
1778 /* If we have no count, delete the signature */
1779 if (!i
) (*PartitionBuffer
)->Signature
= 0;
1781 /* Free the buffer and check for success */
1782 if (Buffer
) ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
1783 if (!NT_SUCCESS(Status
)) ExFreePoolWithTag(*PartitionBuffer
, TAG_FILE_SYSTEM
);
1791 xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject
,
1792 IN ULONG SectorSize
,
1793 IN ULONG PartitionNumber
,
1794 IN ULONG PartitionType
)
1798 IO_STATUS_BLOCK IoStatusBlock
;
1800 LARGE_INTEGER Offset
, VolumeOffset
;
1801 PUCHAR Buffer
= NULL
;
1805 PPARTITION_DESCRIPTOR PartitionDescriptor
;
1806 BOOLEAN IsPrimary
= TRUE
, IsEzDrive
= FALSE
;
1808 PIO_STACK_LOCATION IoStackLocation
;
1809 VolumeOffset
.QuadPart
= Offset
.QuadPart
= 0;
1812 /* Normalize the buffer size */
1813 BufferSize
= max(512, SectorSize
);
1815 /* Check for EZ Drive */
1816 HalExamineMBR(DeviceObject
, BufferSize
, 0x55, &MbrBuffer
);
1819 /* EZ Drive found, bias the offset */
1821 ExFreePool(MbrBuffer
);
1822 Offset
.QuadPart
= 512;
1825 /* Allocate our partition buffer */
1826 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, PAGE_SIZE
, TAG_FILE_SYSTEM
);
1827 if (!Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
1829 /* Initialize the event we'll use and loop partitions */
1830 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1833 /* Reset the event since we reuse it */
1834 KeResetEvent(&Event
);
1836 /* Build the read IRP */
1837 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
1847 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1851 /* Make sure to disable volume verification */
1852 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
1853 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
1855 /* Call the driver */
1856 Status
= IoCallDriver(DeviceObject
, Irp
);
1857 if (Status
== STATUS_PENDING
)
1859 /* Wait for completion */
1860 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1861 Status
= IoStatusBlock
.Status
;
1864 /* Check for failure */
1865 if (!NT_SUCCESS(Status
)) break;
1867 /* If we biased for EZ-Drive, unbias now */
1868 if (IsEzDrive
&& (Offset
.QuadPart
== 512)) Offset
.QuadPart
= 0;
1870 /* Make sure this is a valid MBR */
1871 if (((PUSHORT
)Buffer
)[BOOT_SIGNATURE_OFFSET
] != BOOT_RECORD_SIGNATURE
)
1873 /* It's not, fail */
1874 Status
= STATUS_BAD_MASTER_BOOT_RECORD
;
1878 /* Get the partition descriptors and loop them */
1879 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1880 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1881 for (Entry
= 1; Entry
<= 4; Entry
++, PartitionDescriptor
++)
1883 /* Check if it's unused or a container partition */
1884 if ((PartitionDescriptor
->PartitionType
==
1885 PARTITION_ENTRY_UNUSED
) ||
1886 (IsContainerPartition(PartitionDescriptor
->PartitionType
)))
1888 /* Go to the next one */
1892 /* It's a valid partition, so increase the partition count */
1893 if (++i
== PartitionNumber
)
1895 /* We found a match, set the type */
1896 PartitionDescriptor
->PartitionType
= (UCHAR
)PartitionType
;
1898 /* Reset the reusable event */
1899 KeResetEvent(&Event
);
1901 /* Build the write IRP */
1902 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
1912 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1916 /* Disable volume verification */
1917 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
1918 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
1920 /* Call the driver */
1921 Status
= IoCallDriver(DeviceObject
, Irp
);
1922 if (Status
== STATUS_PENDING
)
1924 /* Wait for completion */
1925 KeWaitForSingleObject(&Event
,
1930 Status
= IoStatusBlock
.Status
;
1933 /* We're done, break out of the loop */
1938 /* If we looped all the partitions, break out */
1939 if (Entry
<= NUM_PARTITION_TABLE_ENTRIES
) break;
1941 /* Nothing found yet, get the partition array again */
1942 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1943 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1944 for (Entry
= 1; Entry
<= 4; Entry
++, PartitionDescriptor
++)
1946 /* Check if this was a container partition (we skipped these) */
1947 if (IsContainerPartition(PartitionDescriptor
->PartitionType
))
1949 /* Update the partition offset */
1950 Offset
.QuadPart
= VolumeOffset
.QuadPart
+
1951 GET_STARTING_SECTOR(PartitionDescriptor
) *
1954 /* If this was the primary partition, update the volume too */
1955 if (IsPrimary
) VolumeOffset
= Offset
;
1960 /* Check if we already searched all the partitions */
1961 if (Entry
> NUM_PARTITION_TABLE_ENTRIES
)
1963 /* Then we failed to find a good MBR */
1964 Status
= STATUS_BAD_MASTER_BOOT_RECORD
;
1968 /* Loop the next partitions, which are not primary anymore */
1970 } while (i
< PartitionNumber
);
1972 /* Everything done, cleanup */
1973 if (Buffer
) ExFreePool(Buffer
);
1979 xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject
,
1980 IN ULONG SectorSize
,
1981 IN ULONG SectorsPerTrack
,
1982 IN ULONG NumberOfHeads
,
1983 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer
)
1986 IO_STATUS_BLOCK IoStatusBlock
;
1988 NTSTATUS Status
= STATUS_SUCCESS
;
1992 PPARTITION_TABLE PartitionTable
;
1993 LARGE_INTEGER Offset
, NextOffset
, ExtendedOffset
, SectorOffset
;
1994 LARGE_INTEGER StartOffset
, PartitionLength
;
1997 BOOLEAN IsEzDrive
= FALSE
, IsSuperFloppy
= FALSE
, DoRewrite
= FALSE
, IsMbr
;
1998 ULONG ConventionalCylinders
;
2000 PDISK_LAYOUT DiskLayout
= (PDISK_LAYOUT
)PartitionBuffer
;
2002 UCHAR PartitionType
;
2003 PIO_STACK_LOCATION IoStackLocation
;
2004 PPARTITION_INFORMATION PartitionInfo
= PartitionBuffer
->PartitionEntry
;
2005 PPARTITION_INFORMATION TableEntry
;
2006 ExtendedOffset
.QuadPart
= NextOffset
.QuadPart
= Offset
.QuadPart
= 0;
2009 /* Normalize the buffer size */
2010 BufferSize
= max(512, SectorSize
);
2012 /* Get the partial drive geometry */
2013 xHalGetPartialGeometry(DeviceObject
, &ConventionalCylinders
, &DiskSize
);
2015 /* Check for EZ Drive */
2016 HalExamineMBR(DeviceObject
, BufferSize
, 0x55, &MbrBuffer
);
2019 /* EZ Drive found, bias the offset */
2021 ExFreePool(MbrBuffer
);
2022 Offset
.QuadPart
= 512;
2025 /* Get the number of bits to shift to multiply by the sector size */
2026 for (k
= 0; k
< 32; k
++) if ((SectorSize
>> k
) == 1) break;
2028 /* Check if there's only one partition */
2029 if (PartitionBuffer
->PartitionCount
== 1)
2031 /* Check if it has no starting offset or hidden sectors */
2032 if (!(PartitionInfo
->StartingOffset
.QuadPart
) &&
2033 !(PartitionInfo
->HiddenSectors
))
2035 /* Then it's a super floppy */
2036 IsSuperFloppy
= TRUE
;
2038 /* Which also means it must be non-bootable FAT-16 */
2039 if ((PartitionInfo
->PartitionNumber
) ||
2040 (PartitionInfo
->PartitionType
!= PARTITION_FAT_16
) ||
2041 (PartitionInfo
->BootIndicator
))
2043 /* It's not, so we fail */
2044 return STATUS_INVALID_PARAMETER
;
2047 /* Check if it needs a rewrite, and disable EZ drive for sure */
2048 if (PartitionInfo
->RewritePartition
) DoRewrite
= TRUE
;
2053 /* Count the number of partition tables */
2054 DiskLayout
->TableCount
= (PartitionBuffer
->PartitionCount
+ 4 - 1) / 4;
2056 /* Allocate our partition buffer */
2057 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, PAGE_SIZE
, TAG_FILE_SYSTEM
);
2058 if (!Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
2060 /* Loop the entries */
2061 Entry
= (PPTE
)&Buffer
[PARTITION_TABLE_OFFSET
];
2062 for (i
= 0; i
< DiskLayout
->TableCount
; i
++)
2064 /* Set if this is the MBR partition */
2067 /* Initialize th event */
2068 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
2070 /* Build the read IRP */
2071 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
2081 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2085 /* Make sure to disable volume verification */
2086 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
2087 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
2089 /* Call the driver */
2090 Status
= IoCallDriver(DeviceObject
, Irp
);
2091 if (Status
== STATUS_PENDING
)
2093 /* Wait for completion */
2094 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
2095 Status
= IoStatusBlock
.Status
;
2098 /* Check for failure */
2099 if (!NT_SUCCESS(Status
)) break;
2101 /* If we biased for EZ-Drive, unbias now */
2102 if (IsEzDrive
&& (Offset
.QuadPart
== 512)) Offset
.QuadPart
= 0;
2104 /* Check if this is a normal disk */
2107 /* Set the boot record signature */
2108 Buffer
[BOOT_SIGNATURE_OFFSET
] = BOOT_RECORD_SIGNATURE
;
2110 /* By default, don't require a rewrite */
2113 /* Check if we don't have an offset */
2114 if (!Offset
.QuadPart
)
2116 /* Check if the signature doesn't match */
2117 if (((PULONG
)Buffer
)[PARTITION_TABLE_OFFSET
/ 2 - 1] !=
2118 PartitionBuffer
->Signature
)
2120 /* Then write the signature and now w need a rewrite */
2121 ((PULONG
)Buffer
)[PARTITION_TABLE_OFFSET
/ 2 - 1] =
2122 PartitionBuffer
->Signature
;
2127 /* Loop the partition table entries */
2128 PartitionTable
= &DiskLayout
->PartitionTable
[i
];
2129 for (j
= 0; j
< 4; j
++)
2131 /* Get the current entry and type */
2132 TableEntry
= &PartitionTable
->PartitionEntry
[j
];
2133 PartitionType
= TableEntry
->PartitionType
;
2135 /* Check if the entry needs a rewrite */
2136 if (TableEntry
->RewritePartition
)
2138 /* Then we need one too */
2141 /* Save the type and if it's a bootable partition */
2142 Entry
[j
].PartitionType
= TableEntry
->PartitionType
;
2143 Entry
[j
].ActiveFlag
= TableEntry
->BootIndicator
? 0x80 : 0;
2145 /* Make sure it's used */
2146 if (PartitionType
!= PARTITION_ENTRY_UNUSED
)
2148 /* Make sure it's not a container (unless primary) */
2149 if ((IsMbr
) || !(IsContainerPartition(PartitionType
)))
2151 /* Use the partition offset */
2152 StartOffset
.QuadPart
= Offset
.QuadPart
;
2156 /* Use the extended logical partition offset */
2157 StartOffset
.QuadPart
= ExtendedOffset
.QuadPart
;
2160 /* Set the sector offset */
2161 SectorOffset
.QuadPart
= TableEntry
->
2162 StartingOffset
.QuadPart
-
2163 StartOffset
.QuadPart
;
2165 /* Now calculate the starting sector */
2166 StartOffset
.QuadPart
= SectorOffset
.QuadPart
>> k
;
2167 Entry
[j
].StartingSector
= StartOffset
.LowPart
;
2169 /* As well as the length */
2170 PartitionLength
.QuadPart
= TableEntry
->PartitionLength
.
2172 Entry
[j
].PartitionLength
= PartitionLength
.LowPart
;
2174 /* Calculate the CHS values */
2175 HalpCalculateChsValues(&TableEntry
->StartingOffset
,
2176 &TableEntry
->PartitionLength
,
2180 ConventionalCylinders
,
2181 (PPARTITION_DESCRIPTOR
)
2186 /* Otherwise set up an empty entry */
2187 Entry
[j
].StartingSector
= 0;
2188 Entry
[j
].PartitionLength
= 0;
2189 Entry
[j
].StartingTrack
= 0;
2190 Entry
[j
].EndingTrack
= 0;
2191 Entry
[j
].StartingCylinder
= 0;
2192 Entry
[j
].EndingCylinder
= 0;
2196 /* Check if this is a container partition */
2197 if (IsContainerPartition(PartitionType
))
2199 /* Then update the offset to use */
2200 NextOffset
= TableEntry
->StartingOffset
;
2205 /* Check if we need to write back the buffer */
2208 /* We don't need to do this again */
2211 /* Initialize the event */
2212 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
2214 /* If we unbiased for EZ-Drive, rebias now */
2215 if ((IsEzDrive
) && !(Offset
.QuadPart
)) Offset
.QuadPart
= 512;
2217 /* Build the write IRP */
2218 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
2228 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2232 /* Make sure to disable volume verification */
2233 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
2234 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
2236 /* Call the driver */
2237 Status
= IoCallDriver(DeviceObject
, Irp
);
2238 if (Status
== STATUS_PENDING
)
2240 /* Wait for completion */
2241 KeWaitForSingleObject(&Event
,
2246 Status
= IoStatusBlock
.Status
;
2249 /* Check for failure */
2250 if (!NT_SUCCESS(Status
)) break;
2252 /* If we biased for EZ-Drive, unbias now */
2253 if (IsEzDrive
&& (Offset
.QuadPart
== 512)) Offset
.QuadPart
= 0;
2256 /* Update the partition offset and set the extended offset if needed */
2257 Offset
= NextOffset
;
2258 if (IsMbr
) ExtendedOffset
= NextOffset
;
2261 /* If we had a buffer, free it, then return status */
2262 if (Buffer
) ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
2266 /* PUBLIC FUNCTIONS **********************************************************/
2273 HalExamineMBR(IN PDEVICE_OBJECT DeviceObject
,
2274 IN ULONG SectorSize
,
2275 IN ULONG MbrTypeIdentifier
,
2276 OUT PVOID
*MbrBuffer
)
2278 HALDISPATCH
->HalExamineMBR(DeviceObject
,
2289 IoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject
,
2290 IN ULONG SectorSize
,
2291 IN BOOLEAN ReturnRecognizedPartitions
,
2292 IN OUT PDRIVE_LAYOUT_INFORMATION
*PartitionBuffer
)
2294 return HALDISPATCH
->HalIoReadPartitionTable(DeviceObject
,
2296 ReturnRecognizedPartitions
,
2305 IoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject
,
2306 IN ULONG SectorSize
,
2307 IN ULONG PartitionNumber
,
2308 IN ULONG PartitionType
)
2310 return HALDISPATCH
->HalIoSetPartitionInformation(DeviceObject
,
2321 IoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject
,
2322 IN ULONG SectorSize
,
2323 IN ULONG SectorsPerTrack
,
2324 IN ULONG NumberOfHeads
,
2325 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer
)
2327 return HALDISPATCH
->HalIoWritePartitionTable(DeviceObject
,
2339 IoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
2340 IN PSTRING NtDeviceName
,
2341 OUT PUCHAR NtSystemPath
,
2342 OUT PSTRING NtSystemPathString
)
2344 HALDISPATCH
->HalIoAssignDriveLetters(LoaderBlock
,
2347 NtSystemPathString
);