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)
7 * Eric Kohl (ekohl@rz-online.de)
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 ((ULONG)-1)
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
,
52 WCHAR DriveNameBuffer
[16];
53 UNICODE_STRING DriveName
;
56 REG_DISK_MOUNT_INFO DiskMountInfo
;
58 DPRINT("HalpAssignDrive()\n");
60 if ((DriveNumber
!= AUTO_DRIVE
) && (DriveNumber
< 26))
62 /* Force assignment */
63 if ((ObSystemDeviceMap
->DriveMap
& (1 << DriveNumber
)) != 0)
65 DbgPrint("Drive letter already used!\n");
71 /* Automatic assignment */
72 DriveNumber
= AUTO_DRIVE
;
74 for (i
= 2; i
< 26; i
++)
76 if ((ObSystemDeviceMap
->DriveMap
& (1 << i
)) == 0)
83 if (DriveNumber
== AUTO_DRIVE
)
85 DbgPrint("No drive letter available!\n");
90 DPRINT("DriveNumber %d\n", DriveNumber
);
92 /* Update the System Device Map */
93 ObSystemDeviceMap
->DriveMap
|= (1 << DriveNumber
);
94 ObSystemDeviceMap
->DriveType
[DriveNumber
] = DriveType
;
96 /* Build drive name */
97 swprintf(DriveNameBuffer
,
100 RtlInitUnicodeString(&DriveName
,
103 DPRINT(" %wZ ==> %wZ\n",
107 /* Create symbolic link */
108 Status
= IoCreateSymbolicLink(&DriveName
,
112 DriveType
== DOSDEVICE_DRIVE_FIXED
&&
115 DiskMountInfo
.Signature
= Signature
;
116 DiskMountInfo
.StartingOffset
= StartingOffset
;
117 swprintf(DriveNameBuffer
, DiskMountString
, L
'A' + DriveNumber
);
118 RtlInitUnicodeString(&DriveName
, DriveNameBuffer
);
120 Status
= ZwSetValueKey(hKey
,
125 sizeof(DiskMountInfo
));
126 if (!NT_SUCCESS(Status
))
128 DPRINT1("ZwCreateValueKey failed for %wZ, status=%x\n", &DriveName
, Status
);
135 xHalpGetRDiskCount(VOID
)
138 UNICODE_STRING ArcName
;
139 PWCHAR ArcNameBuffer
;
140 OBJECT_ATTRIBUTES ObjectAttributes
;
141 HANDLE DirectoryHandle
;
142 POBJECT_DIRECTORY_INFORMATION DirectoryInfo
;
147 BOOLEAN First
= TRUE
;
150 DirectoryInfo
= ExAllocatePool(PagedPool
, 2 * PAGE_SIZE
);
151 if (DirectoryInfo
== NULL
)
156 RtlInitUnicodeString(&ArcName
, L
"\\ArcName");
157 InitializeObjectAttributes(&ObjectAttributes
,
163 Status
= ZwOpenDirectoryObject (&DirectoryHandle
,
164 SYMBOLIC_LINK_ALL_ACCESS
,
166 if (!NT_SUCCESS(Status
))
168 DPRINT1("ZwOpenDirectoryObject for %wZ failed, status=%lx\n", &ArcName
, Status
);
169 ExFreePool(DirectoryInfo
);
175 while (NT_SUCCESS(Status
))
177 Status
= NtQueryDirectoryObject (DirectoryHandle
,
185 if (NT_SUCCESS(Status
))
188 while (DirectoryInfo
[Count
].Name
.Buffer
)
190 DPRINT("Count %x\n", Count
);
191 DirectoryInfo
[Count
].Name
.Buffer
[DirectoryInfo
[Count
].Name
.Length
/ sizeof(WCHAR
)] = 0;
192 ArcNameBuffer
= DirectoryInfo
[Count
].Name
.Buffer
;
193 if (DirectoryInfo
[Count
].Name
.Length
>= sizeof(L
"multi(0)disk(0)rdisk(0)") - sizeof(WCHAR
) &&
194 !_wcsnicmp(ArcNameBuffer
, L
"multi(0)disk(0)rdisk(", (sizeof(L
"multi(0)disk(0)rdisk(") - sizeof(WCHAR
)) / sizeof(WCHAR
)))
196 DPRINT("%S\n", ArcNameBuffer
);
197 ArcNameBuffer
+= (sizeof(L
"multi(0)disk(0)rdisk(") - sizeof(WCHAR
)) / sizeof(WCHAR
);
199 while (iswdigit(*ArcNameBuffer
))
201 CurrentRDisk
= CurrentRDisk
* 10 + *ArcNameBuffer
- L
'0';
204 if (!_wcsicmp(ArcNameBuffer
, L
")") &&
205 CurrentRDisk
>= RDiskCount
)
207 RDiskCount
= CurrentRDisk
+ 1;
214 ExFreePool(DirectoryInfo
);
219 xHalpGetDiskNumberFromRDisk(ULONG RDisk
, PULONG DiskNumber
)
221 WCHAR NameBuffer
[80];
222 UNICODE_STRING ArcName
;
223 UNICODE_STRING LinkName
;
224 OBJECT_ATTRIBUTES ObjectAttributes
;
229 L
"\\ArcName\\multi(0)disk(0)rdisk(%lu)",
232 RtlInitUnicodeString(&ArcName
, NameBuffer
);
233 InitializeObjectAttributes(&ObjectAttributes
,
238 Status
= ZwOpenSymbolicLinkObject(&LinkHandle
,
239 SYMBOLIC_LINK_ALL_ACCESS
,
241 if (!NT_SUCCESS(Status
))
243 DPRINT1("ZwOpenSymbolicLinkObject failed for %wZ, status=%lx\n", &ArcName
, Status
);
247 LinkName
.Buffer
= NameBuffer
;
249 LinkName
.MaximumLength
= sizeof(NameBuffer
);
250 Status
= ZwQuerySymbolicLinkObject(LinkHandle
,
254 if (!NT_SUCCESS(Status
))
256 DPRINT1("ZwQuerySymbolicLinkObject failed, status=%lx\n", Status
);
259 if (LinkName
.Length
< sizeof(L
"\\Device\\Harddisk0\\Partition0") - sizeof(WCHAR
) ||
260 LinkName
.Length
>= sizeof(NameBuffer
))
262 return STATUS_UNSUCCESSFUL
;
265 NameBuffer
[LinkName
.Length
/ sizeof(WCHAR
)] = 0;
266 if (_wcsnicmp(NameBuffer
, L
"\\Device\\Harddisk", (sizeof(L
"\\Device\\Harddisk") - sizeof(WCHAR
)) / sizeof(WCHAR
)))
268 return STATUS_UNSUCCESSFUL
;
270 LinkName
.Buffer
+= (sizeof(L
"\\Device\\Harddisk") - sizeof(WCHAR
)) / sizeof(WCHAR
);
272 if (!iswdigit(*LinkName
.Buffer
))
274 return STATUS_UNSUCCESSFUL
;
277 while (iswdigit(*LinkName
.Buffer
))
279 *DiskNumber
= *DiskNumber
* 10 + *LinkName
.Buffer
- L
'0';
282 if (_wcsicmp(LinkName
.Buffer
, L
"\\Partition0"))
284 return STATUS_UNSUCCESSFUL
;
286 return STATUS_SUCCESS
;
291 xHalQueryDriveLayout(IN PUNICODE_STRING DeviceName
,
292 OUT PDRIVE_LAYOUT_INFORMATION
*LayoutInfo
)
294 IO_STATUS_BLOCK StatusBlock
;
295 DISK_GEOMETRY DiskGeometry
;
296 PDEVICE_OBJECT DeviceObject
= NULL
;
297 PFILE_OBJECT FileObject
;
302 DPRINT("xHalpQueryDriveLayout %wZ %p\n",
306 /* Get the drives sector size */
307 Status
= IoGetDeviceObjectPointer(DeviceName
,
308 FILE_READ_ATTRIBUTES
,
311 if (!NT_SUCCESS(Status
))
313 DPRINT("Status %x\n", Status
);
317 KeInitializeEvent(&Event
,
321 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
326 sizeof(DISK_GEOMETRY
),
332 ObDereferenceObject(FileObject
);
333 return(STATUS_INSUFFICIENT_RESOURCES
);
336 Status
= IoCallDriver(DeviceObject
,
338 if (Status
== STATUS_PENDING
)
340 KeWaitForSingleObject(&Event
,
345 Status
= StatusBlock
.Status
;
347 if (!NT_SUCCESS(Status
))
349 if (DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
351 DiskGeometry
.BytesPerSector
= 512;
355 ObDereferenceObject(FileObject
);
360 DPRINT("DiskGeometry.BytesPerSector: %d\n",
361 DiskGeometry
.BytesPerSector
);
363 if (DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
)
365 PDRIVE_LAYOUT_INFORMATION Buffer
;
367 /* Allocate a partition list for a single entry. */
368 Buffer
= ExAllocatePool(NonPagedPool
,
369 sizeof(DRIVE_LAYOUT_INFORMATION
));
372 RtlZeroMemory(Buffer
,
373 sizeof(DRIVE_LAYOUT_INFORMATION
));
374 Buffer
->PartitionCount
= 1;
375 *LayoutInfo
= Buffer
;
377 Status
= STATUS_SUCCESS
;
381 Status
= STATUS_UNSUCCESSFUL
;
386 /* Read the partition table */
387 Status
= IoReadPartitionTable(DeviceObject
,
388 DiskGeometry
.BytesPerSector
,
393 ObDereferenceObject(FileObject
);
400 xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
401 IN PSTRING NtDeviceName
,
402 OUT PUCHAR NtSystemPath
,
403 OUT PSTRING NtSystemPathString
)
405 PDRIVE_LAYOUT_INFORMATION
*LayoutArray
;
406 PCONFIGURATION_INFORMATION ConfigInfo
;
407 OBJECT_ATTRIBUTES ObjectAttributes
;
408 IO_STATUS_BLOCK StatusBlock
;
409 UNICODE_STRING UnicodeString1
;
410 UNICODE_STRING UnicodeString2
;
420 PKEY_VALUE_PARTIAL_INFORMATION PartialInformation
;
421 PREG_DISK_MOUNT_INFO DiskMountInfo
;
424 DPRINT("xHalIoAssignDriveLetters()\n");
426 ConfigInfo
= IoGetConfigurationInformation();
428 RDiskCount
= xHalpGetRDiskCount();
430 DPRINT("RDiskCount %d\n", RDiskCount
);
432 Buffer1
= (PWSTR
)ExAllocatePool(PagedPool
,
434 Buffer2
= (PWSTR
)ExAllocatePool(PagedPool
,
437 PartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)ExAllocatePool(PagedPool
,
438 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(REG_DISK_MOUNT_INFO
));
440 DiskMountInfo
= (PREG_DISK_MOUNT_INFO
) PartialInformation
->Data
;
442 /* Open or Create the 'MountedDevices' key */
443 RtlInitUnicodeString(&UnicodeString1
, L
"\\Registry\\Machine\\SYSTEM\\MountedDevices");
444 InitializeObjectAttributes(&ObjectAttributes
,
446 OBJ_CASE_INSENSITIVE
,
449 Status
= ZwOpenKey(&hKey
,
452 if (!NT_SUCCESS(Status
))
454 Status
= ZwCreateKey(&hKey
,
459 REG_OPTION_NON_VOLATILE
,
462 if (!NT_SUCCESS(Status
))
465 DPRINT("ZwCreateKey failed for %wZ, status=%x\n", &UnicodeString1
, Status
);
468 /* Create PhysicalDrive links */
469 DPRINT("Physical disk drives: %d\n", ConfigInfo
->DiskCount
);
470 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
473 L
"\\Device\\Harddisk%d\\Partition0",
475 RtlInitUnicodeString(&UnicodeString1
,
478 InitializeObjectAttributes(&ObjectAttributes
,
484 Status
= ZwOpenFile(&FileHandle
,
485 FILE_READ_DATA
| SYNCHRONIZE
,
489 FILE_SYNCHRONOUS_IO_NONALERT
);
490 if (NT_SUCCESS(Status
))
495 L
"\\??\\PhysicalDrive%d",
497 RtlInitUnicodeString(&UnicodeString2
,
500 DPRINT("Creating link: %S ==> %S\n",
504 IoCreateSymbolicLink(&UnicodeString2
,
509 /* Initialize layout array */
510 LayoutArray
= ExAllocatePool(NonPagedPool
,
511 ConfigInfo
->DiskCount
* sizeof(PDRIVE_LAYOUT_INFORMATION
));
512 RtlZeroMemory(LayoutArray
,
513 ConfigInfo
->DiskCount
* sizeof(PDRIVE_LAYOUT_INFORMATION
));
514 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
517 L
"\\Device\\Harddisk%d\\Partition0",
519 RtlInitUnicodeString(&UnicodeString1
,
522 Status
= xHalQueryDriveLayout(&UnicodeString1
,
524 if (!NT_SUCCESS(Status
))
526 DbgPrint("xHalQueryDriveLayout() failed (Status = 0x%lx)\n",
528 LayoutArray
[i
] = NULL
;
531 /* We don't use the RewritePartition value while mounting the disks.
532 * We use this value for marking pre-assigned (registry) partitions.
534 for (j
= 0; j
< LayoutArray
[i
]->PartitionCount
; j
++)
536 LayoutArray
[i
]->PartitionEntry
[j
].RewritePartition
= FALSE
;
541 /* Dump layout array */
542 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
544 DPRINT("Harddisk %d:\n",
547 if (LayoutArray
[i
] == NULL
)
550 DPRINT("Logical partitions: %d\n",
551 LayoutArray
[i
]->PartitionCount
);
553 for (j
= 0; j
< LayoutArray
[i
]->PartitionCount
; j
++)
555 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%I64u count:%I64u\n",
557 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
,
558 LayoutArray
[i
]->PartitionEntry
[j
].BootIndicator
,
559 LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
,
560 LayoutArray
[i
]->PartitionEntry
[j
].StartingOffset
.QuadPart
,
561 LayoutArray
[i
]->PartitionEntry
[j
].PartitionLength
.QuadPart
);
566 /* Assign pre-assigned (registry) partitions */
569 for (k
= 2; k
< 26; k
++)
571 swprintf(Buffer1
, DiskMountString
, L
'A' + k
);
572 RtlInitUnicodeString(&UnicodeString1
, Buffer1
);
573 Status
= ZwQueryValueKey(hKey
,
575 KeyValuePartialInformation
,
577 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(REG_DISK_MOUNT_INFO
),
579 if (NT_SUCCESS(Status
) &&
580 PartialInformation
->Type
== REG_BINARY
&&
581 PartialInformation
->DataLength
== sizeof(REG_DISK_MOUNT_INFO
))
583 DPRINT("%wZ => %08x:%08x%08x\n", &UnicodeString1
, DiskMountInfo
->Signature
,
584 DiskMountInfo
->StartingOffset
.u
.HighPart
, DiskMountInfo
->StartingOffset
.u
.LowPart
);
586 BOOLEAN Found
= FALSE
;
587 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
589 DPRINT("%x\n", LayoutArray
[i
]->Signature
);
590 if (LayoutArray
[i
] &&
591 LayoutArray
[i
]->Signature
&&
592 LayoutArray
[i
]->Signature
== DiskMountInfo
->Signature
)
594 for (j
= 0; j
< LayoutArray
[i
]->PartitionCount
; j
++)
596 if (LayoutArray
[i
]->PartitionEntry
[j
].StartingOffset
.QuadPart
== DiskMountInfo
->StartingOffset
.QuadPart
)
598 if (IsRecognizedPartition(LayoutArray
[i
]->PartitionEntry
[j
].PartitionType
) &&
599 LayoutArray
[i
]->PartitionEntry
[j
].RewritePartition
== FALSE
)
602 L
"\\Device\\Harddisk%d\\Partition%d",
604 LayoutArray
[i
]->PartitionEntry
[j
].PartitionNumber
);
605 RtlInitUnicodeString(&UnicodeString2
,
609 DPRINT(" %wZ\n", &UnicodeString2
);
610 Found
= HalpAssignDrive(&UnicodeString2
,
612 DOSDEVICE_DRIVE_FIXED
,
613 DiskMountInfo
->Signature
,
614 DiskMountInfo
->StartingOffset
,
616 /* Mark the partition as assigned */
617 LayoutArray
[i
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
626 /* We didn't find a partition for this entry, remove them. */
627 Status
= ZwDeleteValueKey(hKey
, &UnicodeString1
);
634 /* Assign bootable partition on first harddisk */
635 DPRINT("Assigning bootable primary partition on first harddisk:\n");
638 Status
= xHalpGetDiskNumberFromRDisk(0, &DiskNumber
);
639 if (NT_SUCCESS(Status
) &&
640 DiskNumber
< ConfigInfo
->DiskCount
&&
641 LayoutArray
[DiskNumber
])
643 /* Search for bootable partition */
644 for (j
= 0; j
< NUM_PARTITION_TABLE_ENTRIES
&& j
< LayoutArray
[DiskNumber
]->PartitionCount
; j
++)
646 if ((LayoutArray
[DiskNumber
]->PartitionEntry
[j
].BootIndicator
== TRUE
) &&
647 IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
))
649 if (LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
)
652 L
"\\Device\\Harddisk%lu\\Partition%d",
654 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
655 RtlInitUnicodeString(&UnicodeString2
,
659 DPRINT(" %wZ\n", &UnicodeString2
);
660 HalpAssignDrive(&UnicodeString2
,
662 DOSDEVICE_DRIVE_FIXED
,
663 LayoutArray
[DiskNumber
]->Signature
,
664 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
666 /* Mark the partition as assigned */
667 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
675 /* Assign remaining primary partitions */
676 DPRINT("Assigning remaining primary partitions:\n");
677 for (RDisk
= 0; RDisk
< RDiskCount
; RDisk
++)
679 Status
= xHalpGetDiskNumberFromRDisk(RDisk
, &DiskNumber
);
680 if (NT_SUCCESS(Status
) &&
681 DiskNumber
< ConfigInfo
->DiskCount
&&
682 LayoutArray
[DiskNumber
])
684 /* Search for primary partitions */
685 for (j
= 0; (j
< NUM_PARTITION_TABLE_ENTRIES
) && (j
< LayoutArray
[DiskNumber
]->PartitionCount
); j
++)
687 if (LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
&&
688 IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
))
691 L
"\\Device\\Harddisk%d\\Partition%d",
693 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
694 RtlInitUnicodeString(&UnicodeString2
,
700 HalpAssignDrive(&UnicodeString2
,
702 DOSDEVICE_DRIVE_FIXED
,
703 LayoutArray
[DiskNumber
]->Signature
,
704 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
706 /* Mark the partition as assigned */
707 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
713 /* Assign extended (logical) partitions */
714 DPRINT("Assigning extended (logical) partitions:\n");
715 for (RDisk
= 0; RDisk
< RDiskCount
; RDisk
++)
717 Status
= xHalpGetDiskNumberFromRDisk(RDisk
, &DiskNumber
);
718 if (NT_SUCCESS(Status
) &&
719 DiskNumber
< ConfigInfo
->DiskCount
&&
720 LayoutArray
[DiskNumber
])
722 /* Search for extended partitions */
723 for (j
= NUM_PARTITION_TABLE_ENTRIES
; j
< LayoutArray
[DiskNumber
]->PartitionCount
; j
++)
725 if (IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
) &&
726 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
&&
727 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
!= 0)
730 L
"\\Device\\Harddisk%d\\Partition%d",
732 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
733 RtlInitUnicodeString(&UnicodeString2
,
739 HalpAssignDrive(&UnicodeString2
,
741 DOSDEVICE_DRIVE_FIXED
,
742 LayoutArray
[DiskNumber
]->Signature
,
743 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
745 /* Mark the partition as assigned */
746 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
752 /* Assign remaining primary partitions without an arc-name */
753 DPRINT("Assigning remaining primary partitions:\n");
754 for (DiskNumber
= 0; DiskNumber
< ConfigInfo
->DiskCount
; DiskNumber
++)
756 if (LayoutArray
[DiskNumber
])
758 /* Search for primary partitions */
759 for (j
= 0; (j
< NUM_PARTITION_TABLE_ENTRIES
) && (j
< LayoutArray
[DiskNumber
]->PartitionCount
); j
++)
761 if (LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
&&
762 IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
))
765 L
"\\Device\\Harddisk%d\\Partition%d",
767 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
768 RtlInitUnicodeString(&UnicodeString2
,
774 HalpAssignDrive(&UnicodeString2
,
776 DOSDEVICE_DRIVE_FIXED
,
777 LayoutArray
[DiskNumber
]->Signature
,
778 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
780 /* Mark the partition as assigned */
781 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
787 /* Assign extended (logical) partitions without an arc-name */
788 DPRINT("Assigning extended (logical) partitions:\n");
789 for (DiskNumber
= 0; DiskNumber
< ConfigInfo
->DiskCount
; DiskNumber
++)
791 if (LayoutArray
[DiskNumber
])
793 /* Search for extended partitions */
794 for (j
= NUM_PARTITION_TABLE_ENTRIES
; j
< LayoutArray
[DiskNumber
]->PartitionCount
; j
++)
796 if (IsRecognizedPartition(LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionType
) &&
797 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
== FALSE
&&
798 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
!= 0)
801 L
"\\Device\\Harddisk%d\\Partition%d",
803 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].PartitionNumber
);
804 RtlInitUnicodeString(&UnicodeString2
,
810 HalpAssignDrive(&UnicodeString2
,
812 DOSDEVICE_DRIVE_FIXED
,
813 LayoutArray
[DiskNumber
]->Signature
,
814 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].StartingOffset
,
816 /* Mark the partition as assigned */
817 LayoutArray
[DiskNumber
]->PartitionEntry
[j
].RewritePartition
= TRUE
;
823 /* Assign removable disk drives */
824 DPRINT("Assigning removable disk drives:\n");
825 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
829 /* Search for virtual partitions */
830 if (LayoutArray
[i
]->PartitionCount
== 1 &&
831 LayoutArray
[i
]->PartitionEntry
[0].PartitionType
== 0)
834 L
"\\Device\\Harddisk%d\\Partition1",
836 RtlInitUnicodeString(&UnicodeString2
,
842 HalpAssignDrive(&UnicodeString2
,
844 DOSDEVICE_DRIVE_REMOVABLE
,
846 RtlConvertLongToLargeInteger(0),
852 /* Free layout array */
853 for (i
= 0; i
< ConfigInfo
->DiskCount
; i
++)
855 if (LayoutArray
[i
] != NULL
)
856 ExFreePool(LayoutArray
[i
]);
858 ExFreePool(LayoutArray
);
860 /* Assign floppy drives */
861 DPRINT("Floppy drives: %d\n", ConfigInfo
->FloppyCount
);
862 for (i
= 0; i
< ConfigInfo
->FloppyCount
; i
++)
865 L
"\\Device\\Floppy%d",
867 RtlInitUnicodeString(&UnicodeString1
,
870 /* Assign drive letters A: or B: or first free drive letter */
873 HalpAssignDrive(&UnicodeString1
,
874 (i
< 2) ? i
: AUTO_DRIVE
,
875 DOSDEVICE_DRIVE_REMOVABLE
,
877 RtlConvertLongToLargeInteger(0),
881 /* Assign cdrom drives */
882 DPRINT("CD-Rom drives: %d\n", ConfigInfo
->CdRomCount
);
883 for (i
= 0; i
< ConfigInfo
->CdRomCount
; i
++)
886 L
"\\Device\\CdRom%d",
888 RtlInitUnicodeString(&UnicodeString1
,
891 /* Assign first free drive letter */
892 DPRINT(" %wZ\n", &UnicodeString1
);
893 HalpAssignDrive(&UnicodeString1
,
895 DOSDEVICE_DRIVE_CDROM
,
897 RtlConvertLongToLargeInteger(0),
901 /* Anything else to do? */
903 ExFreePool(PartialInformation
);
914 /* PRIVATE FUNCTIONS *********************************************************/
918 HalpGetFullGeometry(IN PDEVICE_OBJECT DeviceObject
,
919 IN PDISK_GEOMETRY Geometry
,
920 OUT PULONGLONG RealSectorCount
)
923 IO_STATUS_BLOCK IoStatusBlock
;
926 PARTITION_INFORMATION PartitionInfo
;
929 /* Allocate a non-paged event */
930 Event
= ExAllocatePoolWithTag(NonPagedPool
,
933 if (!Event
) return STATUS_INSUFFICIENT_RESOURCES
;
936 KeInitializeEvent(Event
, NotificationEvent
, FALSE
);
939 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
944 sizeof(DISK_GEOMETRY
),
950 /* Fail, free the event */
951 ExFreePoolWithTag(Event
, TAG_FILE_SYSTEM
);
952 return STATUS_INSUFFICIENT_RESOURCES
;
955 /* Call the driver and check if it's pending */
956 Status
= IoCallDriver(DeviceObject
, Irp
);
957 if (Status
== STATUS_PENDING
)
959 /* Wait on the driver */
960 KeWaitForSingleObject(Event
, Executive
, KernelMode
, FALSE
, NULL
);
961 Status
= IoStatusBlock
.Status
;
964 /* Check if the driver returned success */
965 if(NT_SUCCESS(Status
))
967 /* Build another IRP */
968 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO
,
973 sizeof(PARTITION_INFORMATION
),
979 /* Fail, free the event */
980 ExFreePoolWithTag(Event
, TAG_FILE_SYSTEM
);
981 return STATUS_INSUFFICIENT_RESOURCES
;
984 /* Call the driver and check if it's pending */
985 Status
= IoCallDriver(DeviceObject
, Irp
);
986 if (Status
== STATUS_PENDING
)
988 /* Wait on the driver */
989 KeWaitForSingleObject(Event
, Executive
, KernelMode
, FALSE
, NULL
);
990 Status
= IoStatusBlock
.Status
;
993 /* Check if the driver returned success */
994 if(NT_SUCCESS(Status
))
996 /* Get the number of sectors */
997 *RealSectorCount
= (PartitionInfo
.PartitionLength
.QuadPart
/
998 Geometry
->BytesPerSector
);
1002 /* Free the event and return the Status */
1003 ExFreePoolWithTag(Event
, TAG_FILE_SYSTEM
);
1009 HalpIsValidPartitionEntry(IN PPARTITION_DESCRIPTOR Entry
,
1010 IN ULONGLONG MaxOffset
,
1011 IN ULONGLONG MaxSector
)
1013 ULONGLONG EndingSector
;
1016 /* Unused partitions are considered valid */
1017 if (Entry
->PartitionType
== PARTITION_ENTRY_UNUSED
) return TRUE
;
1019 /* Get the last sector of the partition */
1020 EndingSector
= GET_STARTING_SECTOR(Entry
) + GET_PARTITION_LENGTH(Entry
);
1022 /* Check if it's more then the maximum sector */
1023 if (EndingSector
> MaxSector
)
1025 /* Invalid partition */
1026 DPRINT1("FSTUB: entry is invalid\n");
1027 DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry
));
1028 DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry
));
1029 DPRINT1("FSTUB: end %#I64x\n", EndingSector
);
1030 DPRINT1("FSTUB: max %#I64x\n", MaxSector
);
1033 else if(GET_STARTING_SECTOR(Entry
) > MaxOffset
)
1035 /* Invalid partition */
1036 DPRINT1("FSTUB: entry is invalid\n");
1037 DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry
));
1038 DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry
));
1039 DPRINT1("FSTUB: end %#I64x\n", EndingSector
);
1040 DPRINT1("FSTUB: maxOffset %#I64x\n", MaxOffset
);
1044 /* It's fine, return success */
1050 HalpCalculateChsValues(IN PLARGE_INTEGER PartitionOffset
,
1051 IN PLARGE_INTEGER PartitionLength
,
1052 IN CCHAR ShiftCount
,
1053 IN ULONG SectorsPerTrack
,
1054 IN ULONG NumberOfTracks
,
1055 IN ULONG ConventionalCylinders
,
1056 OUT PPARTITION_DESCRIPTOR PartitionDescriptor
)
1058 LARGE_INTEGER FirstSector
, SectorCount
;
1059 ULONG LastSector
, Remainder
, SectorsPerCylinder
;
1060 ULONG StartingCylinder
, EndingCylinder
;
1061 ULONG StartingTrack
, EndingTrack
;
1062 ULONG StartingSector
, EndingSector
;
1065 /* Calculate the number of sectors for each cylinder */
1066 SectorsPerCylinder
= SectorsPerTrack
* NumberOfTracks
;
1068 /* Calculate the first sector, and the sector count */
1069 FirstSector
.QuadPart
= PartitionOffset
->QuadPart
>> ShiftCount
;
1070 SectorCount
.QuadPart
= PartitionLength
->QuadPart
>> ShiftCount
;
1072 /* Now calculate the last sector */
1073 LastSector
= FirstSector
.LowPart
+ SectorCount
.LowPart
- 1;
1075 /* Calculate the first and last cylinders */
1076 StartingCylinder
= FirstSector
.LowPart
/ SectorsPerCylinder
;
1077 EndingCylinder
= LastSector
/ SectorsPerCylinder
;
1079 /* Set the default number of cylinders */
1080 if (!ConventionalCylinders
) ConventionalCylinders
= 1024;
1082 /* Normalize the values */
1083 if (StartingCylinder
>= ConventionalCylinders
)
1085 /* Set the maximum to 1023 */
1086 StartingCylinder
= ConventionalCylinders
- 1;
1088 if (EndingCylinder
>= ConventionalCylinders
)
1090 /* Set the maximum to 1023 */
1091 EndingCylinder
= ConventionalCylinders
- 1;
1094 /* Calculate the starting head and sector that still remain */
1095 Remainder
= FirstSector
.LowPart
% SectorsPerCylinder
;
1096 StartingTrack
= Remainder
/ SectorsPerTrack
;
1097 StartingSector
= Remainder
% SectorsPerTrack
;
1099 /* Calculate the ending head and sector that still remain */
1100 Remainder
= LastSector
% SectorsPerCylinder
;
1101 EndingTrack
= Remainder
/ SectorsPerTrack
;
1102 EndingSector
= Remainder
% SectorsPerTrack
;
1104 /* Set cylinder data for the MSB */
1105 PartitionDescriptor
->StartingCylinderMsb
= (UCHAR
)StartingCylinder
;
1106 PartitionDescriptor
->EndingCylinderMsb
= (UCHAR
)EndingCylinder
;
1108 /* Set the track data */
1109 PartitionDescriptor
->StartingTrack
= (UCHAR
)StartingTrack
;
1110 PartitionDescriptor
->EndingTrack
= (UCHAR
)EndingTrack
;
1112 /* Update cylinder data for the LSB */
1113 StartingCylinder
= ((StartingSector
+ 1) & 0x3F) |
1114 ((StartingCylinder
>> 2) & 0xC0);
1115 EndingCylinder
= ((EndingSector
+ 1) & 0x3F) |
1116 ((EndingCylinder
>> 2) & 0xC0);
1118 /* Set the cylinder data for the LSB */
1119 PartitionDescriptor
->StartingCylinderLsb
= (UCHAR
)StartingCylinder
;
1120 PartitionDescriptor
->EndingCylinderLsb
= (UCHAR
)EndingCylinder
;
1125 xHalGetPartialGeometry(IN PDEVICE_OBJECT DeviceObject
,
1126 IN PULONG ConventionalCylinders
,
1127 IN PLONGLONG DiskSize
)
1129 PDISK_GEOMETRY DiskGeometry
= NULL
;
1130 PIO_STATUS_BLOCK IoStatusBlock
= NULL
;
1131 PKEVENT Event
= NULL
;
1136 *ConventionalCylinders
= 0;
1139 /* Allocate the structure in nonpaged pool */
1140 DiskGeometry
= ExAllocatePoolWithTag(NonPagedPool
,
1141 sizeof(DISK_GEOMETRY
),
1143 if (!DiskGeometry
) goto Cleanup
;
1145 /* Allocate the status block in nonpaged pool */
1146 IoStatusBlock
= ExAllocatePoolWithTag(NonPagedPool
,
1147 sizeof(IO_STATUS_BLOCK
),
1149 if (!IoStatusBlock
) goto Cleanup
;
1151 /* Allocate the event in nonpaged pool too */
1152 Event
= ExAllocatePoolWithTag(NonPagedPool
,
1155 if (!Event
) goto Cleanup
;
1157 /* Initialize the event */
1158 KeInitializeEvent(Event
, NotificationEvent
, FALSE
);
1161 Irp
= IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY
,
1166 sizeof(DISK_GEOMETRY
),
1170 if (!Irp
) goto Cleanup
;
1172 /* Now call the driver */
1173 Status
= IoCallDriver(DeviceObject
, Irp
);
1174 if (Status
== STATUS_PENDING
)
1176 /* Wait for it to complete */
1177 KeWaitForSingleObject(Event
, Executive
, KernelMode
, FALSE
, NULL
);
1178 Status
= IoStatusBlock
->Status
;
1181 /* Check driver status */
1182 if (NT_SUCCESS(Status
))
1184 /* Return the cylinder count */
1185 *ConventionalCylinders
= DiskGeometry
->Cylinders
.LowPart
;
1187 /* Make sure it's not larger then 1024 */
1188 if (DiskGeometry
->Cylinders
.LowPart
>= 1024)
1190 /* Otherwise, normalize the value */
1191 *ConventionalCylinders
= 1024;
1194 /* Calculate the disk size */
1195 *DiskSize
= DiskGeometry
->Cylinders
.QuadPart
*
1196 DiskGeometry
->TracksPerCylinder
*
1197 DiskGeometry
->SectorsPerTrack
*
1198 DiskGeometry
->BytesPerSector
;
1202 /* Free all the pointers */
1203 if (Event
) ExFreePoolWithTag(Event
, TAG_FILE_SYSTEM
);
1204 if (IoStatusBlock
) ExFreePool(IoStatusBlock
);
1205 if (DiskGeometry
) ExFreePool(DiskGeometry
);
1211 xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject
,
1212 IN ULONG SectorSize
,
1213 IN ULONG MbrTypeIdentifier
,
1214 OUT PVOID
*MbrBuffer
)
1216 LARGE_INTEGER Offset
;
1220 IO_STATUS_BLOCK IoStatusBlock
;
1222 PPARTITION_DESCRIPTOR PartitionDescriptor
;
1224 PIO_STACK_LOCATION IoStackLocation
;
1225 Offset
.QuadPart
= 0;
1227 /* Assume failure */
1230 /* Normalize the buffer size */
1231 BufferSize
= max(SectorSize
, 512);
1233 /* Allocate the buffer */
1234 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
1235 PAGE_SIZE
> BufferSize
?
1236 PAGE_SIZE
: BufferSize
,
1238 if (!Buffer
) return;
1240 /* Initialize the Event */
1241 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1244 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
1254 ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
1258 /* Make sure to override volume verification */
1259 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
1260 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
1262 /* Call the driver */
1263 Status
= IoCallDriver(DeviceObject
, Irp
);
1264 if (Status
== STATUS_PENDING
)
1266 /* Wait for completion */
1267 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1268 Status
= IoStatusBlock
.Status
;
1271 /* Check driver Status */
1272 if (NT_SUCCESS(Status
))
1274 /* Validate the MBR Signature */
1275 if (((PUSHORT
)Buffer
)[BOOT_SIGNATURE_OFFSET
] != BOOT_RECORD_SIGNATURE
)
1278 ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
1282 /* Get the partition entry */
1283 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1284 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1286 /* Make sure it's what the caller wanted */
1287 if (PartitionDescriptor
->PartitionType
!= MbrTypeIdentifier
)
1289 /* It's not, free our buffer */
1290 ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
1294 /* Check if this is a secondary entry */
1295 if (PartitionDescriptor
->PartitionType
== 0x54)
1297 /* Return our buffer, but at sector 63 */
1298 *(PULONG
)Buffer
= 63;
1299 *MbrBuffer
= Buffer
;
1301 else if (PartitionDescriptor
->PartitionType
== 0x55)
1303 /* EZ Drive, return the buffer directly */
1304 *MbrBuffer
= Buffer
;
1308 /* Otherwise crash on debug builds */
1309 ASSERT(PartitionDescriptor
->PartitionType
== 0x55);
1317 xHalIoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject
,
1318 IN ULONG SectorSize
,
1319 IN BOOLEAN ReturnRecognizedPartitions
,
1320 IN OUT PDRIVE_LAYOUT_INFORMATION
*PartitionBuffer
)
1323 IO_STATUS_BLOCK IoStatusBlock
;
1325 PPARTITION_DESCRIPTOR PartitionDescriptor
;
1328 PPARTITION_INFORMATION PartitionInfo
;
1329 PUCHAR Buffer
= NULL
;
1330 ULONG BufferSize
= 2048, InputSize
;
1331 PDRIVE_LAYOUT_INFORMATION DriveLayoutInfo
= NULL
;
1332 LONG j
= -1, i
= -1, k
;
1333 DISK_GEOMETRY DiskGeometry
;
1334 LONGLONG EndSector
, MaxSector
, StartOffset
;
1335 ULONGLONG MaxOffset
;
1336 LARGE_INTEGER Offset
, VolumeOffset
;
1337 BOOLEAN IsPrimary
= TRUE
, IsEzDrive
= FALSE
, MbrFound
= FALSE
;
1338 BOOLEAN IsValid
, IsEmpty
= TRUE
;
1340 PIO_STACK_LOCATION IoStackLocation
;
1341 PBOOT_SECTOR_INFO BootSectorInfo
= (PBOOT_SECTOR_INFO
)Buffer
;
1342 UCHAR PartitionType
;
1343 LARGE_INTEGER HiddenSectors64
;
1344 VolumeOffset
.QuadPart
= Offset
.QuadPart
= 0;
1347 /* Allocate the buffer */
1348 *PartitionBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
1351 if (!(*PartitionBuffer
)) return STATUS_INSUFFICIENT_RESOURCES
;
1353 /* Normalize the buffer size */
1354 InputSize
= max(512, SectorSize
);
1356 /* Check for EZ Drive */
1357 HalExamineMBR(DeviceObject
, InputSize
, 0x55, &MbrBuffer
);
1360 /* EZ Drive found, bias the offset */
1362 ExFreePool(MbrBuffer
);
1363 Offset
.QuadPart
= 512;
1366 /* Get drive geometry */
1367 Status
= HalpGetFullGeometry(DeviceObject
, &DiskGeometry
, &MaxOffset
);
1368 if (!NT_SUCCESS(Status
))
1370 ExFreePoolWithTag(*PartitionBuffer
, TAG_FILE_SYSTEM
);
1371 *PartitionBuffer
= NULL
;
1375 /* Get the end and maximum sector */
1376 EndSector
= MaxOffset
;
1377 MaxSector
= MaxOffset
<< 1;
1378 DPRINT("FSTUB: MaxOffset = %#I64x, MaxSector = %#I64x\n",
1379 MaxOffset
, MaxSector
);
1381 /* Allocate our buffer */
1382 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, PAGE_SIZE
, TAG_FILE_SYSTEM
);
1385 /* Fail, free the input buffer */
1386 ExFreePoolWithTag(*PartitionBuffer
, TAG_FILE_SYSTEM
);
1387 *PartitionBuffer
= NULL
;
1388 return STATUS_INSUFFICIENT_RESOURCES
;
1391 /* Start partition loop */
1394 /* Assume the partition is valid */
1397 /* Initialize the event */
1398 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1400 /* Clear the buffer and build the IRP */
1401 RtlZeroMemory(Buffer
, InputSize
);
1402 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
1412 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1416 /* Make sure to disable volume verification */
1417 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
1418 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
1420 /* Call the driver */
1421 Status
= IoCallDriver(DeviceObject
, Irp
);
1422 if (Status
== STATUS_PENDING
)
1424 /* Wait for completion */
1425 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1426 Status
= IoStatusBlock
.Status
;
1429 /* Normalize status code and check for failure */
1430 if (Status
== STATUS_NO_DATA_DETECTED
) Status
= STATUS_SUCCESS
;
1431 if (!NT_SUCCESS(Status
)) break;
1433 /* If we biased for EZ-Drive, unbias now */
1434 if (IsEzDrive
&& (Offset
.QuadPart
== 512)) Offset
.QuadPart
= 0;
1436 /* Make sure this is a valid MBR */
1437 if (((PUSHORT
)Buffer
)[BOOT_SIGNATURE_OFFSET
] != BOOT_RECORD_SIGNATURE
)
1439 /* It's not, fail */
1440 DPRINT1("FSTUB: (IoReadPartitionTable) No 0xaa55 found in "
1441 "partition table %d\n", j
+ 1);
1445 /* At this point we have a valid MBR */
1448 /* Check if we weren't given an offset */
1449 if (!Offset
.QuadPart
)
1451 /* Then read the signature off the disk */
1452 (*PartitionBuffer
)->Signature
= ((PULONG
)Buffer
)
1453 [PARTITION_TABLE_OFFSET
/ 2 - 1];
1456 /* Get the partition descriptor array */
1457 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1458 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1460 /* Get the partition type */
1461 PartitionType
= PartitionDescriptor
->PartitionType
;
1463 /* Start looping partitions */
1465 DPRINT("FSTUB: Partition Table %d:\n", j
);
1466 for (Entry
= 1, k
= 0; Entry
<= 4; Entry
++, PartitionDescriptor
++)
1468 /* Get the partition type */
1469 PartitionType
= PartitionDescriptor
->PartitionType
;
1471 /* Print debug messages */
1472 DPRINT("Partition Entry %d,%d: type %#x %s\n",
1476 (PartitionDescriptor
->ActiveFlag
) ? "Active" : "");
1477 DPRINT("\tOffset %#08lx for %#08lx Sectors\n",
1478 GET_STARTING_SECTOR(PartitionDescriptor
),
1479 GET_PARTITION_LENGTH(PartitionDescriptor
));
1481 /* Make sure that the partition is valid, unless it's the first */
1482 if (!(HalpIsValidPartitionEntry(PartitionDescriptor
,
1484 MaxSector
)) && !(j
))
1486 /* It's invalid, so fail */
1491 /* Check if it's a container */
1492 if (IsContainerPartition(PartitionType
))
1494 /* Increase the count of containers */
1497 /* More then one table is invalid */
1498 DPRINT1("FSTUB: Multiple container partitions found in "
1499 "partition table %d\n - table is invalid\n",
1506 /* Check if the partition is supposedly empty */
1509 /* But check if it actually has a start and/or length */
1510 if ((GET_STARTING_SECTOR(PartitionDescriptor
)) ||
1511 (GET_PARTITION_LENGTH(PartitionDescriptor
)))
1513 /* So then it's not really empty */
1518 /* Check if the caller wanted only recognized partitions */
1519 if (ReturnRecognizedPartitions
)
1521 /* Then check if this one is unused, or a container */
1522 if ((PartitionType
== PARTITION_ENTRY_UNUSED
) ||
1523 IsContainerPartition(PartitionType
))
1525 /* Skip it, since the caller doesn't want it */
1530 /* Increase the structure count and check if they can fit */
1531 if ((sizeof(DRIVE_LAYOUT_INFORMATION
) +
1532 (++i
* sizeof(PARTITION_INFORMATION
))) >
1535 /* Allocate a new buffer that's twice as big */
1536 DriveLayoutInfo
= ExAllocatePoolWithTag(NonPagedPool
,
1539 if (!DriveLayoutInfo
)
1541 /* Out of memory, unto this extra structure */
1543 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1547 /* Copy the contents of the old buffer */
1548 RtlMoveMemory(DriveLayoutInfo
,
1552 /* Free the old buffer and set this one as the new one */
1553 ExFreePoolWithTag(*PartitionBuffer
, TAG_FILE_SYSTEM
);
1554 *PartitionBuffer
= DriveLayoutInfo
;
1556 /* Double the size */
1560 /* Now get the current structure being filled and initialize it */
1561 PartitionInfo
= &(*PartitionBuffer
)->PartitionEntry
[i
];
1562 PartitionInfo
->PartitionType
= PartitionType
;
1563 PartitionInfo
->RewritePartition
= FALSE
;
1565 /* Check if we're dealing with a partition that's in use */
1566 if (PartitionType
!= PARTITION_ENTRY_UNUSED
)
1568 /* Check if it's bootable */
1569 PartitionInfo
->BootIndicator
= PartitionDescriptor
->
1573 /* Check if its' a container */
1574 if (IsContainerPartition(PartitionType
))
1576 /* Then don't recognize it and use the volume offset */
1577 PartitionInfo
->RecognizedPartition
= FALSE
;
1578 StartOffset
= VolumeOffset
.QuadPart
;
1582 /* Then recognize it and use the partition offset */
1583 PartitionInfo
->RecognizedPartition
= TRUE
;
1584 StartOffset
= Offset
.QuadPart
;
1587 /* Get the starting offset */
1588 PartitionInfo
->StartingOffset
.QuadPart
=
1590 UInt32x32To64(GET_STARTING_SECTOR(PartitionDescriptor
),
1593 /* Calculate the number of hidden sectors */
1594 HiddenSectors64
.QuadPart
= (PartitionInfo
->
1595 StartingOffset
.QuadPart
-
1598 PartitionInfo
->HiddenSectors
= HiddenSectors64
.LowPart
;
1600 /* Get the partition length */
1601 PartitionInfo
->PartitionLength
.QuadPart
=
1602 UInt32x32To64(GET_PARTITION_LENGTH(PartitionDescriptor
),
1605 /* FIXME: REACTOS HACK */
1606 PartitionInfo
->PartitionNumber
= i
+ 1;
1610 /* Otherwise, clear all the relevant fields */
1611 PartitionInfo
->BootIndicator
= FALSE
;
1612 PartitionInfo
->RecognizedPartition
= FALSE
;
1613 PartitionInfo
->StartingOffset
.QuadPart
= 0;
1614 PartitionInfo
->PartitionLength
.QuadPart
= 0;
1615 PartitionInfo
->HiddenSectors
= 0;
1617 /* FIXME: REACTOS HACK */
1618 PartitionInfo
->PartitionNumber
= 0;
1622 /* Finish debug log, and check for failure */
1624 if (!NT_SUCCESS(Status
)) break;
1626 /* Also check if we hit an invalid entry here */
1629 /* We did, so break out of the loop minus one entry */
1634 /* Reset the offset */
1635 Offset
.QuadPart
= 0;
1637 /* Go back to the descriptor array and loop it */
1638 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1639 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1640 for (Entry
= 1; Entry
<= 4; Entry
++, PartitionDescriptor
++)
1642 /* Check if this is a container partition, since we skipped them */
1643 if (IsContainerPartition(PartitionType
))
1645 /* Get its offset */
1646 Offset
.QuadPart
= VolumeOffset
.QuadPart
+
1648 GET_STARTING_SECTOR(PartitionDescriptor
),
1651 /* If this is a primary partition, this is the volume offset */
1652 if (IsPrimary
) VolumeOffset
= Offset
;
1654 /* Also update the maximum sector */
1655 MaxSector
= GET_PARTITION_LENGTH(PartitionDescriptor
);
1656 DPRINT1("FSTUB: MaxSector now = %#08lx\n", MaxSector
);
1661 /* Loop the next partitions, which are not primary anymore */
1663 } while (Offset
.HighPart
| Offset
.LowPart
);
1665 /* Check if this is a removable device that's probably a super-floppy */
1666 if ((DiskGeometry
.MediaType
== RemovableMedia
) &&
1671 /* Read the jump bytes to detect super-floppy */
1672 if ((BootSectorInfo
->JumpByte
[0] == 0xeb) ||
1673 (BootSectorInfo
->JumpByte
[0] == 0xe9))
1675 /* Super floppes don't have typical MBRs, so skip them */
1676 DPRINT1("FSTUB: Jump byte %#x found along with empty partition "
1677 "table - disk is a super floppy and has no valid MBR\n",
1678 BootSectorInfo
->JumpByte
);
1683 /* Check if we're still at partition -1 */
1686 /* The likely cause is the super floppy detection above */
1687 if ((MbrFound
) || (DiskGeometry
.MediaType
== RemovableMedia
))
1689 /* Print out debugging information */
1690 DPRINT1("FSTUB: Drive %#p has no valid MBR. Make it into a "
1693 DPRINT1("FSTUB: Drive has %#08lx sectors and is %#016I64x "
1695 EndSector
, EndSector
* DiskGeometry
.BytesPerSector
);
1697 /* We should at least have some sectors */
1700 /* Get the entry we'll use */
1701 PartitionInfo
= &(*PartitionBuffer
)->PartitionEntry
[0];
1703 /* Fill it out with data for a super-floppy */
1704 PartitionInfo
->RewritePartition
= FALSE
;
1705 PartitionInfo
->RecognizedPartition
= TRUE
;
1706 PartitionInfo
->PartitionType
= PARTITION_FAT_16
;
1707 PartitionInfo
->BootIndicator
= FALSE
;
1708 PartitionInfo
->HiddenSectors
= 0;
1709 PartitionInfo
->StartingOffset
.QuadPart
= 0;
1710 PartitionInfo
->PartitionLength
.QuadPart
= (EndSector
*
1714 /* FIXME: REACTOS HACK */
1715 PartitionInfo
->PartitionNumber
= 0;
1717 /* Set the signature and set the count back to 0 */
1718 (*PartitionBuffer
)->Signature
= 1;
1724 /* Otherwise, this isn't a super floppy, so set an invalid count */
1729 /* Set the partition count */
1730 (*PartitionBuffer
)->PartitionCount
= ++i
;
1732 /* If we have no count, delete the signature */
1733 if (!i
) (*PartitionBuffer
)->Signature
= 0;
1735 /* Free the buffer and check for success */
1736 if (Buffer
) ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
1737 if (!NT_SUCCESS(Status
)) ExFreePoolWithTag(*PartitionBuffer
, TAG_FILE_SYSTEM
);
1745 xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject
,
1746 IN ULONG SectorSize
,
1747 IN ULONG PartitionNumber
,
1748 IN ULONG PartitionType
)
1752 IO_STATUS_BLOCK IoStatusBlock
;
1754 LARGE_INTEGER Offset
, VolumeOffset
;
1755 PUCHAR Buffer
= NULL
;
1759 PPARTITION_DESCRIPTOR PartitionDescriptor
;
1760 BOOLEAN IsPrimary
= TRUE
, IsEzDrive
= FALSE
;
1762 PIO_STACK_LOCATION IoStackLocation
;
1763 VolumeOffset
.QuadPart
= Offset
.QuadPart
= 0;
1766 /* Normalize the buffer size */
1767 BufferSize
= max(512, SectorSize
);
1769 /* Check for EZ Drive */
1770 HalExamineMBR(DeviceObject
, BufferSize
, 0x55, &MbrBuffer
);
1773 /* EZ Drive found, bias the offset */
1775 ExFreePool(MbrBuffer
);
1776 Offset
.QuadPart
= 512;
1779 /* Allocate our partition buffer */
1780 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, PAGE_SIZE
, TAG_FILE_SYSTEM
);
1781 if (!Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
1783 /* Initialize the event we'll use and loop partitions */
1784 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1787 /* Reset the event since we reuse it */
1788 KeResetEvent(&Event
);
1790 /* Build the read IRP */
1791 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
1801 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1805 /* Make sure to disable volume verification */
1806 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
1807 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
1809 /* Call the driver */
1810 Status
= IoCallDriver(DeviceObject
, Irp
);
1811 if (Status
== STATUS_PENDING
)
1813 /* Wait for completion */
1814 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1815 Status
= IoStatusBlock
.Status
;
1818 /* Check for failure */
1819 if (!NT_SUCCESS(Status
)) break;
1821 /* If we biased for EZ-Drive, unbias now */
1822 if (IsEzDrive
&& (Offset
.QuadPart
== 512)) Offset
.QuadPart
= 0;
1824 /* Make sure this is a valid MBR */
1825 if (((PUSHORT
)Buffer
)[BOOT_SIGNATURE_OFFSET
] != BOOT_RECORD_SIGNATURE
)
1827 /* It's not, fail */
1828 Status
= STATUS_BAD_MASTER_BOOT_RECORD
;
1832 /* Get the partition descriptors and loop them */
1833 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1834 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1835 for (Entry
= 1; Entry
<= 4; Entry
++, PartitionDescriptor
++)
1837 /* Check if it's unused or a container partition */
1838 if ((PartitionDescriptor
->PartitionType
==
1839 PARTITION_ENTRY_UNUSED
) ||
1840 (IsContainerPartition(PartitionDescriptor
->PartitionType
)))
1842 /* Go to the next one */
1846 /* It's a valid partition, so increase the partition count */
1847 if (++i
== PartitionNumber
)
1849 /* We found a match, set the type */
1850 PartitionDescriptor
->PartitionType
= (UCHAR
)PartitionType
;
1852 /* Reset the reusable event */
1853 KeResetEvent(&Event
);
1855 /* Build the write IRP */
1856 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
1866 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1870 /* Disable volume verification */
1871 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
1872 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
1874 /* Call the driver */
1875 Status
= IoCallDriver(DeviceObject
, Irp
);
1876 if (Status
== STATUS_PENDING
)
1878 /* Wait for completion */
1879 KeWaitForSingleObject(&Event
,
1884 Status
= IoStatusBlock
.Status
;
1887 /* We're done, break out of the loop */
1892 /* If we looped all the partitions, break out */
1893 if (Entry
<= NUM_PARTITION_TABLE_ENTRIES
) break;
1895 /* Nothing found yet, get the partition array again */
1896 PartitionDescriptor
= (PPARTITION_DESCRIPTOR
)
1897 &(((PUSHORT
)Buffer
)[PARTITION_TABLE_OFFSET
]);
1898 for (Entry
= 1; Entry
<= 4; Entry
++, PartitionDescriptor
++)
1900 /* Check if this was a container partition (we skipped these) */
1901 if (IsContainerPartition(PartitionDescriptor
->PartitionType
))
1903 /* Update the partition offset */
1904 Offset
.QuadPart
= VolumeOffset
.QuadPart
+
1905 GET_STARTING_SECTOR(PartitionDescriptor
) *
1908 /* If this was the primary partition, update the volume too */
1909 if (IsPrimary
) VolumeOffset
= Offset
;
1914 /* Check if we already searched all the partitions */
1915 if (Entry
> NUM_PARTITION_TABLE_ENTRIES
)
1917 /* Then we failed to find a good MBR */
1918 Status
= STATUS_BAD_MASTER_BOOT_RECORD
;
1922 /* Loop the next partitions, which are not primary anymore */
1924 } while (i
< PartitionNumber
);
1926 /* Everything done, cleanup */
1927 if (Buffer
) ExFreePool(Buffer
);
1933 xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject
,
1934 IN ULONG SectorSize
,
1935 IN ULONG SectorsPerTrack
,
1936 IN ULONG NumberOfHeads
,
1937 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer
)
1940 IO_STATUS_BLOCK IoStatusBlock
;
1942 NTSTATUS Status
= STATUS_SUCCESS
;
1946 PPARTITION_TABLE PartitionTable
;
1947 LARGE_INTEGER Offset
, NextOffset
, ExtendedOffset
, SectorOffset
;
1948 LARGE_INTEGER StartOffset
, PartitionLength
;
1951 BOOLEAN IsEzDrive
= FALSE
, IsSuperFloppy
= FALSE
, DoRewrite
= FALSE
, IsMbr
;
1952 ULONG ConventionalCylinders
;
1954 PDISK_LAYOUT DiskLayout
= (PDISK_LAYOUT
)PartitionBuffer
;
1956 UCHAR PartitionType
;
1957 PIO_STACK_LOCATION IoStackLocation
;
1958 PPARTITION_INFORMATION PartitionInfo
= PartitionBuffer
->PartitionEntry
;
1959 PPARTITION_INFORMATION TableEntry
;
1960 ExtendedOffset
.QuadPart
= NextOffset
.QuadPart
= Offset
.QuadPart
= 0;
1963 /* Normalize the buffer size */
1964 BufferSize
= max(512, SectorSize
);
1966 /* Get the partial drive geometry */
1967 xHalGetPartialGeometry(DeviceObject
, &ConventionalCylinders
, &DiskSize
);
1969 /* Check for EZ Drive */
1970 HalExamineMBR(DeviceObject
, BufferSize
, 0x55, &MbrBuffer
);
1973 /* EZ Drive found, bias the offset */
1975 ExFreePool(MbrBuffer
);
1976 Offset
.QuadPart
= 512;
1979 /* Get the number of bits to shift to multiply by the sector size */
1980 for (k
= 0; k
< 32; k
++) if ((SectorSize
>> k
) == 1) break;
1982 /* Check if there's only one partition */
1983 if (PartitionBuffer
->PartitionCount
== 1)
1985 /* Check if it has no starting offset or hidden sectors */
1986 if (!(PartitionInfo
->StartingOffset
.QuadPart
) &&
1987 !(PartitionInfo
->HiddenSectors
))
1989 /* Then it's a super floppy */
1990 IsSuperFloppy
= TRUE
;
1992 /* Which also means it must be non-bootable FAT-16 */
1993 if ((PartitionInfo
->PartitionNumber
) ||
1994 (PartitionInfo
->PartitionType
!= PARTITION_FAT_16
) ||
1995 (PartitionInfo
->BootIndicator
))
1997 /* It's not, so we fail */
1998 return STATUS_INVALID_PARAMETER
;
2001 /* Check if it needs a rewrite, and disable EZ drive for sure */
2002 if (PartitionInfo
->RewritePartition
) DoRewrite
= TRUE
;
2007 /* Count the number of partition tables */
2008 DiskLayout
->TableCount
= (PartitionBuffer
->PartitionCount
+ 4 - 1) / 4;
2010 /* Allocate our partition buffer */
2011 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, PAGE_SIZE
, TAG_FILE_SYSTEM
);
2012 if (!Buffer
) return STATUS_INSUFFICIENT_RESOURCES
;
2014 /* Loop the entries */
2015 Entry
= (PPTE
)&Buffer
[PARTITION_TABLE_OFFSET
];
2016 for (i
= 0; i
< DiskLayout
->TableCount
; i
++)
2018 /* Set if this is the MBR partition */
2021 /* Initialize th event */
2022 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
2024 /* Build the read IRP */
2025 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_READ
,
2035 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2039 /* Make sure to disable volume verification */
2040 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
2041 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
2043 /* Call the driver */
2044 Status
= IoCallDriver(DeviceObject
, Irp
);
2045 if (Status
== STATUS_PENDING
)
2047 /* Wait for completion */
2048 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
2049 Status
= IoStatusBlock
.Status
;
2052 /* Check for failure */
2053 if (!NT_SUCCESS(Status
)) break;
2055 /* If we biased for EZ-Drive, unbias now */
2056 if (IsEzDrive
&& (Offset
.QuadPart
== 512)) Offset
.QuadPart
= 0;
2058 /* Check if this is a normal disk */
2061 /* Set the boot record signature */
2062 Buffer
[BOOT_SIGNATURE_OFFSET
] = BOOT_RECORD_SIGNATURE
;
2064 /* By default, don't require a rewrite */
2067 /* Check if we don't have an offset */
2068 if (!Offset
.QuadPart
)
2070 /* Check if the signature doesn't match */
2071 if (((PULONG
)Buffer
)[PARTITION_TABLE_OFFSET
/ 2 - 1] !=
2072 PartitionBuffer
->Signature
)
2074 /* Then write the signature and now w need a rewrite */
2075 ((PULONG
)Buffer
)[PARTITION_TABLE_OFFSET
/ 2 - 1] =
2076 PartitionBuffer
->Signature
;
2081 /* Loop the partition table entries */
2082 PartitionTable
= &DiskLayout
->PartitionTable
[i
];
2083 for (j
= 0; j
< 4; j
++)
2085 /* Get the current entry and type */
2086 TableEntry
= &PartitionTable
->PartitionEntry
[j
];
2087 PartitionType
= TableEntry
->PartitionType
;
2089 /* Check if the entry needs a rewrite */
2090 if (TableEntry
->RewritePartition
)
2092 /* Then we need one too */
2095 /* Save the type and if it's a bootable partition */
2096 Entry
[j
].PartitionType
= TableEntry
->PartitionType
;
2097 Entry
[j
].ActiveFlag
= TableEntry
->BootIndicator
? 0x80 : 0;
2099 /* Make sure it's used */
2100 if (PartitionType
!= PARTITION_ENTRY_UNUSED
)
2102 /* Make sure it's not a container (unless primary) */
2103 if ((IsMbr
) || !(IsContainerPartition(PartitionType
)))
2105 /* Use the partition offset */
2106 StartOffset
.QuadPart
= Offset
.QuadPart
;
2110 /* Use the extended logical partition offset */
2111 StartOffset
.QuadPart
= ExtendedOffset
.QuadPart
;
2114 /* Set the sector offset */
2115 SectorOffset
.QuadPart
= TableEntry
->
2116 StartingOffset
.QuadPart
-
2117 StartOffset
.QuadPart
;
2119 /* Now calculate the starting sector */
2120 StartOffset
.QuadPart
= SectorOffset
.QuadPart
>> k
;
2121 Entry
[j
].StartingSector
= StartOffset
.LowPart
;
2123 /* As well as the length */
2124 PartitionLength
.QuadPart
= TableEntry
->PartitionLength
.
2126 Entry
[j
].PartitionLength
= PartitionLength
.LowPart
;
2128 /* Calculate the CHS values */
2129 HalpCalculateChsValues(&TableEntry
->StartingOffset
,
2130 &TableEntry
->PartitionLength
,
2134 ConventionalCylinders
,
2135 (PPARTITION_DESCRIPTOR
)
2140 /* Otherwise set up an empty entry */
2141 Entry
[j
].StartingSector
= 0;
2142 Entry
[j
].PartitionLength
= 0;
2143 Entry
[j
].StartingTrack
= 0;
2144 Entry
[j
].EndingTrack
= 0;
2145 Entry
[j
].StartingCylinder
= 0;
2146 Entry
[j
].EndingCylinder
= 0;
2150 /* Check if this is a container partition */
2151 if (IsContainerPartition(PartitionType
))
2153 /* Then update the offset to use */
2154 NextOffset
= TableEntry
->StartingOffset
;
2159 /* Check if we need to write back the buffer */
2162 /* We don't need to do this again */
2165 /* Initialize the event */
2166 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
2168 /* If we unbiased for EZ-Drive, rebias now */
2169 if ((IsEzDrive
) && !(Offset
.QuadPart
)) Offset
.QuadPart
= 512;
2171 /* Build the write IRP */
2172 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_WRITE
,
2182 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2186 /* Make sure to disable volume verification */
2187 IoStackLocation
= IoGetNextIrpStackLocation(Irp
);
2188 IoStackLocation
->Flags
|= SL_OVERRIDE_VERIFY_VOLUME
;
2190 /* Call the driver */
2191 Status
= IoCallDriver(DeviceObject
, Irp
);
2192 if (Status
== STATUS_PENDING
)
2194 /* Wait for completion */
2195 KeWaitForSingleObject(&Event
,
2200 Status
= IoStatusBlock
.Status
;
2203 /* Check for failure */
2204 if (!NT_SUCCESS(Status
)) break;
2206 /* If we biased for EZ-Drive, unbias now */
2207 if (IsEzDrive
&& (Offset
.QuadPart
== 512)) Offset
.QuadPart
= 0;
2210 /* Update the partition offset and set the extended offset if needed */
2211 Offset
= NextOffset
;
2212 if (IsMbr
) ExtendedOffset
= NextOffset
;
2215 /* If we had a buffer, free it, then return status */
2216 if (Buffer
) ExFreePoolWithTag(Buffer
, TAG_FILE_SYSTEM
);
2220 /* PUBLIC FUNCTIONS **********************************************************/
2227 HalExamineMBR(IN PDEVICE_OBJECT DeviceObject
,
2228 IN ULONG SectorSize
,
2229 IN ULONG MbrTypeIdentifier
,
2230 OUT PVOID
*MbrBuffer
)
2232 HALDISPATCH
->HalExamineMBR(DeviceObject
,
2243 IoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject
,
2244 IN ULONG SectorSize
,
2245 IN BOOLEAN ReturnRecognizedPartitions
,
2246 IN OUT PDRIVE_LAYOUT_INFORMATION
*PartitionBuffer
)
2248 return HALDISPATCH
->HalIoReadPartitionTable(DeviceObject
,
2250 ReturnRecognizedPartitions
,
2259 IoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject
,
2260 IN ULONG SectorSize
,
2261 IN ULONG PartitionNumber
,
2262 IN ULONG PartitionType
)
2264 return HALDISPATCH
->HalIoSetPartitionInformation(DeviceObject
,
2275 IoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject
,
2276 IN ULONG SectorSize
,
2277 IN ULONG SectorsPerTrack
,
2278 IN ULONG NumberOfHeads
,
2279 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer
)
2281 return HALDISPATCH
->HalIoWritePartitionTable(DeviceObject
,
2293 IoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
2294 IN PSTRING NtDeviceName
,
2295 OUT PUCHAR NtSystemPath
,
2296 OUT PSTRING NtSystemPathString
)
2298 HALDISPATCH
->HalIoAssignDriveLetters(LoaderBlock
,
2301 NtSystemPathString
);