1c2c66affSColin Finck /* 2c2c66affSColin Finck * PROJECT: ReactOS Kernel 3c2c66affSColin Finck * LICENSE: GPL - See COPYING in the top level directory 4c2c66affSColin Finck * FILE: ntoskrnl/fstub/disksup.c 5c2c66affSColin Finck * PURPOSE: I/O HAL Routines for Disk Access 6c2c66affSColin Finck * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7c2c66affSColin Finck * Eric Kohl 8c2c66affSColin Finck * Casper S. Hornstrup (chorns@users.sourceforge.net) 9c2c66affSColin Finck */ 10c2c66affSColin Finck 11c2c66affSColin Finck /* INCLUDES ******************************************************************/ 12c2c66affSColin Finck 13c2c66affSColin Finck #include <ntoskrnl.h> 14c2c66affSColin Finck #define NDEBUG 15c2c66affSColin Finck #include <debug.h> 16c2c66affSColin Finck #include <internal/hal.h> 17c2c66affSColin Finck 18c2c66affSColin Finck /* DEPRECATED FUNCTIONS ******************************************************/ 19c2c66affSColin Finck 20c2c66affSColin Finck #if 1 21c2c66affSColin Finck const WCHAR DiskMountString[] = L"\\DosDevices\\%C:"; 22c2c66affSColin Finck 23c2c66affSColin Finck #define AUTO_DRIVE MAXULONG 24c2c66affSColin Finck 25c2c66affSColin Finck #define PARTITION_MAGIC 0xaa55 26c2c66affSColin Finck 27c2c66affSColin Finck #define EFI_PMBR_OSTYPE_EFI 0xEE 28c2c66affSColin Finck 29c2c66affSColin Finck #include <pshpack1.h> 30c2c66affSColin Finck 31c2c66affSColin Finck typedef struct _REG_DISK_MOUNT_INFO 32c2c66affSColin Finck { 33c2c66affSColin Finck ULONG Signature; 34c2c66affSColin Finck LARGE_INTEGER StartingOffset; 35c2c66affSColin Finck } REG_DISK_MOUNT_INFO, *PREG_DISK_MOUNT_INFO; 36c2c66affSColin Finck 37c2c66affSColin Finck #include <poppack.h> 38c2c66affSColin Finck 39c2c66affSColin Finck typedef enum _DISK_MANAGER 40c2c66affSColin Finck { 41c2c66affSColin Finck NoDiskManager, 42c2c66affSColin Finck OntrackDiskManager, 43c2c66affSColin Finck EZ_Drive 44c2c66affSColin Finck } DISK_MANAGER; 45c2c66affSColin Finck 46c2c66affSColin Finck static BOOLEAN 47c2c66affSColin Finck HalpAssignDrive(IN PUNICODE_STRING PartitionName, 48c2c66affSColin Finck IN ULONG DriveNumber, 49c2c66affSColin Finck IN UCHAR DriveType, 50c2c66affSColin Finck IN ULONG Signature, 51c2c66affSColin Finck IN LARGE_INTEGER StartingOffset, 52c2c66affSColin Finck IN HANDLE hKey, 53c2c66affSColin Finck IN PUNICODE_STRING BootDevice, 54c2c66affSColin Finck OUT PUCHAR NtSystemPath) 55c2c66affSColin Finck { 56c2c66affSColin Finck WCHAR DriveNameBuffer[16]; 57c2c66affSColin Finck UNICODE_STRING DriveName; 58c2c66affSColin Finck ULONG i; 59c2c66affSColin Finck NTSTATUS Status; 60c2c66affSColin Finck REG_DISK_MOUNT_INFO DiskMountInfo; 61c2c66affSColin Finck 62c2c66affSColin Finck DPRINT("HalpAssignDrive()\n"); 63c2c66affSColin Finck 64c2c66affSColin Finck if ((DriveNumber != AUTO_DRIVE) && (DriveNumber < 26)) 65c2c66affSColin Finck { 66c2c66affSColin Finck /* Force assignment */ 67c2c66affSColin Finck KeAcquireGuardedMutex(&ObpDeviceMapLock); 68c2c66affSColin Finck if ((ObSystemDeviceMap->DriveMap & (1 << DriveNumber)) != 0) 69c2c66affSColin Finck { 70c2c66affSColin Finck DbgPrint("Drive letter already used!\n"); 71c2c66affSColin Finck KeReleaseGuardedMutex(&ObpDeviceMapLock); 72c2c66affSColin Finck return FALSE; 73c2c66affSColin Finck } 74c2c66affSColin Finck KeReleaseGuardedMutex(&ObpDeviceMapLock); 75c2c66affSColin Finck } 76c2c66affSColin Finck else 77c2c66affSColin Finck { 78c2c66affSColin Finck /* Automatic assignment */ 79c2c66affSColin Finck DriveNumber = AUTO_DRIVE; 80c2c66affSColin Finck KeAcquireGuardedMutex(&ObpDeviceMapLock); 81c2c66affSColin Finck for (i = 2; i < 26; i++) 82c2c66affSColin Finck { 83c2c66affSColin Finck if ((ObSystemDeviceMap->DriveMap & (1 << i)) == 0) 84c2c66affSColin Finck { 85c2c66affSColin Finck DriveNumber = i; 86c2c66affSColin Finck break; 87c2c66affSColin Finck } 88c2c66affSColin Finck } 89c2c66affSColin Finck KeReleaseGuardedMutex(&ObpDeviceMapLock); 90c2c66affSColin Finck 91c2c66affSColin Finck if (DriveNumber == AUTO_DRIVE) 92c2c66affSColin Finck { 93c2c66affSColin Finck DbgPrint("No drive letter available!\n"); 94c2c66affSColin Finck return FALSE; 95c2c66affSColin Finck } 96c2c66affSColin Finck } 97c2c66affSColin Finck 98c2c66affSColin Finck DPRINT("DriveNumber %lu\n", DriveNumber); 99c2c66affSColin Finck 100c2c66affSColin Finck /* Build drive name */ 101c2c66affSColin Finck swprintf(DriveNameBuffer, 102c2c66affSColin Finck L"\\??\\%C:", 103c2c66affSColin Finck 'A' + DriveNumber); 104c2c66affSColin Finck RtlInitUnicodeString(&DriveName, 105c2c66affSColin Finck DriveNameBuffer); 106c2c66affSColin Finck 107c2c66affSColin Finck DPRINT(" %wZ ==> %wZ\n", 108c2c66affSColin Finck &DriveName, 109c2c66affSColin Finck PartitionName); 110c2c66affSColin Finck 111c2c66affSColin Finck /* Create symbolic link */ 112c2c66affSColin Finck Status = IoCreateSymbolicLink(&DriveName, 113c2c66affSColin Finck PartitionName); 114c2c66affSColin Finck 115c2c66affSColin Finck if (hKey && 116c2c66affSColin Finck DriveType == DOSDEVICE_DRIVE_FIXED && 117c2c66affSColin Finck Signature) 118c2c66affSColin Finck { 119c2c66affSColin Finck DiskMountInfo.Signature = Signature; 120c2c66affSColin Finck DiskMountInfo.StartingOffset = StartingOffset; 121c2c66affSColin Finck swprintf(DriveNameBuffer, DiskMountString, L'A' + DriveNumber); 122c2c66affSColin Finck RtlInitUnicodeString(&DriveName, DriveNameBuffer); 123c2c66affSColin Finck 124c2c66affSColin Finck Status = ZwSetValueKey(hKey, 125c2c66affSColin Finck &DriveName, 126c2c66affSColin Finck 0, 127c2c66affSColin Finck REG_BINARY, 128c2c66affSColin Finck &DiskMountInfo, 129c2c66affSColin Finck sizeof(DiskMountInfo)); 130c2c66affSColin Finck if (!NT_SUCCESS(Status)) 131c2c66affSColin Finck { 132c2c66affSColin Finck DPRINT1("ZwCreateValueKey failed for %wZ, status=%x\n", &DriveName, Status); 133c2c66affSColin Finck } 134c2c66affSColin Finck } 135c2c66affSColin Finck 136c2c66affSColin Finck /* Check if this is a boot partition */ 137c2c66affSColin Finck if (RtlCompareUnicodeString(PartitionName, BootDevice, FALSE) == 0) 138c2c66affSColin Finck { 139c2c66affSColin Finck /* Set NtSystemPath to that partition's disk letter */ 140c2c66affSColin Finck *NtSystemPath = (UCHAR)('A' + DriveNumber); 141c2c66affSColin Finck } 142c2c66affSColin Finck 143c2c66affSColin Finck return TRUE; 144c2c66affSColin Finck } 145c2c66affSColin Finck 146c2c66affSColin Finck ULONG 147c2c66affSColin Finck xHalpGetRDiskCount(VOID) 148c2c66affSColin Finck { 149c2c66affSColin Finck NTSTATUS Status; 150c2c66affSColin Finck UNICODE_STRING ArcName; 151c2c66affSColin Finck PWCHAR ArcNameBuffer; 152c2c66affSColin Finck OBJECT_ATTRIBUTES ObjectAttributes; 153c2c66affSColin Finck HANDLE DirectoryHandle; 154c2c66affSColin Finck POBJECT_DIRECTORY_INFORMATION DirectoryInfo; 155c2c66affSColin Finck ULONG Skip; 156c2c66affSColin Finck ULONG ResultLength; 157c2c66affSColin Finck ULONG CurrentRDisk; 158c2c66affSColin Finck ULONG RDiskCount; 159c2c66affSColin Finck BOOLEAN First = TRUE; 160c2c66affSColin Finck ULONG Count; 161c2c66affSColin Finck 162c2c66affSColin Finck DirectoryInfo = ExAllocatePoolWithTag(PagedPool, 2 * PAGE_SIZE, TAG_FILE_SYSTEM); 163c2c66affSColin Finck if (DirectoryInfo == NULL) 164c2c66affSColin Finck { 165c2c66affSColin Finck return 0; 166c2c66affSColin Finck } 167c2c66affSColin Finck 168c2c66affSColin Finck RtlInitUnicodeString(&ArcName, L"\\ArcName"); 169c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, 170c2c66affSColin Finck &ArcName, 171c2c66affSColin Finck 0, 172c2c66affSColin Finck NULL, 173c2c66affSColin Finck NULL); 174c2c66affSColin Finck 175c2c66affSColin Finck Status = ZwOpenDirectoryObject (&DirectoryHandle, 176c2c66affSColin Finck DIRECTORY_ALL_ACCESS, 177c2c66affSColin Finck &ObjectAttributes); 178c2c66affSColin Finck if (!NT_SUCCESS(Status)) 179c2c66affSColin Finck { 180c2c66affSColin Finck DPRINT1("ZwOpenDirectoryObject for %wZ failed, status=%lx\n", &ArcName, Status); 181c2c66affSColin Finck ExFreePoolWithTag(DirectoryInfo, TAG_FILE_SYSTEM); 182c2c66affSColin Finck return 0; 183c2c66affSColin Finck } 184c2c66affSColin Finck 185c2c66affSColin Finck RDiskCount = 0; 186c2c66affSColin Finck Skip = 0; 187c2c66affSColin Finck while (NT_SUCCESS(Status)) 188c2c66affSColin Finck { 189c2c66affSColin Finck Status = ZwQueryDirectoryObject (DirectoryHandle, 190c2c66affSColin Finck DirectoryInfo, 191c2c66affSColin Finck 2 * PAGE_SIZE, 192c2c66affSColin Finck FALSE, 193c2c66affSColin Finck First, 194c2c66affSColin Finck &Skip, 195c2c66affSColin Finck &ResultLength); 196c2c66affSColin Finck First = FALSE; 197c2c66affSColin Finck if (NT_SUCCESS(Status)) 198c2c66affSColin Finck { 199c2c66affSColin Finck Count = 0; 200c2c66affSColin Finck while (DirectoryInfo[Count].Name.Buffer) 201c2c66affSColin Finck { 202c2c66affSColin Finck DPRINT("Count %x\n", Count); 203c2c66affSColin Finck DirectoryInfo[Count].Name.Buffer[DirectoryInfo[Count].Name.Length / sizeof(WCHAR)] = 0; 204c2c66affSColin Finck ArcNameBuffer = DirectoryInfo[Count].Name.Buffer; 205c2c66affSColin Finck if (DirectoryInfo[Count].Name.Length >= sizeof(L"multi(0)disk(0)rdisk(0)") - sizeof(WCHAR) && 206c2c66affSColin Finck !_wcsnicmp(ArcNameBuffer, L"multi(0)disk(0)rdisk(", (sizeof(L"multi(0)disk(0)rdisk(") - sizeof(WCHAR)) / sizeof(WCHAR))) 207c2c66affSColin Finck { 208c2c66affSColin Finck DPRINT("%S\n", ArcNameBuffer); 209c2c66affSColin Finck ArcNameBuffer += (sizeof(L"multi(0)disk(0)rdisk(") - sizeof(WCHAR)) / sizeof(WCHAR); 210c2c66affSColin Finck CurrentRDisk = 0; 211c2c66affSColin Finck while (iswdigit(*ArcNameBuffer)) 212c2c66affSColin Finck { 213c2c66affSColin Finck CurrentRDisk = CurrentRDisk * 10 + *ArcNameBuffer - L'0'; 214c2c66affSColin Finck ArcNameBuffer++; 215c2c66affSColin Finck } 216c2c66affSColin Finck if (!_wcsicmp(ArcNameBuffer, L")") && 217c2c66affSColin Finck CurrentRDisk >= RDiskCount) 218c2c66affSColin Finck { 219c2c66affSColin Finck RDiskCount = CurrentRDisk + 1; 220c2c66affSColin Finck } 221c2c66affSColin Finck } 222c2c66affSColin Finck Count++; 223c2c66affSColin Finck } 224c2c66affSColin Finck } 225c2c66affSColin Finck } 226c2c66affSColin Finck 227c2c66affSColin Finck ZwClose(DirectoryHandle); 228c2c66affSColin Finck 229c2c66affSColin Finck ExFreePoolWithTag(DirectoryInfo, TAG_FILE_SYSTEM); 230c2c66affSColin Finck return RDiskCount; 231c2c66affSColin Finck } 232c2c66affSColin Finck 233c2c66affSColin Finck NTSTATUS 234c2c66affSColin Finck xHalpGetDiskNumberFromRDisk(ULONG RDisk, PULONG DiskNumber) 235c2c66affSColin Finck { 236c2c66affSColin Finck WCHAR NameBuffer[80]; 237c2c66affSColin Finck UNICODE_STRING ArcName; 238c2c66affSColin Finck UNICODE_STRING LinkName; 239c2c66affSColin Finck OBJECT_ATTRIBUTES ObjectAttributes; 240c2c66affSColin Finck HANDLE LinkHandle; 241c2c66affSColin Finck NTSTATUS Status; 242c2c66affSColin Finck 243c2c66affSColin Finck swprintf(NameBuffer, 244c2c66affSColin Finck L"\\ArcName\\multi(0)disk(0)rdisk(%lu)", 245c2c66affSColin Finck RDisk); 246c2c66affSColin Finck 247c2c66affSColin Finck RtlInitUnicodeString(&ArcName, NameBuffer); 248c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, 249c2c66affSColin Finck &ArcName, 250c2c66affSColin Finck 0, 251c2c66affSColin Finck NULL, 252c2c66affSColin Finck NULL); 253c2c66affSColin Finck Status = ZwOpenSymbolicLinkObject(&LinkHandle, 254c2c66affSColin Finck SYMBOLIC_LINK_ALL_ACCESS, 255c2c66affSColin Finck &ObjectAttributes); 256c2c66affSColin Finck if (!NT_SUCCESS(Status)) 257c2c66affSColin Finck { 258c2c66affSColin Finck DPRINT1("ZwOpenSymbolicLinkObject failed for %wZ, status=%lx\n", &ArcName, Status); 259c2c66affSColin Finck return Status; 260c2c66affSColin Finck } 261c2c66affSColin Finck 262c2c66affSColin Finck LinkName.Buffer = NameBuffer; 263c2c66affSColin Finck LinkName.Length = 0; 264c2c66affSColin Finck LinkName.MaximumLength = sizeof(NameBuffer); 265c2c66affSColin Finck Status = ZwQuerySymbolicLinkObject(LinkHandle, 266c2c66affSColin Finck &LinkName, 267c2c66affSColin Finck NULL); 268c2c66affSColin Finck ZwClose(LinkHandle); 269c2c66affSColin Finck if (!NT_SUCCESS(Status)) 270c2c66affSColin Finck { 271c2c66affSColin Finck DPRINT1("ZwQuerySymbolicLinkObject failed, status=%lx\n", Status); 272c2c66affSColin Finck return Status; 273c2c66affSColin Finck } 274c2c66affSColin Finck if (LinkName.Length < sizeof(L"\\Device\\Harddisk0\\Partition0") - sizeof(WCHAR) || 275c2c66affSColin Finck LinkName.Length >= sizeof(NameBuffer)) 276c2c66affSColin Finck { 277c2c66affSColin Finck return STATUS_UNSUCCESSFUL; 278c2c66affSColin Finck } 279c2c66affSColin Finck 280c2c66affSColin Finck NameBuffer[LinkName.Length / sizeof(WCHAR)] = 0; 281c2c66affSColin Finck if (_wcsnicmp(NameBuffer, L"\\Device\\Harddisk", (sizeof(L"\\Device\\Harddisk") - sizeof(WCHAR)) / sizeof(WCHAR))) 282c2c66affSColin Finck { 283c2c66affSColin Finck return STATUS_UNSUCCESSFUL; 284c2c66affSColin Finck } 285c2c66affSColin Finck LinkName.Buffer += (sizeof(L"\\Device\\Harddisk") - sizeof(WCHAR)) / sizeof(WCHAR); 286c2c66affSColin Finck 287c2c66affSColin Finck if (!iswdigit(*LinkName.Buffer)) 288c2c66affSColin Finck { 289c2c66affSColin Finck return STATUS_UNSUCCESSFUL; 290c2c66affSColin Finck } 291c2c66affSColin Finck *DiskNumber = 0; 292c2c66affSColin Finck while (iswdigit(*LinkName.Buffer)) 293c2c66affSColin Finck { 294c2c66affSColin Finck *DiskNumber = *DiskNumber * 10 + *LinkName.Buffer - L'0'; 295c2c66affSColin Finck LinkName.Buffer++; 296c2c66affSColin Finck } 297c2c66affSColin Finck if (_wcsicmp(LinkName.Buffer, L"\\Partition0")) 298c2c66affSColin Finck { 299c2c66affSColin Finck return STATUS_UNSUCCESSFUL; 300c2c66affSColin Finck } 301c2c66affSColin Finck return STATUS_SUCCESS; 302c2c66affSColin Finck } 303c2c66affSColin Finck 304c2c66affSColin Finck NTSTATUS 305c2c66affSColin Finck FASTCALL 306c2c66affSColin Finck xHalQueryDriveLayout(IN PUNICODE_STRING DeviceName, 307c2c66affSColin Finck OUT PDRIVE_LAYOUT_INFORMATION *LayoutInfo) 308c2c66affSColin Finck { 309c2c66affSColin Finck IO_STATUS_BLOCK StatusBlock; 310c2c66affSColin Finck DISK_GEOMETRY DiskGeometry; 311c2c66affSColin Finck PDEVICE_OBJECT DeviceObject = NULL; 312c2c66affSColin Finck PFILE_OBJECT FileObject; 313c2c66affSColin Finck KEVENT Event; 314c2c66affSColin Finck PIRP Irp; 315c2c66affSColin Finck NTSTATUS Status; 316c2c66affSColin Finck 317c2c66affSColin Finck DPRINT("xHalpQueryDriveLayout %wZ %p\n", 318c2c66affSColin Finck DeviceName, 319c2c66affSColin Finck LayoutInfo); 320c2c66affSColin Finck 321c2c66affSColin Finck /* Get the drives sector size */ 322c2c66affSColin Finck Status = IoGetDeviceObjectPointer(DeviceName, 323c2c66affSColin Finck FILE_READ_ATTRIBUTES, 324c2c66affSColin Finck &FileObject, 325c2c66affSColin Finck &DeviceObject); 326c2c66affSColin Finck if (!NT_SUCCESS(Status)) 327c2c66affSColin Finck { 328c2c66affSColin Finck DPRINT("Status %x\n", Status); 329c2c66affSColin Finck return(Status); 330c2c66affSColin Finck } 331c2c66affSColin Finck 332c2c66affSColin Finck KeInitializeEvent(&Event, 333c2c66affSColin Finck NotificationEvent, 334c2c66affSColin Finck FALSE); 335c2c66affSColin Finck 336c2c66affSColin Finck Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY, 337c2c66affSColin Finck DeviceObject, 338c2c66affSColin Finck NULL, 339c2c66affSColin Finck 0, 340c2c66affSColin Finck &DiskGeometry, 341c2c66affSColin Finck sizeof(DISK_GEOMETRY), 342c2c66affSColin Finck FALSE, 343c2c66affSColin Finck &Event, 344c2c66affSColin Finck &StatusBlock); 345c2c66affSColin Finck if (Irp == NULL) 346c2c66affSColin Finck { 347c2c66affSColin Finck ObDereferenceObject(FileObject); 348c2c66affSColin Finck return(STATUS_INSUFFICIENT_RESOURCES); 349c2c66affSColin Finck } 350c2c66affSColin Finck 351c2c66affSColin Finck Status = IoCallDriver(DeviceObject, 352c2c66affSColin Finck Irp); 353c2c66affSColin Finck if (Status == STATUS_PENDING) 354c2c66affSColin Finck { 355c2c66affSColin Finck KeWaitForSingleObject(&Event, 356c2c66affSColin Finck Executive, 357c2c66affSColin Finck KernelMode, 358c2c66affSColin Finck FALSE, 359c2c66affSColin Finck NULL); 360c2c66affSColin Finck Status = StatusBlock.Status; 361c2c66affSColin Finck } 362c2c66affSColin Finck if (!NT_SUCCESS(Status)) 363c2c66affSColin Finck { 364c2c66affSColin Finck if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) 365c2c66affSColin Finck { 366c2c66affSColin Finck DiskGeometry.BytesPerSector = 512; 367c2c66affSColin Finck } 368c2c66affSColin Finck else 369c2c66affSColin Finck { 370c2c66affSColin Finck ObDereferenceObject(FileObject); 371c2c66affSColin Finck return(Status); 372c2c66affSColin Finck } 373c2c66affSColin Finck } 374c2c66affSColin Finck 375c2c66affSColin Finck DPRINT("DiskGeometry.BytesPerSector: %lu\n", 376c2c66affSColin Finck DiskGeometry.BytesPerSector); 377c2c66affSColin Finck 378c2c66affSColin Finck if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) 379c2c66affSColin Finck { 380c2c66affSColin Finck PDRIVE_LAYOUT_INFORMATION Buffer; 381c2c66affSColin Finck 382c2c66affSColin Finck /* Allocate a partition list for a single entry. */ 383c2c66affSColin Finck Buffer = ExAllocatePoolWithTag(NonPagedPool, 384c2c66affSColin Finck sizeof(DRIVE_LAYOUT_INFORMATION), TAG_FILE_SYSTEM); 385c2c66affSColin Finck if (Buffer != NULL) 386c2c66affSColin Finck { 387c2c66affSColin Finck RtlZeroMemory(Buffer, 388c2c66affSColin Finck sizeof(DRIVE_LAYOUT_INFORMATION)); 389c2c66affSColin Finck Buffer->PartitionCount = 1; 390c2c66affSColin Finck *LayoutInfo = Buffer; 391c2c66affSColin Finck 392c2c66affSColin Finck Status = STATUS_SUCCESS; 393c2c66affSColin Finck } 394c2c66affSColin Finck else 395c2c66affSColin Finck { 396c2c66affSColin Finck Status = STATUS_UNSUCCESSFUL; 397c2c66affSColin Finck } 398c2c66affSColin Finck } 399c2c66affSColin Finck else 400c2c66affSColin Finck { 401c2c66affSColin Finck /* Read the partition table */ 402c2c66affSColin Finck Status = IoReadPartitionTable(DeviceObject, 403c2c66affSColin Finck DiskGeometry.BytesPerSector, 404c2c66affSColin Finck TRUE, 405c2c66affSColin Finck LayoutInfo); 406c2c66affSColin Finck } 407c2c66affSColin Finck 408c2c66affSColin Finck ObDereferenceObject(FileObject); 409c2c66affSColin Finck 410c2c66affSColin Finck return(Status); 411c2c66affSColin Finck } 412c2c66affSColin Finck 413c2c66affSColin Finck VOID 414c2c66affSColin Finck FASTCALL 415c2c66affSColin Finck xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock, 416c2c66affSColin Finck IN PSTRING NtDeviceName, 417c2c66affSColin Finck OUT PUCHAR NtSystemPath, 418c2c66affSColin Finck OUT PSTRING NtSystemPathString) 419c2c66affSColin Finck { 420c2c66affSColin Finck PDRIVE_LAYOUT_INFORMATION *LayoutArray; 421c2c66affSColin Finck PCONFIGURATION_INFORMATION ConfigInfo; 422c2c66affSColin Finck OBJECT_ATTRIBUTES ObjectAttributes; 423c2c66affSColin Finck IO_STATUS_BLOCK StatusBlock; 424c2c66affSColin Finck UNICODE_STRING UnicodeString1; 425c2c66affSColin Finck UNICODE_STRING UnicodeString2; 426c2c66affSColin Finck HANDLE FileHandle; 427c2c66affSColin Finck PWSTR Buffer1; 428c2c66affSColin Finck PWSTR Buffer2; 429c2c66affSColin Finck ULONG i, j, k; 430c2c66affSColin Finck ULONG DiskNumber; 431c2c66affSColin Finck ULONG RDisk; 432c2c66affSColin Finck NTSTATUS Status; 433c2c66affSColin Finck HANDLE hKey; 434c2c66affSColin Finck ULONG Length; 435c2c66affSColin Finck PKEY_VALUE_PARTIAL_INFORMATION PartialInformation; 436c2c66affSColin Finck PREG_DISK_MOUNT_INFO DiskMountInfo; 437c2c66affSColin Finck ULONG RDiskCount; 438c2c66affSColin Finck UNICODE_STRING BootDevice; 439c2c66affSColin Finck 440c2c66affSColin Finck Status = RtlAnsiStringToUnicodeString(&BootDevice, 441c2c66affSColin Finck NtDeviceName, 442c2c66affSColin Finck TRUE); 443c2c66affSColin Finck 444c2c66affSColin Finck DPRINT("xHalIoAssignDriveLetters()\n"); 445c2c66affSColin Finck 446c2c66affSColin Finck ConfigInfo = IoGetConfigurationInformation(); 447c2c66affSColin Finck 448c2c66affSColin Finck RDiskCount = xHalpGetRDiskCount(); 449c2c66affSColin Finck 450c2c66affSColin Finck DPRINT("RDiskCount %lu\n", RDiskCount); 451c2c66affSColin Finck 452c2c66affSColin Finck Buffer1 = ExAllocatePoolWithTag(PagedPool, 453c2c66affSColin Finck 64 * sizeof(WCHAR), 454c2c66affSColin Finck TAG_FILE_SYSTEM); 455c2c66affSColin Finck if (!Buffer1) return; 456c2c66affSColin Finck 457c2c66affSColin Finck Buffer2 = ExAllocatePoolWithTag(PagedPool, 458c2c66affSColin Finck 32 * sizeof(WCHAR), 459c2c66affSColin Finck TAG_FILE_SYSTEM); 460c2c66affSColin Finck if (!Buffer2) 461c2c66affSColin Finck { 462c2c66affSColin Finck ExFreePoolWithTag(Buffer1, TAG_FILE_SYSTEM); 463c2c66affSColin Finck return; 464c2c66affSColin Finck } 465c2c66affSColin Finck 466c2c66affSColin Finck PartialInformation = ExAllocatePoolWithTag(PagedPool, 467c2c66affSColin Finck sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(REG_DISK_MOUNT_INFO), 468c2c66affSColin Finck TAG_FILE_SYSTEM); 469c2c66affSColin Finck if (!PartialInformation) 470c2c66affSColin Finck { 471c2c66affSColin Finck ExFreePoolWithTag(Buffer2, TAG_FILE_SYSTEM); 472c2c66affSColin Finck ExFreePoolWithTag(Buffer1, TAG_FILE_SYSTEM); 473c2c66affSColin Finck return; 474c2c66affSColin Finck } 475c2c66affSColin Finck 476c2c66affSColin Finck DiskMountInfo = (PREG_DISK_MOUNT_INFO) PartialInformation->Data; 477c2c66affSColin Finck 478c2c66affSColin Finck /* Create or open the 'MountedDevices' key */ 479c2c66affSColin Finck RtlInitUnicodeString(&UnicodeString1, L"\\Registry\\Machine\\SYSTEM\\MountedDevices"); 480c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, 481c2c66affSColin Finck &UnicodeString1, 482c2c66affSColin Finck OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 483c2c66affSColin Finck NULL, 484c2c66affSColin Finck NULL); 485c2c66affSColin Finck Status = ZwCreateKey(&hKey, 486c2c66affSColin Finck KEY_ALL_ACCESS, 487c2c66affSColin Finck &ObjectAttributes, 488c2c66affSColin Finck 0, 489c2c66affSColin Finck NULL, 490c2c66affSColin Finck REG_OPTION_NON_VOLATILE, 491c2c66affSColin Finck NULL); 492c2c66affSColin Finck if (!NT_SUCCESS(Status)) 493c2c66affSColin Finck { 494c2c66affSColin Finck hKey = NULL; 495c2c66affSColin Finck DPRINT("ZwCreateKey failed for %wZ, status=%x\n", &UnicodeString1, Status); 496c2c66affSColin Finck } 497c2c66affSColin Finck 498c2c66affSColin Finck /* Create PhysicalDrive links */ 499c2c66affSColin Finck DPRINT("Physical disk drives: %lu\n", ConfigInfo->DiskCount); 500c2c66affSColin Finck for (i = 0; i < ConfigInfo->DiskCount; i++) 501c2c66affSColin Finck { 502c2c66affSColin Finck swprintf(Buffer1, L"\\Device\\Harddisk%lu\\Partition0", i); 503c2c66affSColin Finck RtlInitUnicodeString(&UnicodeString1, Buffer1); 504c2c66affSColin Finck 505c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, 506c2c66affSColin Finck &UnicodeString1, 507c2c66affSColin Finck 0, 508c2c66affSColin Finck NULL, 509c2c66affSColin Finck NULL); 510c2c66affSColin Finck 511c2c66affSColin Finck Status = ZwOpenFile(&FileHandle, 512c2c66affSColin Finck FILE_READ_DATA | SYNCHRONIZE, 513c2c66affSColin Finck &ObjectAttributes, 514c2c66affSColin Finck &StatusBlock, 515c2c66affSColin Finck FILE_SHARE_READ, 516c2c66affSColin Finck FILE_SYNCHRONOUS_IO_NONALERT); 517c2c66affSColin Finck if (NT_SUCCESS(Status)) 518c2c66affSColin Finck { 519c2c66affSColin Finck ZwClose(FileHandle); 520c2c66affSColin Finck 521c2c66affSColin Finck swprintf(Buffer2, L"\\??\\PhysicalDrive%lu", i); 522c2c66affSColin Finck RtlInitUnicodeString(&UnicodeString2, Buffer2); 523c2c66affSColin Finck 524c2c66affSColin Finck DPRINT("Creating link: %S ==> %S\n", 525c2c66affSColin Finck Buffer2, 526c2c66affSColin Finck Buffer1); 527c2c66affSColin Finck 528c2c66affSColin Finck IoCreateSymbolicLink(&UnicodeString2, 529c2c66affSColin Finck &UnicodeString1); 530c2c66affSColin Finck } 531c2c66affSColin Finck } 532c2c66affSColin Finck 533c2c66affSColin Finck /* Initialize layout array */ 534c2c66affSColin Finck if (ConfigInfo->DiskCount == 0) 535c2c66affSColin Finck goto end_assign_disks; 536c2c66affSColin Finck LayoutArray = ExAllocatePoolWithTag(NonPagedPool, 537c2c66affSColin Finck ConfigInfo->DiskCount * sizeof(PDRIVE_LAYOUT_INFORMATION), TAG_FILE_SYSTEM); 538c2c66affSColin Finck if (!LayoutArray) 539c2c66affSColin Finck { 540c2c66affSColin Finck ExFreePoolWithTag(PartialInformation, TAG_FILE_SYSTEM); 541c2c66affSColin Finck ExFreePoolWithTag(Buffer2, TAG_FILE_SYSTEM); 542c2c66affSColin Finck ExFreePoolWithTag(Buffer1, TAG_FILE_SYSTEM); 543c2c66affSColin Finck if (hKey) ObCloseHandle(hKey, KernelMode); 544c2c66affSColin Finck return; 545c2c66affSColin Finck } 546c2c66affSColin Finck 547c2c66affSColin Finck RtlZeroMemory(LayoutArray, 548c2c66affSColin Finck ConfigInfo->DiskCount * sizeof(PDRIVE_LAYOUT_INFORMATION)); 549c2c66affSColin Finck for (i = 0; i < ConfigInfo->DiskCount; i++) 550c2c66affSColin Finck { 551c2c66affSColin Finck swprintf(Buffer1, L"\\Device\\Harddisk%lu\\Partition0", i); 552c2c66affSColin Finck RtlInitUnicodeString(&UnicodeString1, Buffer1); 553c2c66affSColin Finck 554c2c66affSColin Finck Status = xHalQueryDriveLayout(&UnicodeString1, &LayoutArray[i]); 555c2c66affSColin Finck if (!NT_SUCCESS(Status)) 556c2c66affSColin Finck { 557c2c66affSColin Finck DbgPrint("xHalQueryDriveLayout() failed (Status = 0x%lx)\n", 558c2c66affSColin Finck Status); 559c2c66affSColin Finck LayoutArray[i] = NULL; 560c2c66affSColin Finck continue; 561c2c66affSColin Finck } 562c2c66affSColin Finck /* We don't use the RewritePartition value while mounting the disks. 563c2c66affSColin Finck * We use this value for marking pre-assigned (registry) partitions. 564c2c66affSColin Finck */ 565c2c66affSColin Finck for (j = 0; j < LayoutArray[i]->PartitionCount; j++) 566c2c66affSColin Finck { 567c2c66affSColin Finck LayoutArray[i]->PartitionEntry[j].RewritePartition = FALSE; 568c2c66affSColin Finck } 569c2c66affSColin Finck } 570c2c66affSColin Finck 571c2c66affSColin Finck #ifndef NDEBUG 572c2c66affSColin Finck /* Dump layout array */ 573c2c66affSColin Finck for (i = 0; i < ConfigInfo->DiskCount; i++) 574c2c66affSColin Finck { 575c2c66affSColin Finck DPRINT("Harddisk %d:\n", 576c2c66affSColin Finck i); 577c2c66affSColin Finck 578c2c66affSColin Finck if (LayoutArray[i] == NULL) 579c2c66affSColin Finck continue; 580c2c66affSColin Finck 581c2c66affSColin Finck DPRINT("Logical partitions: %d\n", 582c2c66affSColin Finck LayoutArray[i]->PartitionCount); 583c2c66affSColin Finck 584c2c66affSColin Finck for (j = 0; j < LayoutArray[i]->PartitionCount; j++) 585c2c66affSColin Finck { 586c2c66affSColin Finck DPRINT(" %d: nr:%x boot:%x type:%x startblock:%I64u count:%I64u\n", 587c2c66affSColin Finck j, 588c2c66affSColin Finck LayoutArray[i]->PartitionEntry[j].PartitionNumber, 589c2c66affSColin Finck LayoutArray[i]->PartitionEntry[j].BootIndicator, 590c2c66affSColin Finck LayoutArray[i]->PartitionEntry[j].PartitionType, 591c2c66affSColin Finck LayoutArray[i]->PartitionEntry[j].StartingOffset.QuadPart, 592c2c66affSColin Finck LayoutArray[i]->PartitionEntry[j].PartitionLength.QuadPart); 593c2c66affSColin Finck } 594c2c66affSColin Finck } 595c2c66affSColin Finck #endif 596c2c66affSColin Finck 597c2c66affSColin Finck /* Assign pre-assigned (registry) partitions */ 598c2c66affSColin Finck if (hKey) 599c2c66affSColin Finck { 600c2c66affSColin Finck for (k = 2; k < 26; k++) 601c2c66affSColin Finck { 602c2c66affSColin Finck swprintf(Buffer1, DiskMountString, L'A' + k); 603c2c66affSColin Finck RtlInitUnicodeString(&UnicodeString1, Buffer1); 604c2c66affSColin Finck Status = ZwQueryValueKey(hKey, 605c2c66affSColin Finck &UnicodeString1, 606c2c66affSColin Finck KeyValuePartialInformation, 607c2c66affSColin Finck PartialInformation, 608c2c66affSColin Finck sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(REG_DISK_MOUNT_INFO), 609c2c66affSColin Finck &Length); 610c2c66affSColin Finck if (NT_SUCCESS(Status) && 611c2c66affSColin Finck PartialInformation->Type == REG_BINARY && 612c2c66affSColin Finck PartialInformation->DataLength == sizeof(REG_DISK_MOUNT_INFO)) 613c2c66affSColin Finck { 614c2c66affSColin Finck DPRINT("%wZ => %08x:%08x%08x\n", &UnicodeString1, DiskMountInfo->Signature, 615c2c66affSColin Finck DiskMountInfo->StartingOffset.u.HighPart, DiskMountInfo->StartingOffset.u.LowPart); 616c2c66affSColin Finck { 617c2c66affSColin Finck BOOLEAN Found = FALSE; 618c2c66affSColin Finck for (i = 0; i < ConfigInfo->DiskCount; i++) 619c2c66affSColin Finck { 620c2c66affSColin Finck DPRINT("%x\n", LayoutArray[i]->Signature); 621c2c66affSColin Finck if (LayoutArray[i] && 622c2c66affSColin Finck LayoutArray[i]->Signature && 623c2c66affSColin Finck LayoutArray[i]->Signature == DiskMountInfo->Signature) 624c2c66affSColin Finck { 625c2c66affSColin Finck for (j = 0; j < LayoutArray[i]->PartitionCount; j++) 626c2c66affSColin Finck { 627c2c66affSColin Finck if (LayoutArray[i]->PartitionEntry[j].StartingOffset.QuadPart == DiskMountInfo->StartingOffset.QuadPart) 628c2c66affSColin Finck { 629c2c66affSColin Finck if (IsRecognizedPartition(LayoutArray[i]->PartitionEntry[j].PartitionType) && 630c2c66affSColin Finck LayoutArray[i]->PartitionEntry[j].RewritePartition == FALSE) 631c2c66affSColin Finck { 632c2c66affSColin Finck swprintf(Buffer2, 633c2c66affSColin Finck L"\\Device\\Harddisk%lu\\Partition%lu", 634c2c66affSColin Finck i, 635c2c66affSColin Finck LayoutArray[i]->PartitionEntry[j].PartitionNumber); 636c2c66affSColin Finck RtlInitUnicodeString(&UnicodeString2, Buffer2); 637c2c66affSColin Finck 638c2c66affSColin Finck /* Assign drive */ 639c2c66affSColin Finck DPRINT(" %wZ\n", &UnicodeString2); 640c2c66affSColin Finck Found = HalpAssignDrive(&UnicodeString2, 641c2c66affSColin Finck k, 642c2c66affSColin Finck DOSDEVICE_DRIVE_FIXED, 643c2c66affSColin Finck DiskMountInfo->Signature, 644c2c66affSColin Finck DiskMountInfo->StartingOffset, 645c2c66affSColin Finck NULL, 646c2c66affSColin Finck &BootDevice, 647c2c66affSColin Finck NtSystemPath); 648c2c66affSColin Finck /* Mark the partition as assigned */ 649c2c66affSColin Finck LayoutArray[i]->PartitionEntry[j].RewritePartition = TRUE; 650c2c66affSColin Finck } 651c2c66affSColin Finck break; 652c2c66affSColin Finck } 653c2c66affSColin Finck } 654c2c66affSColin Finck } 655c2c66affSColin Finck } 656c2c66affSColin Finck if (Found == FALSE) 657c2c66affSColin Finck { 658c2c66affSColin Finck /* We didn't find a partition for this entry, remove them. */ 659c2c66affSColin Finck Status = ZwDeleteValueKey(hKey, &UnicodeString1); 660c2c66affSColin Finck } 661c2c66affSColin Finck } 662c2c66affSColin Finck } 663c2c66affSColin Finck } 664c2c66affSColin Finck } 665c2c66affSColin Finck 666c2c66affSColin Finck /* Assign bootable partition on first harddisk */ 667c2c66affSColin Finck DPRINT("Assigning bootable primary partition on first harddisk:\n"); 668c2c66affSColin Finck if (RDiskCount > 0) 669c2c66affSColin Finck { 670c2c66affSColin Finck Status = xHalpGetDiskNumberFromRDisk(0, &DiskNumber); 671c2c66affSColin Finck if (NT_SUCCESS(Status) && 672c2c66affSColin Finck DiskNumber < ConfigInfo->DiskCount && 673c2c66affSColin Finck LayoutArray[DiskNumber]) 674c2c66affSColin Finck { 675c2c66affSColin Finck /* Search for bootable partition */ 676c2c66affSColin Finck for (j = 0; j < NUM_PARTITION_TABLE_ENTRIES && j < LayoutArray[DiskNumber]->PartitionCount; j++) 677c2c66affSColin Finck { 678c2c66affSColin Finck if ((LayoutArray[DiskNumber]->PartitionEntry[j].BootIndicator != FALSE) && 679c2c66affSColin Finck IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType)) 680c2c66affSColin Finck { 681c2c66affSColin Finck if (LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE) 682c2c66affSColin Finck { 683c2c66affSColin Finck swprintf(Buffer2, 684c2c66affSColin Finck L"\\Device\\Harddisk%lu\\Partition%lu", 685c2c66affSColin Finck DiskNumber, 686c2c66affSColin Finck LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber); 687c2c66affSColin Finck RtlInitUnicodeString(&UnicodeString2, Buffer2); 688c2c66affSColin Finck 689c2c66affSColin Finck /* Assign drive */ 690c2c66affSColin Finck DPRINT(" %wZ\n", &UnicodeString2); 691c2c66affSColin Finck HalpAssignDrive(&UnicodeString2, 692c2c66affSColin Finck AUTO_DRIVE, 693c2c66affSColin Finck DOSDEVICE_DRIVE_FIXED, 694c2c66affSColin Finck LayoutArray[DiskNumber]->Signature, 695c2c66affSColin Finck LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset, 696c2c66affSColin Finck hKey, 697c2c66affSColin Finck &BootDevice, 698c2c66affSColin Finck NtSystemPath); 699c2c66affSColin Finck /* Mark the partition as assigned */ 700c2c66affSColin Finck LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE; 701c2c66affSColin Finck } 702c2c66affSColin Finck break; 703c2c66affSColin Finck } 704c2c66affSColin Finck } 705c2c66affSColin Finck } 706c2c66affSColin Finck } 707c2c66affSColin Finck 708c2c66affSColin Finck /* Assign remaining primary partitions */ 709c2c66affSColin Finck DPRINT("Assigning remaining primary partitions:\n"); 710c2c66affSColin Finck for (RDisk = 0; RDisk < RDiskCount; RDisk++) 711c2c66affSColin Finck { 712c2c66affSColin Finck Status = xHalpGetDiskNumberFromRDisk(RDisk, &DiskNumber); 713c2c66affSColin Finck if (NT_SUCCESS(Status) && 714c2c66affSColin Finck DiskNumber < ConfigInfo->DiskCount && 715c2c66affSColin Finck LayoutArray[DiskNumber]) 716c2c66affSColin Finck { 717c2c66affSColin Finck /* Search for primary partitions */ 718c2c66affSColin Finck for (j = 0; (j < NUM_PARTITION_TABLE_ENTRIES) && (j < LayoutArray[DiskNumber]->PartitionCount); j++) 719c2c66affSColin Finck { 720c2c66affSColin Finck if (LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE && 721c2c66affSColin Finck IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType)) 722c2c66affSColin Finck { 723c2c66affSColin Finck swprintf(Buffer2, 724c2c66affSColin Finck L"\\Device\\Harddisk%lu\\Partition%lu", 725c2c66affSColin Finck DiskNumber, 726c2c66affSColin Finck LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber); 727c2c66affSColin Finck RtlInitUnicodeString(&UnicodeString2, Buffer2); 728c2c66affSColin Finck 729c2c66affSColin Finck /* Assign drive */ 730c2c66affSColin Finck DPRINT(" %wZ\n", 731c2c66affSColin Finck &UnicodeString2); 732c2c66affSColin Finck HalpAssignDrive(&UnicodeString2, 733c2c66affSColin Finck AUTO_DRIVE, 734c2c66affSColin Finck DOSDEVICE_DRIVE_FIXED, 735c2c66affSColin Finck LayoutArray[DiskNumber]->Signature, 736c2c66affSColin Finck LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset, 737c2c66affSColin Finck hKey, 738c2c66affSColin Finck &BootDevice, 739c2c66affSColin Finck NtSystemPath); 740c2c66affSColin Finck /* Mark the partition as assigned */ 741c2c66affSColin Finck LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE; 742c2c66affSColin Finck } 743c2c66affSColin Finck } 744c2c66affSColin Finck } 745c2c66affSColin Finck } 746c2c66affSColin Finck 747c2c66affSColin Finck /* Assign extended (logical) partitions */ 748c2c66affSColin Finck DPRINT("Assigning extended (logical) partitions:\n"); 749c2c66affSColin Finck for (RDisk = 0; RDisk < RDiskCount; RDisk++) 750c2c66affSColin Finck { 751c2c66affSColin Finck Status = xHalpGetDiskNumberFromRDisk(RDisk, &DiskNumber); 752c2c66affSColin Finck if (NT_SUCCESS(Status) && 753c2c66affSColin Finck DiskNumber < ConfigInfo->DiskCount && 754c2c66affSColin Finck LayoutArray[DiskNumber]) 755c2c66affSColin Finck { 756c2c66affSColin Finck /* Search for extended partitions */ 757c2c66affSColin Finck for (j = NUM_PARTITION_TABLE_ENTRIES; j < LayoutArray[DiskNumber]->PartitionCount; j++) 758c2c66affSColin Finck { 759c2c66affSColin Finck if (IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType) && 760c2c66affSColin Finck LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE && 761c2c66affSColin Finck LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber != 0) 762c2c66affSColin Finck { 763c2c66affSColin Finck swprintf(Buffer2, 764c2c66affSColin Finck L"\\Device\\Harddisk%lu\\Partition%lu", 765c2c66affSColin Finck DiskNumber, 766c2c66affSColin Finck LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber); 767c2c66affSColin Finck RtlInitUnicodeString(&UnicodeString2, Buffer2); 768c2c66affSColin Finck 769c2c66affSColin Finck /* Assign drive */ 770c2c66affSColin Finck DPRINT(" %wZ\n", 771c2c66affSColin Finck &UnicodeString2); 772c2c66affSColin Finck HalpAssignDrive(&UnicodeString2, 773c2c66affSColin Finck AUTO_DRIVE, 774c2c66affSColin Finck DOSDEVICE_DRIVE_FIXED, 775c2c66affSColin Finck LayoutArray[DiskNumber]->Signature, 776c2c66affSColin Finck LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset, 777c2c66affSColin Finck hKey, 778c2c66affSColin Finck &BootDevice, 779c2c66affSColin Finck NtSystemPath); 780c2c66affSColin Finck /* Mark the partition as assigned */ 781c2c66affSColin Finck LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE; 782c2c66affSColin Finck } 783c2c66affSColin Finck } 784c2c66affSColin Finck } 785c2c66affSColin Finck } 786c2c66affSColin Finck 787c2c66affSColin Finck /* Assign remaining primary partitions without an arc-name */ 788c2c66affSColin Finck DPRINT("Assigning remaining primary partitions:\n"); 789c2c66affSColin Finck for (DiskNumber = 0; DiskNumber < ConfigInfo->DiskCount; DiskNumber++) 790c2c66affSColin Finck { 791c2c66affSColin Finck if (LayoutArray[DiskNumber]) 792c2c66affSColin Finck { 793c2c66affSColin Finck /* Search for primary partitions */ 794c2c66affSColin Finck for (j = 0; (j < NUM_PARTITION_TABLE_ENTRIES) && (j < LayoutArray[DiskNumber]->PartitionCount); j++) 795c2c66affSColin Finck { 796c2c66affSColin Finck if (LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE && 797c2c66affSColin Finck IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType)) 798c2c66affSColin Finck { 799c2c66affSColin Finck swprintf(Buffer2, 800c2c66affSColin Finck L"\\Device\\Harddisk%lu\\Partition%lu", 801c2c66affSColin Finck DiskNumber, 802c2c66affSColin Finck LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber); 803c2c66affSColin Finck RtlInitUnicodeString(&UnicodeString2, Buffer2); 804c2c66affSColin Finck 805c2c66affSColin Finck /* Assign drive */ 806c2c66affSColin Finck DPRINT(" %wZ\n", 807c2c66affSColin Finck &UnicodeString2); 808c2c66affSColin Finck HalpAssignDrive(&UnicodeString2, 809c2c66affSColin Finck AUTO_DRIVE, 810c2c66affSColin Finck DOSDEVICE_DRIVE_FIXED, 811c2c66affSColin Finck LayoutArray[DiskNumber]->Signature, 812c2c66affSColin Finck LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset, 813c2c66affSColin Finck hKey, 814c2c66affSColin Finck &BootDevice, 815c2c66affSColin Finck NtSystemPath); 816c2c66affSColin Finck /* Mark the partition as assigned */ 817c2c66affSColin Finck LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE; 818c2c66affSColin Finck } 819c2c66affSColin Finck } 820c2c66affSColin Finck } 821c2c66affSColin Finck } 822c2c66affSColin Finck 823c2c66affSColin Finck /* Assign extended (logical) partitions without an arc-name */ 824c2c66affSColin Finck DPRINT("Assigning extended (logical) partitions:\n"); 825c2c66affSColin Finck for (DiskNumber = 0; DiskNumber < ConfigInfo->DiskCount; DiskNumber++) 826c2c66affSColin Finck { 827c2c66affSColin Finck if (LayoutArray[DiskNumber]) 828c2c66affSColin Finck { 829c2c66affSColin Finck /* Search for extended partitions */ 830c2c66affSColin Finck for (j = NUM_PARTITION_TABLE_ENTRIES; j < LayoutArray[DiskNumber]->PartitionCount; j++) 831c2c66affSColin Finck { 832c2c66affSColin Finck if (IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType) && 833c2c66affSColin Finck LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE && 834c2c66affSColin Finck LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber != 0) 835c2c66affSColin Finck { 836c2c66affSColin Finck swprintf(Buffer2, 837c2c66affSColin Finck L"\\Device\\Harddisk%lu\\Partition%lu", 838c2c66affSColin Finck DiskNumber, 839c2c66affSColin Finck LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber); 840c2c66affSColin Finck RtlInitUnicodeString(&UnicodeString2, Buffer2); 841c2c66affSColin Finck 842c2c66affSColin Finck /* Assign drive */ 843c2c66affSColin Finck DPRINT(" %wZ\n", 844c2c66affSColin Finck &UnicodeString2); 845c2c66affSColin Finck HalpAssignDrive(&UnicodeString2, 846c2c66affSColin Finck AUTO_DRIVE, 847c2c66affSColin Finck DOSDEVICE_DRIVE_FIXED, 848c2c66affSColin Finck LayoutArray[DiskNumber]->Signature, 849c2c66affSColin Finck LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset, 850c2c66affSColin Finck hKey, 851c2c66affSColin Finck &BootDevice, 852c2c66affSColin Finck NtSystemPath); 853c2c66affSColin Finck /* Mark the partition as assigned */ 854c2c66affSColin Finck LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE; 855c2c66affSColin Finck } 856c2c66affSColin Finck } 857c2c66affSColin Finck } 858c2c66affSColin Finck } 859c2c66affSColin Finck 860c2c66affSColin Finck /* Assign removable disk drives */ 861c2c66affSColin Finck DPRINT("Assigning removable disk drives:\n"); 862c2c66affSColin Finck for (i = 0; i < ConfigInfo->DiskCount; i++) 863c2c66affSColin Finck { 864c2c66affSColin Finck if (LayoutArray[i]) 865c2c66affSColin Finck { 866c2c66affSColin Finck /* Search for virtual partitions */ 867c2c66affSColin Finck if (LayoutArray[i]->PartitionCount == 1 && 868c2c66affSColin Finck LayoutArray[i]->PartitionEntry[0].PartitionType == 0) 869c2c66affSColin Finck { 870c2c66affSColin Finck swprintf(Buffer2, L"\\Device\\Harddisk%lu\\Partition1", i); 871c2c66affSColin Finck RtlInitUnicodeString(&UnicodeString2, Buffer2); 872c2c66affSColin Finck 873c2c66affSColin Finck /* Assign drive */ 874c2c66affSColin Finck DPRINT(" %wZ\n", 875c2c66affSColin Finck &UnicodeString2); 876c2c66affSColin Finck HalpAssignDrive(&UnicodeString2, 877c2c66affSColin Finck AUTO_DRIVE, 878c2c66affSColin Finck DOSDEVICE_DRIVE_REMOVABLE, 879c2c66affSColin Finck 0, 880c2c66affSColin Finck RtlConvertLongToLargeInteger(0), 881c2c66affSColin Finck hKey, 882c2c66affSColin Finck &BootDevice, 883c2c66affSColin Finck NtSystemPath); 884c2c66affSColin Finck } 885c2c66affSColin Finck } 886c2c66affSColin Finck } 887c2c66affSColin Finck 888c2c66affSColin Finck /* Free layout array */ 889c2c66affSColin Finck for (i = 0; i < ConfigInfo->DiskCount; i++) 890c2c66affSColin Finck { 891c2c66affSColin Finck if (LayoutArray[i] != NULL) 892c2c66affSColin Finck ExFreePoolWithTag(LayoutArray[i], TAG_FILE_SYSTEM); 893c2c66affSColin Finck } 894c2c66affSColin Finck ExFreePoolWithTag(LayoutArray, TAG_FILE_SYSTEM); 895c2c66affSColin Finck end_assign_disks: 896c2c66affSColin Finck 897c2c66affSColin Finck /* Assign floppy drives */ 898c2c66affSColin Finck DPRINT("Floppy drives: %lu\n", ConfigInfo->FloppyCount); 899c2c66affSColin Finck for (i = 0; i < ConfigInfo->FloppyCount; i++) 900c2c66affSColin Finck { 901c2c66affSColin Finck swprintf(Buffer1, L"\\Device\\Floppy%lu", i); 902c2c66affSColin Finck RtlInitUnicodeString(&UnicodeString1, Buffer1); 903c2c66affSColin Finck 904c2c66affSColin Finck /* Assign drive letters A: or B: or first free drive letter */ 905c2c66affSColin Finck DPRINT(" %wZ\n", 906c2c66affSColin Finck &UnicodeString1); 907c2c66affSColin Finck HalpAssignDrive(&UnicodeString1, 908c2c66affSColin Finck (i < 2) ? i : AUTO_DRIVE, 909c2c66affSColin Finck DOSDEVICE_DRIVE_REMOVABLE, 910c2c66affSColin Finck 0, 911c2c66affSColin Finck RtlConvertLongToLargeInteger(0), 912c2c66affSColin Finck hKey, 913c2c66affSColin Finck &BootDevice, 914c2c66affSColin Finck NtSystemPath); 915c2c66affSColin Finck } 916c2c66affSColin Finck 917c2c66affSColin Finck /* Assign cdrom drives */ 918c2c66affSColin Finck DPRINT("CD-Rom drives: %lu\n", ConfigInfo->CdRomCount); 919c2c66affSColin Finck for (i = 0; i < ConfigInfo->CdRomCount; i++) 920c2c66affSColin Finck { 921c2c66affSColin Finck swprintf(Buffer1, L"\\Device\\CdRom%lu", i); 922c2c66affSColin Finck RtlInitUnicodeString(&UnicodeString1, Buffer1); 923c2c66affSColin Finck 924c2c66affSColin Finck /* Assign first free drive letter */ 925c2c66affSColin Finck DPRINT(" %wZ\n", &UnicodeString1); 926c2c66affSColin Finck HalpAssignDrive(&UnicodeString1, 927c2c66affSColin Finck AUTO_DRIVE, 928c2c66affSColin Finck DOSDEVICE_DRIVE_CDROM, 929c2c66affSColin Finck 0, 930c2c66affSColin Finck RtlConvertLongToLargeInteger(0), 931c2c66affSColin Finck hKey, 932c2c66affSColin Finck &BootDevice, 933c2c66affSColin Finck NtSystemPath); 934c2c66affSColin Finck } 935c2c66affSColin Finck 936c2c66affSColin Finck /* Anything else to do? */ 937c2c66affSColin Finck 938c2c66affSColin Finck ExFreePoolWithTag(PartialInformation, TAG_FILE_SYSTEM); 939c2c66affSColin Finck ExFreePoolWithTag(Buffer2, TAG_FILE_SYSTEM); 940c2c66affSColin Finck ExFreePoolWithTag(Buffer1, TAG_FILE_SYSTEM); 941c2c66affSColin Finck if (hKey) ObCloseHandle(hKey, KernelMode); 942c2c66affSColin Finck } 943c2c66affSColin Finck 944c2c66affSColin Finck #endif 945c2c66affSColin Finck 946c2c66affSColin Finck /* PRIVATE FUNCTIONS *********************************************************/ 947c2c66affSColin Finck 948c2c66affSColin Finck NTSTATUS 949c2c66affSColin Finck NTAPI 950c2c66affSColin Finck HalpGetFullGeometry(IN PDEVICE_OBJECT DeviceObject, 951c2c66affSColin Finck IN PDISK_GEOMETRY Geometry, 952c2c66affSColin Finck OUT PULONGLONG RealSectorCount) 953c2c66affSColin Finck { 954c2c66affSColin Finck PIRP Irp; 955c2c66affSColin Finck IO_STATUS_BLOCK IoStatusBlock; 956c2c66affSColin Finck PKEVENT Event; 957c2c66affSColin Finck NTSTATUS Status; 958c2c66affSColin Finck PARTITION_INFORMATION PartitionInfo; 959c2c66affSColin Finck PAGED_CODE(); 960c2c66affSColin Finck 961c2c66affSColin Finck /* Allocate a non-paged event */ 962c2c66affSColin Finck Event = ExAllocatePoolWithTag(NonPagedPool, 963c2c66affSColin Finck sizeof(KEVENT), 964c2c66affSColin Finck TAG_FILE_SYSTEM); 965c2c66affSColin Finck if (!Event) return STATUS_INSUFFICIENT_RESOURCES; 966c2c66affSColin Finck 967c2c66affSColin Finck /* Initialize it */ 968c2c66affSColin Finck KeInitializeEvent(Event, NotificationEvent, FALSE); 969c2c66affSColin Finck 970c2c66affSColin Finck /* Build the IRP */ 971c2c66affSColin Finck Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY, 972c2c66affSColin Finck DeviceObject, 973c2c66affSColin Finck NULL, 974c2c66affSColin Finck 0UL, 975c2c66affSColin Finck Geometry, 976c2c66affSColin Finck sizeof(DISK_GEOMETRY), 977c2c66affSColin Finck FALSE, 978c2c66affSColin Finck Event, 979c2c66affSColin Finck &IoStatusBlock); 980c2c66affSColin Finck if (!Irp) 981c2c66affSColin Finck { 982c2c66affSColin Finck /* Fail, free the event */ 983c2c66affSColin Finck ExFreePoolWithTag(Event, TAG_FILE_SYSTEM); 984c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 985c2c66affSColin Finck } 986c2c66affSColin Finck 987c2c66affSColin Finck /* Call the driver and check if it's pending */ 988c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp); 989c2c66affSColin Finck if (Status == STATUS_PENDING) 990c2c66affSColin Finck { 991c2c66affSColin Finck /* Wait on the driver */ 992c2c66affSColin Finck KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL); 993c2c66affSColin Finck Status = IoStatusBlock.Status; 994c2c66affSColin Finck } 995c2c66affSColin Finck 996c2c66affSColin Finck /* Check if the driver returned success */ 997c2c66affSColin Finck if(NT_SUCCESS(Status)) 998c2c66affSColin Finck { 999c2c66affSColin Finck /* Build another IRP */ 1000c2c66affSColin Finck Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO, 1001c2c66affSColin Finck DeviceObject, 1002c2c66affSColin Finck NULL, 1003c2c66affSColin Finck 0UL, 1004c2c66affSColin Finck &PartitionInfo, 1005c2c66affSColin Finck sizeof(PARTITION_INFORMATION), 1006c2c66affSColin Finck FALSE, 1007c2c66affSColin Finck Event, 1008c2c66affSColin Finck &IoStatusBlock); 1009c2c66affSColin Finck if (!Irp) 1010c2c66affSColin Finck { 1011c2c66affSColin Finck /* Fail, free the event */ 1012c2c66affSColin Finck ExFreePoolWithTag(Event, TAG_FILE_SYSTEM); 1013c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 1014c2c66affSColin Finck } 1015c2c66affSColin Finck 1016c2c66affSColin Finck /* Reset event */ 1017*75850abcSThomas Faber KeClearEvent(Event); 1018c2c66affSColin Finck 1019c2c66affSColin Finck /* Call the driver and check if it's pending */ 1020c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp); 1021c2c66affSColin Finck if (Status == STATUS_PENDING) 1022c2c66affSColin Finck { 1023c2c66affSColin Finck /* Wait on the driver */ 1024c2c66affSColin Finck KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL); 1025c2c66affSColin Finck Status = IoStatusBlock.Status; 1026c2c66affSColin Finck } 1027c2c66affSColin Finck 1028c2c66affSColin Finck /* Check if the driver returned success */ 1029c2c66affSColin Finck if(NT_SUCCESS(Status)) 1030c2c66affSColin Finck { 1031c2c66affSColin Finck /* Get the number of sectors */ 1032c2c66affSColin Finck *RealSectorCount = (PartitionInfo.PartitionLength.QuadPart / 1033c2c66affSColin Finck Geometry->BytesPerSector); 1034c2c66affSColin Finck } 1035c2c66affSColin Finck } 1036c2c66affSColin Finck 1037c2c66affSColin Finck /* Free the event and return the Status */ 1038c2c66affSColin Finck ExFreePoolWithTag(Event, TAG_FILE_SYSTEM); 1039c2c66affSColin Finck return Status; 1040c2c66affSColin Finck } 1041c2c66affSColin Finck 1042c2c66affSColin Finck BOOLEAN 1043c2c66affSColin Finck NTAPI 1044c2c66affSColin Finck HalpIsValidPartitionEntry(IN PPARTITION_DESCRIPTOR Entry, 1045c2c66affSColin Finck IN ULONGLONG MaxOffset, 1046c2c66affSColin Finck IN ULONGLONG MaxSector) 1047c2c66affSColin Finck { 1048c2c66affSColin Finck ULONGLONG EndingSector; 1049c2c66affSColin Finck PAGED_CODE(); 1050c2c66affSColin Finck 1051c2c66affSColin Finck /* Unused partitions are considered valid */ 1052c2c66affSColin Finck if (Entry->PartitionType == PARTITION_ENTRY_UNUSED) return TRUE; 1053c2c66affSColin Finck 1054c2c66affSColin Finck /* Get the last sector of the partition */ 1055c2c66affSColin Finck EndingSector = GET_STARTING_SECTOR(Entry) + GET_PARTITION_LENGTH(Entry); 1056c2c66affSColin Finck 1057c2c66affSColin Finck /* Check if it's more then the maximum sector */ 1058c2c66affSColin Finck if (EndingSector > MaxSector) 1059c2c66affSColin Finck { 1060c2c66affSColin Finck /* Invalid partition */ 1061c2c66affSColin Finck DPRINT1("FSTUB: entry is invalid\n"); 1062c2c66affSColin Finck DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry)); 1063c2c66affSColin Finck DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry)); 1064c2c66affSColin Finck DPRINT1("FSTUB: end %#I64x\n", EndingSector); 1065c2c66affSColin Finck DPRINT1("FSTUB: max %#I64x\n", MaxSector); 1066c2c66affSColin Finck return FALSE; 1067c2c66affSColin Finck } 1068c2c66affSColin Finck else if(GET_STARTING_SECTOR(Entry) > MaxOffset) 1069c2c66affSColin Finck { 1070c2c66affSColin Finck /* Invalid partition */ 1071c2c66affSColin Finck DPRINT1("FSTUB: entry is invalid\n"); 1072c2c66affSColin Finck DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry)); 1073c2c66affSColin Finck DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry)); 1074c2c66affSColin Finck DPRINT1("FSTUB: end %#I64x\n", EndingSector); 1075c2c66affSColin Finck DPRINT1("FSTUB: maxOffset %#I64x\n", MaxOffset); 1076c2c66affSColin Finck return FALSE; 1077c2c66affSColin Finck } 1078c2c66affSColin Finck 1079c2c66affSColin Finck /* It's fine, return success */ 1080c2c66affSColin Finck return TRUE; 1081c2c66affSColin Finck } 1082c2c66affSColin Finck 1083c2c66affSColin Finck VOID 1084c2c66affSColin Finck NTAPI 1085c2c66affSColin Finck HalpCalculateChsValues(IN PLARGE_INTEGER PartitionOffset, 1086c2c66affSColin Finck IN PLARGE_INTEGER PartitionLength, 1087c2c66affSColin Finck IN CCHAR ShiftCount, 1088c2c66affSColin Finck IN ULONG SectorsPerTrack, 1089c2c66affSColin Finck IN ULONG NumberOfTracks, 1090c2c66affSColin Finck IN ULONG ConventionalCylinders, 1091c2c66affSColin Finck OUT PPARTITION_DESCRIPTOR PartitionDescriptor) 1092c2c66affSColin Finck { 1093c2c66affSColin Finck LARGE_INTEGER FirstSector, SectorCount; 1094c2c66affSColin Finck ULONG LastSector, Remainder, SectorsPerCylinder; 1095c2c66affSColin Finck ULONG StartingCylinder, EndingCylinder; 1096c2c66affSColin Finck ULONG StartingTrack, EndingTrack; 1097c2c66affSColin Finck ULONG StartingSector, EndingSector; 1098c2c66affSColin Finck PAGED_CODE(); 1099c2c66affSColin Finck 1100c2c66affSColin Finck /* Calculate the number of sectors for each cylinder */ 1101c2c66affSColin Finck SectorsPerCylinder = SectorsPerTrack * NumberOfTracks; 1102c2c66affSColin Finck 1103c2c66affSColin Finck /* Calculate the first sector, and the sector count */ 1104c2c66affSColin Finck FirstSector.QuadPart = PartitionOffset->QuadPart >> ShiftCount; 1105c2c66affSColin Finck SectorCount.QuadPart = PartitionLength->QuadPart >> ShiftCount; 1106c2c66affSColin Finck 1107c2c66affSColin Finck /* Now calculate the last sector */ 1108c2c66affSColin Finck LastSector = FirstSector.LowPart + SectorCount.LowPart - 1; 1109c2c66affSColin Finck 1110c2c66affSColin Finck /* Calculate the first and last cylinders */ 1111c2c66affSColin Finck StartingCylinder = FirstSector.LowPart / SectorsPerCylinder; 1112c2c66affSColin Finck EndingCylinder = LastSector / SectorsPerCylinder; 1113c2c66affSColin Finck 1114c2c66affSColin Finck /* Set the default number of cylinders */ 1115c2c66affSColin Finck if (!ConventionalCylinders) ConventionalCylinders = 1024; 1116c2c66affSColin Finck 1117c2c66affSColin Finck /* Normalize the values */ 1118c2c66affSColin Finck if (StartingCylinder >= ConventionalCylinders) 1119c2c66affSColin Finck { 1120c2c66affSColin Finck /* Set the maximum to 1023 */ 1121c2c66affSColin Finck StartingCylinder = ConventionalCylinders - 1; 1122c2c66affSColin Finck } 1123c2c66affSColin Finck if (EndingCylinder >= ConventionalCylinders) 1124c2c66affSColin Finck { 1125c2c66affSColin Finck /* Set the maximum to 1023 */ 1126c2c66affSColin Finck EndingCylinder = ConventionalCylinders - 1; 1127c2c66affSColin Finck } 1128c2c66affSColin Finck 1129c2c66affSColin Finck /* Calculate the starting head and sector that still remain */ 1130c2c66affSColin Finck Remainder = FirstSector.LowPart % SectorsPerCylinder; 1131c2c66affSColin Finck StartingTrack = Remainder / SectorsPerTrack; 1132c2c66affSColin Finck StartingSector = Remainder % SectorsPerTrack; 1133c2c66affSColin Finck 1134c2c66affSColin Finck /* Calculate the ending head and sector that still remain */ 1135c2c66affSColin Finck Remainder = LastSector % SectorsPerCylinder; 1136c2c66affSColin Finck EndingTrack = Remainder / SectorsPerTrack; 1137c2c66affSColin Finck EndingSector = Remainder % SectorsPerTrack; 1138c2c66affSColin Finck 1139c2c66affSColin Finck /* Set cylinder data for the MSB */ 1140c2c66affSColin Finck PartitionDescriptor->StartingCylinderMsb = (UCHAR)StartingCylinder; 1141c2c66affSColin Finck PartitionDescriptor->EndingCylinderMsb = (UCHAR)EndingCylinder; 1142c2c66affSColin Finck 1143c2c66affSColin Finck /* Set the track data */ 1144c2c66affSColin Finck PartitionDescriptor->StartingTrack = (UCHAR)StartingTrack; 1145c2c66affSColin Finck PartitionDescriptor->EndingTrack = (UCHAR)EndingTrack; 1146c2c66affSColin Finck 1147c2c66affSColin Finck /* Update cylinder data for the LSB */ 1148c2c66affSColin Finck StartingCylinder = ((StartingSector + 1) & 0x3F) | 1149c2c66affSColin Finck ((StartingCylinder >> 2) & 0xC0); 1150c2c66affSColin Finck EndingCylinder = ((EndingSector + 1) & 0x3F) | 1151c2c66affSColin Finck ((EndingCylinder >> 2) & 0xC0); 1152c2c66affSColin Finck 1153c2c66affSColin Finck /* Set the cylinder data for the LSB */ 1154c2c66affSColin Finck PartitionDescriptor->StartingCylinderLsb = (UCHAR)StartingCylinder; 1155c2c66affSColin Finck PartitionDescriptor->EndingCylinderLsb = (UCHAR)EndingCylinder; 1156c2c66affSColin Finck } 1157c2c66affSColin Finck 1158c2c66affSColin Finck VOID 1159c2c66affSColin Finck FASTCALL 1160c2c66affSColin Finck xHalGetPartialGeometry(IN PDEVICE_OBJECT DeviceObject, 1161c2c66affSColin Finck IN PULONG ConventionalCylinders, 1162c2c66affSColin Finck IN PLONGLONG DiskSize) 1163c2c66affSColin Finck { 1164c2c66affSColin Finck PDISK_GEOMETRY DiskGeometry = NULL; 1165c2c66affSColin Finck PIO_STATUS_BLOCK IoStatusBlock = NULL; 1166c2c66affSColin Finck PKEVENT Event = NULL; 1167c2c66affSColin Finck PIRP Irp; 1168c2c66affSColin Finck NTSTATUS Status; 1169c2c66affSColin Finck 1170c2c66affSColin Finck /* Set defaults */ 1171c2c66affSColin Finck *ConventionalCylinders = 0; 1172c2c66affSColin Finck *DiskSize = 0; 1173c2c66affSColin Finck 1174c2c66affSColin Finck /* Allocate the structure in nonpaged pool */ 1175c2c66affSColin Finck DiskGeometry = ExAllocatePoolWithTag(NonPagedPool, 1176c2c66affSColin Finck sizeof(DISK_GEOMETRY), 1177c2c66affSColin Finck TAG_FILE_SYSTEM); 1178c2c66affSColin Finck if (!DiskGeometry) goto Cleanup; 1179c2c66affSColin Finck 1180c2c66affSColin Finck /* Allocate the status block in nonpaged pool */ 1181c2c66affSColin Finck IoStatusBlock = ExAllocatePoolWithTag(NonPagedPool, 1182c2c66affSColin Finck sizeof(IO_STATUS_BLOCK), 1183c2c66affSColin Finck TAG_FILE_SYSTEM); 1184c2c66affSColin Finck if (!IoStatusBlock) goto Cleanup; 1185c2c66affSColin Finck 1186c2c66affSColin Finck /* Allocate the event in nonpaged pool too */ 1187c2c66affSColin Finck Event = ExAllocatePoolWithTag(NonPagedPool, 1188c2c66affSColin Finck sizeof(KEVENT), 1189c2c66affSColin Finck TAG_FILE_SYSTEM); 1190c2c66affSColin Finck if (!Event) goto Cleanup; 1191c2c66affSColin Finck 1192c2c66affSColin Finck /* Initialize the event */ 1193c2c66affSColin Finck KeInitializeEvent(Event, NotificationEvent, FALSE); 1194c2c66affSColin Finck 1195c2c66affSColin Finck /* Build the IRP */ 1196c2c66affSColin Finck Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY, 1197c2c66affSColin Finck DeviceObject, 1198c2c66affSColin Finck NULL, 1199c2c66affSColin Finck 0, 1200c2c66affSColin Finck DiskGeometry, 1201c2c66affSColin Finck sizeof(DISK_GEOMETRY), 1202c2c66affSColin Finck FALSE, 1203c2c66affSColin Finck Event, 1204c2c66affSColin Finck IoStatusBlock); 1205c2c66affSColin Finck if (!Irp) goto Cleanup; 1206c2c66affSColin Finck 1207c2c66affSColin Finck /* Now call the driver */ 1208c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp); 1209c2c66affSColin Finck if (Status == STATUS_PENDING) 1210c2c66affSColin Finck { 1211c2c66affSColin Finck /* Wait for it to complete */ 1212c2c66affSColin Finck KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL); 1213c2c66affSColin Finck Status = IoStatusBlock->Status; 1214c2c66affSColin Finck } 1215c2c66affSColin Finck 1216c2c66affSColin Finck /* Check driver status */ 1217c2c66affSColin Finck if (NT_SUCCESS(Status)) 1218c2c66affSColin Finck { 1219c2c66affSColin Finck /* Return the cylinder count */ 1220c2c66affSColin Finck *ConventionalCylinders = DiskGeometry->Cylinders.LowPart; 1221c2c66affSColin Finck 1222c2c66affSColin Finck /* Make sure it's not larger then 1024 */ 1223c2c66affSColin Finck if (DiskGeometry->Cylinders.LowPart >= 1024) 1224c2c66affSColin Finck { 1225c2c66affSColin Finck /* Otherwise, normalize the value */ 1226c2c66affSColin Finck *ConventionalCylinders = 1024; 1227c2c66affSColin Finck } 1228c2c66affSColin Finck 1229c2c66affSColin Finck /* Calculate the disk size */ 1230c2c66affSColin Finck *DiskSize = DiskGeometry->Cylinders.QuadPart * 1231c2c66affSColin Finck DiskGeometry->TracksPerCylinder * 1232c2c66affSColin Finck DiskGeometry->SectorsPerTrack * 1233c2c66affSColin Finck DiskGeometry->BytesPerSector; 1234c2c66affSColin Finck } 1235c2c66affSColin Finck 1236c2c66affSColin Finck Cleanup: 1237c2c66affSColin Finck /* Free all the pointers */ 1238c2c66affSColin Finck if (Event) ExFreePoolWithTag(Event, TAG_FILE_SYSTEM); 1239c2c66affSColin Finck if (IoStatusBlock) ExFreePoolWithTag(IoStatusBlock, TAG_FILE_SYSTEM); 1240c2c66affSColin Finck if (DiskGeometry) ExFreePoolWithTag(DiskGeometry, TAG_FILE_SYSTEM); 1241c2c66affSColin Finck return; 1242c2c66affSColin Finck } 1243c2c66affSColin Finck 1244c2c66affSColin Finck VOID 1245c2c66affSColin Finck FASTCALL 1246c2c66affSColin Finck xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject, 1247c2c66affSColin Finck IN ULONG SectorSize, 1248c2c66affSColin Finck IN ULONG MbrTypeIdentifier, 1249c2c66affSColin Finck OUT PVOID *MbrBuffer) 1250c2c66affSColin Finck { 1251c2c66affSColin Finck LARGE_INTEGER Offset; 1252c2c66affSColin Finck PUCHAR Buffer; 1253c2c66affSColin Finck ULONG BufferSize; 1254c2c66affSColin Finck KEVENT Event; 1255c2c66affSColin Finck IO_STATUS_BLOCK IoStatusBlock; 1256c2c66affSColin Finck PIRP Irp; 1257c2c66affSColin Finck PPARTITION_DESCRIPTOR PartitionDescriptor; 1258c2c66affSColin Finck NTSTATUS Status; 1259c2c66affSColin Finck PIO_STACK_LOCATION IoStackLocation; 1260c2c66affSColin Finck Offset.QuadPart = 0; 1261c2c66affSColin Finck 1262c2c66affSColin Finck /* Assume failure */ 1263c2c66affSColin Finck *MbrBuffer = NULL; 1264c2c66affSColin Finck 1265c2c66affSColin Finck /* Normalize the buffer size */ 1266c2c66affSColin Finck BufferSize = max(SectorSize, 512); 1267c2c66affSColin Finck 1268c2c66affSColin Finck /* Allocate the buffer */ 1269c2c66affSColin Finck Buffer = ExAllocatePoolWithTag(NonPagedPool, 1270c2c66affSColin Finck PAGE_SIZE > BufferSize ? 1271c2c66affSColin Finck PAGE_SIZE : BufferSize, 1272c2c66affSColin Finck TAG_FILE_SYSTEM); 1273c2c66affSColin Finck if (!Buffer) return; 1274c2c66affSColin Finck 1275c2c66affSColin Finck /* Initialize the Event */ 1276c2c66affSColin Finck KeInitializeEvent(&Event, NotificationEvent, FALSE); 1277c2c66affSColin Finck 1278c2c66affSColin Finck /* Build the IRP */ 1279c2c66affSColin Finck Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, 1280c2c66affSColin Finck DeviceObject, 1281c2c66affSColin Finck Buffer, 1282c2c66affSColin Finck BufferSize, 1283c2c66affSColin Finck &Offset, 1284c2c66affSColin Finck &Event, 1285c2c66affSColin Finck &IoStatusBlock); 1286c2c66affSColin Finck if (!Irp) 1287c2c66affSColin Finck { 1288c2c66affSColin Finck /* Failed */ 1289c2c66affSColin Finck ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM); 1290c2c66affSColin Finck return; 1291c2c66affSColin Finck } 1292c2c66affSColin Finck 1293c2c66affSColin Finck /* Make sure to override volume verification */ 1294c2c66affSColin Finck IoStackLocation = IoGetNextIrpStackLocation(Irp); 1295c2c66affSColin Finck IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 1296c2c66affSColin Finck 1297c2c66affSColin Finck /* Call the driver */ 1298c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp); 1299c2c66affSColin Finck if (Status == STATUS_PENDING) 1300c2c66affSColin Finck { 1301c2c66affSColin Finck /* Wait for completion */ 1302c2c66affSColin Finck KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 1303c2c66affSColin Finck Status = IoStatusBlock.Status; 1304c2c66affSColin Finck } 1305c2c66affSColin Finck 1306c2c66affSColin Finck /* Check driver Status */ 1307c2c66affSColin Finck if (NT_SUCCESS(Status)) 1308c2c66affSColin Finck { 1309c2c66affSColin Finck /* Validate the MBR Signature */ 1310c2c66affSColin Finck if (((PUSHORT)Buffer)[BOOT_SIGNATURE_OFFSET] != BOOT_RECORD_SIGNATURE) 1311c2c66affSColin Finck { 1312c2c66affSColin Finck /* Failed */ 1313c2c66affSColin Finck ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM); 1314c2c66affSColin Finck return; 1315c2c66affSColin Finck } 1316c2c66affSColin Finck 1317c2c66affSColin Finck /* Get the partition entry */ 1318c2c66affSColin Finck PartitionDescriptor = (PPARTITION_DESCRIPTOR) 1319c2c66affSColin Finck &(((PUSHORT)Buffer)[PARTITION_TABLE_OFFSET]); 1320c2c66affSColin Finck 1321c2c66affSColin Finck /* Make sure it's what the caller wanted */ 1322c2c66affSColin Finck if (PartitionDescriptor->PartitionType != MbrTypeIdentifier) 1323c2c66affSColin Finck { 1324c2c66affSColin Finck /* It's not, free our buffer */ 1325c2c66affSColin Finck ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM); 1326c2c66affSColin Finck } 1327c2c66affSColin Finck else 1328c2c66affSColin Finck { 1329c2c66affSColin Finck /* Check if this is a secondary entry */ 1330c2c66affSColin Finck if (PartitionDescriptor->PartitionType == 0x54) 1331c2c66affSColin Finck { 1332c2c66affSColin Finck /* Return our buffer, but at sector 63 */ 1333c2c66affSColin Finck *(PULONG)Buffer = 63; 1334c2c66affSColin Finck *MbrBuffer = Buffer; 1335c2c66affSColin Finck } 1336c2c66affSColin Finck else if (PartitionDescriptor->PartitionType == 0x55) 1337c2c66affSColin Finck { 1338c2c66affSColin Finck /* EZ Drive, return the buffer directly */ 1339c2c66affSColin Finck *MbrBuffer = Buffer; 1340c2c66affSColin Finck } 1341c2c66affSColin Finck else 1342c2c66affSColin Finck { 1343c2c66affSColin Finck /* Otherwise crash on debug builds */ 1344c2c66affSColin Finck ASSERT(PartitionDescriptor->PartitionType == 0x55); 1345c2c66affSColin Finck } 1346c2c66affSColin Finck } 1347c2c66affSColin Finck } 1348c2c66affSColin Finck } 1349c2c66affSColin Finck 1350c2c66affSColin Finck VOID 1351c2c66affSColin Finck NTAPI 1352c2c66affSColin Finck FstubFixupEfiPartition(IN PPARTITION_DESCRIPTOR PartitionDescriptor, 1353c2c66affSColin Finck IN ULONGLONG MaxOffset) 1354c2c66affSColin Finck { 1355c2c66affSColin Finck ULONG PartitionMaxOffset, PartitionLength; 1356c2c66affSColin Finck PAGED_CODE(); 1357c2c66affSColin Finck 1358c2c66affSColin Finck /* Compute partition length (according to MBR entry) */ 1359c2c66affSColin Finck PartitionMaxOffset = GET_STARTING_SECTOR(PartitionDescriptor) + GET_PARTITION_LENGTH(PartitionDescriptor); 1360c2c66affSColin Finck /* In case the partition length goes beyond disk size... */ 1361c2c66affSColin Finck if (PartitionMaxOffset > MaxOffset) 1362c2c66affSColin Finck { 1363c2c66affSColin Finck /* Resize partition to its maximum real length */ 1364c2c66affSColin Finck PartitionLength = (ULONG)(PartitionMaxOffset - GET_STARTING_SECTOR(PartitionDescriptor)); 1365c2c66affSColin Finck SET_PARTITION_LENGTH(PartitionDescriptor, PartitionLength); 1366c2c66affSColin Finck } 1367c2c66affSColin Finck } 1368c2c66affSColin Finck 1369c2c66affSColin Finck NTSTATUS 1370c2c66affSColin Finck FASTCALL 1371c2c66affSColin Finck xHalIoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject, 1372c2c66affSColin Finck IN ULONG SectorSize, 1373c2c66affSColin Finck IN BOOLEAN ReturnRecognizedPartitions, 1374c2c66affSColin Finck IN OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer) 1375c2c66affSColin Finck { 1376c2c66affSColin Finck KEVENT Event; 1377c2c66affSColin Finck IO_STATUS_BLOCK IoStatusBlock; 1378c2c66affSColin Finck PIRP Irp; 1379c2c66affSColin Finck PPARTITION_DESCRIPTOR PartitionDescriptor; 1380c2c66affSColin Finck CCHAR Entry; 1381c2c66affSColin Finck NTSTATUS Status; 1382c2c66affSColin Finck PPARTITION_INFORMATION PartitionInfo; 1383c2c66affSColin Finck PUCHAR Buffer = NULL; 1384c2c66affSColin Finck ULONG BufferSize = 2048, InputSize; 1385c2c66affSColin Finck PDRIVE_LAYOUT_INFORMATION DriveLayoutInfo = NULL; 1386c2c66affSColin Finck LONG j = -1, i = -1, k; 1387c2c66affSColin Finck DISK_GEOMETRY DiskGeometry; 1388c2c66affSColin Finck LONGLONG EndSector, MaxSector, StartOffset; 1389c2c66affSColin Finck ULONGLONG MaxOffset; 1390c2c66affSColin Finck LARGE_INTEGER Offset, VolumeOffset; 1391c2c66affSColin Finck BOOLEAN IsPrimary = TRUE, IsEzDrive = FALSE, MbrFound = FALSE; 1392c2c66affSColin Finck BOOLEAN IsValid, IsEmpty = TRUE; 1393c2c66affSColin Finck PVOID MbrBuffer; 1394c2c66affSColin Finck PIO_STACK_LOCATION IoStackLocation; 1395c2c66affSColin Finck PBOOT_SECTOR_INFO BootSectorInfo = (PBOOT_SECTOR_INFO)Buffer; 1396c2c66affSColin Finck UCHAR PartitionType; 1397c2c66affSColin Finck LARGE_INTEGER HiddenSectors64; 1398c2c66affSColin Finck VolumeOffset.QuadPart = Offset.QuadPart = 0; 1399c2c66affSColin Finck PAGED_CODE(); 1400c2c66affSColin Finck 1401c2c66affSColin Finck /* Allocate the buffer */ 1402c2c66affSColin Finck *PartitionBuffer = ExAllocatePoolWithTag(NonPagedPool, 1403c2c66affSColin Finck BufferSize, 1404c2c66affSColin Finck TAG_FILE_SYSTEM); 1405c2c66affSColin Finck if (!(*PartitionBuffer)) return STATUS_INSUFFICIENT_RESOURCES; 1406c2c66affSColin Finck 1407c2c66affSColin Finck /* Normalize the buffer size */ 1408c2c66affSColin Finck InputSize = max(512, SectorSize); 1409c2c66affSColin Finck 1410c2c66affSColin Finck /* Check for EZ Drive */ 1411c2c66affSColin Finck HalExamineMBR(DeviceObject, InputSize, 0x55, &MbrBuffer); 1412c2c66affSColin Finck if (MbrBuffer) 1413c2c66affSColin Finck { 1414c2c66affSColin Finck /* EZ Drive found, bias the offset */ 1415c2c66affSColin Finck IsEzDrive = TRUE; 1416c2c66affSColin Finck ExFreePoolWithTag(MbrBuffer, TAG_FILE_SYSTEM); 1417c2c66affSColin Finck Offset.QuadPart = 512; 1418c2c66affSColin Finck } 1419c2c66affSColin Finck 1420c2c66affSColin Finck /* Get drive geometry */ 1421c2c66affSColin Finck Status = HalpGetFullGeometry(DeviceObject, &DiskGeometry, &MaxOffset); 1422c2c66affSColin Finck if (!NT_SUCCESS(Status)) 1423c2c66affSColin Finck { 1424c2c66affSColin Finck ExFreePoolWithTag(*PartitionBuffer, TAG_FILE_SYSTEM); 1425c2c66affSColin Finck *PartitionBuffer = NULL; 1426c2c66affSColin Finck return Status; 1427c2c66affSColin Finck } 1428c2c66affSColin Finck 1429c2c66affSColin Finck /* Get the end and maximum sector */ 1430c2c66affSColin Finck EndSector = MaxOffset; 1431c2c66affSColin Finck MaxSector = MaxOffset << 1; 1432c2c66affSColin Finck DPRINT("FSTUB: MaxOffset = %#I64x, MaxSector = %#I64x\n", 1433c2c66affSColin Finck MaxOffset, MaxSector); 1434c2c66affSColin Finck 1435c2c66affSColin Finck /* Allocate our buffer */ 1436c2c66affSColin Finck Buffer = ExAllocatePoolWithTag(NonPagedPool, InputSize, TAG_FILE_SYSTEM); 1437c2c66affSColin Finck if (!Buffer) 1438c2c66affSColin Finck { 1439c2c66affSColin Finck /* Fail, free the input buffer */ 1440c2c66affSColin Finck ExFreePoolWithTag(*PartitionBuffer, TAG_FILE_SYSTEM); 1441c2c66affSColin Finck *PartitionBuffer = NULL; 1442c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 1443c2c66affSColin Finck } 1444c2c66affSColin Finck 1445c2c66affSColin Finck /* Start partition loop */ 1446c2c66affSColin Finck do 1447c2c66affSColin Finck { 1448c2c66affSColin Finck /* Assume the partition is valid */ 1449c2c66affSColin Finck IsValid = TRUE; 1450c2c66affSColin Finck 1451c2c66affSColin Finck /* Initialize the event */ 1452c2c66affSColin Finck KeInitializeEvent(&Event, NotificationEvent, FALSE); 1453c2c66affSColin Finck 1454c2c66affSColin Finck /* Clear the buffer and build the IRP */ 1455c2c66affSColin Finck RtlZeroMemory(Buffer, InputSize); 1456c2c66affSColin Finck Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, 1457c2c66affSColin Finck DeviceObject, 1458c2c66affSColin Finck Buffer, 1459c2c66affSColin Finck InputSize, 1460c2c66affSColin Finck &Offset, 1461c2c66affSColin Finck &Event, 1462c2c66affSColin Finck &IoStatusBlock); 1463c2c66affSColin Finck if (!Irp) 1464c2c66affSColin Finck { 1465c2c66affSColin Finck /* Failed */ 1466c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES; 1467c2c66affSColin Finck break; 1468c2c66affSColin Finck } 1469c2c66affSColin Finck 1470c2c66affSColin Finck /* Make sure to disable volume verification */ 1471c2c66affSColin Finck IoStackLocation = IoGetNextIrpStackLocation(Irp); 1472c2c66affSColin Finck IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 1473c2c66affSColin Finck 1474c2c66affSColin Finck /* Call the driver */ 1475c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp); 1476c2c66affSColin Finck if (Status == STATUS_PENDING) 1477c2c66affSColin Finck { 1478c2c66affSColin Finck /* Wait for completion */ 1479c2c66affSColin Finck KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 1480c2c66affSColin Finck Status = IoStatusBlock.Status; 1481c2c66affSColin Finck } 1482c2c66affSColin Finck 1483c2c66affSColin Finck /* Normalize status code and check for failure */ 1484c2c66affSColin Finck if (Status == STATUS_NO_DATA_DETECTED) Status = STATUS_SUCCESS; 1485c2c66affSColin Finck if (!NT_SUCCESS(Status)) break; 1486c2c66affSColin Finck 1487c2c66affSColin Finck /* If we biased for EZ-Drive, unbias now */ 1488c2c66affSColin Finck if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0; 1489c2c66affSColin Finck 1490c2c66affSColin Finck /* Make sure this is a valid MBR */ 1491c2c66affSColin Finck if (((PUSHORT)Buffer)[BOOT_SIGNATURE_OFFSET] != BOOT_RECORD_SIGNATURE) 1492c2c66affSColin Finck { 1493c2c66affSColin Finck /* It's not, fail */ 1494c2c66affSColin Finck DPRINT1("FSTUB: (IoReadPartitionTable) No 0xaa55 found in " 1495c2c66affSColin Finck "partition table %d\n", j + 1); 1496c2c66affSColin Finck break; 1497c2c66affSColin Finck } 1498c2c66affSColin Finck 1499c2c66affSColin Finck /* At this point we have a valid MBR */ 1500c2c66affSColin Finck MbrFound = TRUE; 1501c2c66affSColin Finck 1502c2c66affSColin Finck /* Check if we weren't given an offset */ 1503c2c66affSColin Finck if (!Offset.QuadPart) 1504c2c66affSColin Finck { 1505c2c66affSColin Finck /* Then read the signature off the disk */ 1506c2c66affSColin Finck (*PartitionBuffer)->Signature = ((PULONG)Buffer) 1507c2c66affSColin Finck [PARTITION_TABLE_OFFSET / 2 - 1]; 1508c2c66affSColin Finck } 1509c2c66affSColin Finck 1510c2c66affSColin Finck /* Get the partition descriptor array */ 1511c2c66affSColin Finck PartitionDescriptor = (PPARTITION_DESCRIPTOR) 1512c2c66affSColin Finck &(((PUSHORT)Buffer)[PARTITION_TABLE_OFFSET]); 1513c2c66affSColin Finck 1514c2c66affSColin Finck /* Start looping partitions */ 1515c2c66affSColin Finck j++; 1516c2c66affSColin Finck DPRINT("FSTUB: Partition Table %d:\n", j); 1517c2c66affSColin Finck for (Entry = 1, k = 0; Entry <= 4; Entry++, PartitionDescriptor++) 1518c2c66affSColin Finck { 1519c2c66affSColin Finck /* Get the partition type */ 1520c2c66affSColin Finck PartitionType = PartitionDescriptor->PartitionType; 1521c2c66affSColin Finck 1522c2c66affSColin Finck /* Print debug messages */ 1523c2c66affSColin Finck DPRINT("Partition Entry %d,%d: type %#x %s\n", 1524c2c66affSColin Finck j, 1525c2c66affSColin Finck Entry, 1526c2c66affSColin Finck PartitionType, 1527c2c66affSColin Finck (PartitionDescriptor->ActiveFlag) ? "Active" : ""); 1528c2c66affSColin Finck DPRINT("\tOffset %#08lx for %#08lx Sectors\n", 1529c2c66affSColin Finck GET_STARTING_SECTOR(PartitionDescriptor), 1530c2c66affSColin Finck GET_PARTITION_LENGTH(PartitionDescriptor)); 1531c2c66affSColin Finck 1532c2c66affSColin Finck /* Check whether we're facing a protective MBR */ 1533c2c66affSColin Finck if (PartitionType == EFI_PMBR_OSTYPE_EFI) 1534c2c66affSColin Finck { 1535c2c66affSColin Finck /* Partition length might be bigger than disk size */ 1536c2c66affSColin Finck FstubFixupEfiPartition(PartitionDescriptor, 1537c2c66affSColin Finck MaxOffset); 1538c2c66affSColin Finck } 1539c2c66affSColin Finck 1540c2c66affSColin Finck /* Make sure that the partition is valid, unless it's the first */ 1541c2c66affSColin Finck if (!(HalpIsValidPartitionEntry(PartitionDescriptor, 1542c2c66affSColin Finck MaxOffset, 1543c2c66affSColin Finck MaxSector)) && !(j)) 1544c2c66affSColin Finck { 1545c2c66affSColin Finck /* It's invalid, so fail */ 1546c2c66affSColin Finck IsValid = FALSE; 1547c2c66affSColin Finck break; 1548c2c66affSColin Finck } 1549c2c66affSColin Finck 1550c2c66affSColin Finck /* Check if it's a container */ 1551c2c66affSColin Finck if (IsContainerPartition(PartitionType)) 1552c2c66affSColin Finck { 1553c2c66affSColin Finck /* Increase the count of containers */ 1554c2c66affSColin Finck if (++k != 1) 1555c2c66affSColin Finck { 1556c2c66affSColin Finck /* More then one table is invalid */ 1557c2c66affSColin Finck DPRINT1("FSTUB: Multiple container partitions found in " 1558c2c66affSColin Finck "partition table %d\n - table is invalid\n", 1559c2c66affSColin Finck j); 1560c2c66affSColin Finck IsValid = FALSE; 1561c2c66affSColin Finck break; 1562c2c66affSColin Finck } 1563c2c66affSColin Finck } 1564c2c66affSColin Finck 1565c2c66affSColin Finck /* Check if the partition is supposedly empty */ 1566c2c66affSColin Finck if (IsEmpty) 1567c2c66affSColin Finck { 1568c2c66affSColin Finck /* But check if it actually has a start and/or length */ 1569c2c66affSColin Finck if ((GET_STARTING_SECTOR(PartitionDescriptor)) || 1570c2c66affSColin Finck (GET_PARTITION_LENGTH(PartitionDescriptor))) 1571c2c66affSColin Finck { 1572c2c66affSColin Finck /* So then it's not really empty */ 1573c2c66affSColin Finck IsEmpty = FALSE; 1574c2c66affSColin Finck } 1575c2c66affSColin Finck } 1576c2c66affSColin Finck 1577c2c66affSColin Finck /* Check if the caller wanted only recognized partitions */ 1578c2c66affSColin Finck if (ReturnRecognizedPartitions) 1579c2c66affSColin Finck { 1580c2c66affSColin Finck /* Then check if this one is unused, or a container */ 1581c2c66affSColin Finck if ((PartitionType == PARTITION_ENTRY_UNUSED) || 1582c2c66affSColin Finck IsContainerPartition(PartitionType)) 1583c2c66affSColin Finck { 1584c2c66affSColin Finck /* Skip it, since the caller doesn't want it */ 1585c2c66affSColin Finck continue; 1586c2c66affSColin Finck } 1587c2c66affSColin Finck } 1588c2c66affSColin Finck 1589c2c66affSColin Finck /* Increase the structure count and check if they can fit */ 1590c2c66affSColin Finck if ((sizeof(DRIVE_LAYOUT_INFORMATION) + 1591c2c66affSColin Finck (++i * sizeof(PARTITION_INFORMATION))) > 1592c2c66affSColin Finck BufferSize) 1593c2c66affSColin Finck { 1594c2c66affSColin Finck /* Allocate a new buffer that's twice as big */ 1595c2c66affSColin Finck DriveLayoutInfo = ExAllocatePoolWithTag(NonPagedPool, 1596c2c66affSColin Finck BufferSize << 1, 1597c2c66affSColin Finck TAG_FILE_SYSTEM); 1598c2c66affSColin Finck if (!DriveLayoutInfo) 1599c2c66affSColin Finck { 1600c2c66affSColin Finck /* Out of memory, unto this extra structure */ 1601c2c66affSColin Finck --i; 1602c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES; 1603c2c66affSColin Finck break; 1604c2c66affSColin Finck } 1605c2c66affSColin Finck 1606c2c66affSColin Finck /* Copy the contents of the old buffer */ 1607c2c66affSColin Finck RtlMoveMemory(DriveLayoutInfo, 1608c2c66affSColin Finck *PartitionBuffer, 1609c2c66affSColin Finck BufferSize); 1610c2c66affSColin Finck 1611c2c66affSColin Finck /* Free the old buffer and set this one as the new one */ 1612c2c66affSColin Finck ExFreePoolWithTag(*PartitionBuffer, TAG_FILE_SYSTEM); 1613c2c66affSColin Finck *PartitionBuffer = DriveLayoutInfo; 1614c2c66affSColin Finck 1615c2c66affSColin Finck /* Double the size */ 1616c2c66affSColin Finck BufferSize <<= 1; 1617c2c66affSColin Finck } 1618c2c66affSColin Finck 1619c2c66affSColin Finck /* Now get the current structure being filled and initialize it */ 1620c2c66affSColin Finck PartitionInfo = &(*PartitionBuffer)->PartitionEntry[i]; 1621c2c66affSColin Finck PartitionInfo->PartitionType = PartitionType; 1622c2c66affSColin Finck PartitionInfo->RewritePartition = FALSE; 1623c2c66affSColin Finck 1624c2c66affSColin Finck /* Check if we're dealing with a partition that's in use */ 1625c2c66affSColin Finck if (PartitionType != PARTITION_ENTRY_UNUSED) 1626c2c66affSColin Finck { 1627c2c66affSColin Finck /* Check if it's bootable */ 1628c2c66affSColin Finck PartitionInfo->BootIndicator = PartitionDescriptor-> 1629c2c66affSColin Finck ActiveFlag & 0x80 ? 1630c2c66affSColin Finck TRUE : FALSE; 1631c2c66affSColin Finck 1632c2c66affSColin Finck /* Check if its' a container */ 1633c2c66affSColin Finck if (IsContainerPartition(PartitionType)) 1634c2c66affSColin Finck { 1635c2c66affSColin Finck /* Then don't recognize it and use the volume offset */ 1636c2c66affSColin Finck PartitionInfo->RecognizedPartition = FALSE; 1637c2c66affSColin Finck StartOffset = VolumeOffset.QuadPart; 1638c2c66affSColin Finck } 1639c2c66affSColin Finck else 1640c2c66affSColin Finck { 1641c2c66affSColin Finck /* Then recognize it and use the partition offset */ 1642c2c66affSColin Finck PartitionInfo->RecognizedPartition = TRUE; 1643c2c66affSColin Finck StartOffset = Offset.QuadPart; 1644c2c66affSColin Finck } 1645c2c66affSColin Finck 1646c2c66affSColin Finck /* Get the starting offset */ 1647c2c66affSColin Finck PartitionInfo->StartingOffset.QuadPart = 1648c2c66affSColin Finck StartOffset + 1649c2c66affSColin Finck UInt32x32To64(GET_STARTING_SECTOR(PartitionDescriptor), 1650c2c66affSColin Finck SectorSize); 1651c2c66affSColin Finck 1652c2c66affSColin Finck /* Calculate the number of hidden sectors */ 1653c2c66affSColin Finck HiddenSectors64.QuadPart = (PartitionInfo-> 1654c2c66affSColin Finck StartingOffset.QuadPart - 1655c2c66affSColin Finck StartOffset) / 1656c2c66affSColin Finck SectorSize; 1657c2c66affSColin Finck PartitionInfo->HiddenSectors = HiddenSectors64.LowPart; 1658c2c66affSColin Finck 1659c2c66affSColin Finck /* Get the partition length */ 1660c2c66affSColin Finck PartitionInfo->PartitionLength.QuadPart = 1661c2c66affSColin Finck UInt32x32To64(GET_PARTITION_LENGTH(PartitionDescriptor), 1662c2c66affSColin Finck SectorSize); 1663c2c66affSColin Finck 1664c2c66affSColin Finck /* Get the partition number */ 1665c2c66affSColin Finck PartitionInfo->PartitionNumber = (!IsContainerPartition(PartitionType)) ? i + 1 : 0; 1666c2c66affSColin Finck } 1667c2c66affSColin Finck else 1668c2c66affSColin Finck { 1669c2c66affSColin Finck /* Otherwise, clear all the relevant fields */ 1670c2c66affSColin Finck PartitionInfo->BootIndicator = FALSE; 1671c2c66affSColin Finck PartitionInfo->RecognizedPartition = FALSE; 1672c2c66affSColin Finck PartitionInfo->StartingOffset.QuadPart = 0; 1673c2c66affSColin Finck PartitionInfo->PartitionLength.QuadPart = 0; 1674c2c66affSColin Finck PartitionInfo->HiddenSectors = 0; 1675c2c66affSColin Finck 1676c2c66affSColin Finck PartitionInfo->PartitionNumber = 0; 1677c2c66affSColin Finck } 1678c2c66affSColin Finck } 1679c2c66affSColin Finck 1680c2c66affSColin Finck /* Finish debug log, and check for failure */ 1681c2c66affSColin Finck DPRINT("\n"); 1682c2c66affSColin Finck if (!NT_SUCCESS(Status)) break; 1683c2c66affSColin Finck 1684c2c66affSColin Finck /* Also check if we hit an invalid entry here */ 1685c2c66affSColin Finck if (!IsValid) 1686c2c66affSColin Finck { 1687c2c66affSColin Finck /* We did, so break out of the loop minus one entry */ 1688c2c66affSColin Finck j--; 1689c2c66affSColin Finck break; 1690c2c66affSColin Finck } 1691c2c66affSColin Finck 1692c2c66affSColin Finck /* Reset the offset */ 1693c2c66affSColin Finck Offset.QuadPart = 0; 1694c2c66affSColin Finck 1695c2c66affSColin Finck /* Go back to the descriptor array and loop it */ 1696c2c66affSColin Finck PartitionDescriptor = (PPARTITION_DESCRIPTOR) 1697c2c66affSColin Finck &(((PUSHORT)Buffer)[PARTITION_TABLE_OFFSET]); 1698c2c66affSColin Finck for (Entry = 1; Entry <= 4; Entry++, PartitionDescriptor++) 1699c2c66affSColin Finck { 1700c2c66affSColin Finck /* Check if this is a container partition, since we skipped them */ 1701c2c66affSColin Finck if (IsContainerPartition(PartitionDescriptor->PartitionType)) 1702c2c66affSColin Finck { 1703c2c66affSColin Finck /* Get its offset */ 1704c2c66affSColin Finck Offset.QuadPart = VolumeOffset.QuadPart + 1705c2c66affSColin Finck UInt32x32To64( 1706c2c66affSColin Finck GET_STARTING_SECTOR(PartitionDescriptor), 1707c2c66affSColin Finck SectorSize); 1708c2c66affSColin Finck 1709c2c66affSColin Finck /* If this is a primary partition, this is the volume offset */ 1710c2c66affSColin Finck if (IsPrimary) VolumeOffset = Offset; 1711c2c66affSColin Finck 1712c2c66affSColin Finck /* Also update the maximum sector */ 1713c2c66affSColin Finck MaxSector = GET_PARTITION_LENGTH(PartitionDescriptor); 1714c2c66affSColin Finck DPRINT1("FSTUB: MaxSector now = %I64d\n", MaxSector); 1715c2c66affSColin Finck break; 1716c2c66affSColin Finck } 1717c2c66affSColin Finck } 1718c2c66affSColin Finck 1719c2c66affSColin Finck /* Loop the next partitions, which are not primary anymore */ 1720c2c66affSColin Finck IsPrimary = FALSE; 1721c2c66affSColin Finck } while (Offset.HighPart | Offset.LowPart); 1722c2c66affSColin Finck 1723c2c66affSColin Finck /* Check if this is a removable device that's probably a super-floppy */ 1724c2c66affSColin Finck if ((DiskGeometry.MediaType == RemovableMedia) && 1725c2c66affSColin Finck !(j) && 1726c2c66affSColin Finck (MbrFound) && 1727c2c66affSColin Finck (IsEmpty)) 1728c2c66affSColin Finck { 1729c2c66affSColin Finck /* Read the jump bytes to detect super-floppy */ 1730c2c66affSColin Finck if ((BootSectorInfo->JumpByte[0] == 0xeb) || 1731c2c66affSColin Finck (BootSectorInfo->JumpByte[0] == 0xe9)) 1732c2c66affSColin Finck { 1733c2c66affSColin Finck /* Super floppes don't have typical MBRs, so skip them */ 1734c2c66affSColin Finck DPRINT1("FSTUB: Jump byte %#x found along with empty partition " 1735c2c66affSColin Finck "table - disk is a super floppy and has no valid MBR\n", 1736c2c66affSColin Finck BootSectorInfo->JumpByte); 1737c2c66affSColin Finck j = -1; 1738c2c66affSColin Finck } 1739c2c66affSColin Finck } 1740c2c66affSColin Finck 1741c2c66affSColin Finck /* Check if we're still at partition -1 */ 1742c2c66affSColin Finck if (j == -1) 1743c2c66affSColin Finck { 1744c2c66affSColin Finck /* The likely cause is the super floppy detection above */ 1745c2c66affSColin Finck if ((MbrFound) || (DiskGeometry.MediaType == RemovableMedia)) 1746c2c66affSColin Finck { 1747c2c66affSColin Finck /* Print out debugging information */ 1748c2c66affSColin Finck DPRINT1("FSTUB: Drive %#p has no valid MBR. Make it into a " 1749c2c66affSColin Finck "super-floppy\n", 1750c2c66affSColin Finck DeviceObject); 1751c2c66affSColin Finck DPRINT1("FSTUB: Drive has %I64d sectors and is %#016I64x " 1752c2c66affSColin Finck "bytes large\n", 1753c2c66affSColin Finck EndSector, EndSector * DiskGeometry.BytesPerSector); 1754c2c66affSColin Finck 1755c2c66affSColin Finck /* We should at least have some sectors */ 1756c2c66affSColin Finck if (EndSector > 0) 1757c2c66affSColin Finck { 1758c2c66affSColin Finck /* Get the entry we'll use */ 1759c2c66affSColin Finck PartitionInfo = &(*PartitionBuffer)->PartitionEntry[0]; 1760c2c66affSColin Finck 1761c2c66affSColin Finck /* Fill it out with data for a super-floppy */ 1762c2c66affSColin Finck PartitionInfo->RewritePartition = FALSE; 1763c2c66affSColin Finck PartitionInfo->RecognizedPartition = TRUE; 1764c2c66affSColin Finck PartitionInfo->PartitionType = PARTITION_FAT_16; 1765c2c66affSColin Finck PartitionInfo->BootIndicator = FALSE; 1766c2c66affSColin Finck PartitionInfo->HiddenSectors = 0; 1767c2c66affSColin Finck PartitionInfo->StartingOffset.QuadPart = 0; 1768c2c66affSColin Finck PartitionInfo->PartitionLength.QuadPart = (EndSector * 1769c2c66affSColin Finck DiskGeometry. 1770c2c66affSColin Finck BytesPerSector); 1771c2c66affSColin Finck 1772c2c66affSColin Finck /* FIXME: REACTOS HACK */ 1773c2c66affSColin Finck PartitionInfo->PartitionNumber = 0; 1774c2c66affSColin Finck 1775c2c66affSColin Finck /* Set the signature and set the count back to 0 */ 1776c2c66affSColin Finck (*PartitionBuffer)->Signature = 1; 1777c2c66affSColin Finck i = 0; 1778c2c66affSColin Finck } 1779c2c66affSColin Finck } 1780c2c66affSColin Finck else 1781c2c66affSColin Finck { 1782c2c66affSColin Finck /* Otherwise, this isn't a super floppy, so set an invalid count */ 1783c2c66affSColin Finck i = -1; 1784c2c66affSColin Finck } 1785c2c66affSColin Finck } 1786c2c66affSColin Finck 1787c2c66affSColin Finck /* Set the partition count */ 1788c2c66affSColin Finck (*PartitionBuffer)->PartitionCount = ++i; 1789c2c66affSColin Finck 1790c2c66affSColin Finck /* If we have no count, delete the signature */ 1791c2c66affSColin Finck if (!i) (*PartitionBuffer)->Signature = 0; 1792c2c66affSColin Finck 1793c2c66affSColin Finck /* Free the buffer and check for success */ 1794c2c66affSColin Finck if (Buffer) ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM); 1795c2c66affSColin Finck if (!NT_SUCCESS(Status)) 1796c2c66affSColin Finck { 1797c2c66affSColin Finck ExFreePoolWithTag(*PartitionBuffer, TAG_FILE_SYSTEM); 1798c2c66affSColin Finck *PartitionBuffer = NULL; 1799c2c66affSColin Finck } 1800c2c66affSColin Finck 1801c2c66affSColin Finck /* Return status */ 1802c2c66affSColin Finck return Status; 1803c2c66affSColin Finck } 1804c2c66affSColin Finck 1805c2c66affSColin Finck NTSTATUS 1806c2c66affSColin Finck FASTCALL 1807c2c66affSColin Finck xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject, 1808c2c66affSColin Finck IN ULONG SectorSize, 1809c2c66affSColin Finck IN ULONG PartitionNumber, 1810c2c66affSColin Finck IN ULONG PartitionType) 1811c2c66affSColin Finck { 1812c2c66affSColin Finck PIRP Irp; 1813c2c66affSColin Finck KEVENT Event; 1814c2c66affSColin Finck IO_STATUS_BLOCK IoStatusBlock; 1815c2c66affSColin Finck NTSTATUS Status; 1816c2c66affSColin Finck LARGE_INTEGER Offset, VolumeOffset; 1817c2c66affSColin Finck PUCHAR Buffer = NULL; 1818c2c66affSColin Finck ULONG BufferSize; 1819c2c66affSColin Finck ULONG i = 0; 1820c2c66affSColin Finck ULONG Entry; 1821c2c66affSColin Finck PPARTITION_DESCRIPTOR PartitionDescriptor; 1822c2c66affSColin Finck BOOLEAN IsPrimary = TRUE, IsEzDrive = FALSE; 1823c2c66affSColin Finck PVOID MbrBuffer; 1824c2c66affSColin Finck PIO_STACK_LOCATION IoStackLocation; 1825c2c66affSColin Finck VolumeOffset.QuadPart = Offset.QuadPart = 0; 1826c2c66affSColin Finck PAGED_CODE(); 1827c2c66affSColin Finck 1828c2c66affSColin Finck /* Normalize the buffer size */ 1829c2c66affSColin Finck BufferSize = max(512, SectorSize); 1830c2c66affSColin Finck 1831c2c66affSColin Finck /* Check for EZ Drive */ 1832c2c66affSColin Finck HalExamineMBR(DeviceObject, BufferSize, 0x55, &MbrBuffer); 1833c2c66affSColin Finck if (MbrBuffer) 1834c2c66affSColin Finck { 1835c2c66affSColin Finck /* EZ Drive found, bias the offset */ 1836c2c66affSColin Finck IsEzDrive = TRUE; 1837c2c66affSColin Finck ExFreePoolWithTag(MbrBuffer, TAG_FILE_SYSTEM); 1838c2c66affSColin Finck Offset.QuadPart = 512; 1839c2c66affSColin Finck } 1840c2c66affSColin Finck 1841c2c66affSColin Finck /* Allocate our partition buffer */ 1842c2c66affSColin Finck Buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, TAG_FILE_SYSTEM); 1843c2c66affSColin Finck if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES; 1844c2c66affSColin Finck 1845c2c66affSColin Finck /* Initialize the event we'll use and loop partitions */ 1846c2c66affSColin Finck KeInitializeEvent(&Event, NotificationEvent, FALSE); 1847c2c66affSColin Finck do 1848c2c66affSColin Finck { 1849c2c66affSColin Finck /* Reset the event since we reuse it */ 1850*75850abcSThomas Faber KeClearEvent(&Event); 1851c2c66affSColin Finck 1852c2c66affSColin Finck /* Build the read IRP */ 1853c2c66affSColin Finck Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, 1854c2c66affSColin Finck DeviceObject, 1855c2c66affSColin Finck Buffer, 1856c2c66affSColin Finck BufferSize, 1857c2c66affSColin Finck &Offset, 1858c2c66affSColin Finck &Event, 1859c2c66affSColin Finck &IoStatusBlock); 1860c2c66affSColin Finck if (!Irp) 1861c2c66affSColin Finck { 1862c2c66affSColin Finck /* Fail */ 1863c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES; 1864c2c66affSColin Finck break; 1865c2c66affSColin Finck } 1866c2c66affSColin Finck 1867c2c66affSColin Finck /* Make sure to disable volume verification */ 1868c2c66affSColin Finck IoStackLocation = IoGetNextIrpStackLocation(Irp); 1869c2c66affSColin Finck IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 1870c2c66affSColin Finck 1871c2c66affSColin Finck /* Call the driver */ 1872c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp); 1873c2c66affSColin Finck if (Status == STATUS_PENDING) 1874c2c66affSColin Finck { 1875c2c66affSColin Finck /* Wait for completion */ 1876c2c66affSColin Finck KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 1877c2c66affSColin Finck Status = IoStatusBlock.Status; 1878c2c66affSColin Finck } 1879c2c66affSColin Finck 1880c2c66affSColin Finck /* Check for failure */ 1881c2c66affSColin Finck if (!NT_SUCCESS(Status)) break; 1882c2c66affSColin Finck 1883c2c66affSColin Finck /* If we biased for EZ-Drive, unbias now */ 1884c2c66affSColin Finck if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0; 1885c2c66affSColin Finck 1886c2c66affSColin Finck /* Make sure this is a valid MBR */ 1887c2c66affSColin Finck if (((PUSHORT)Buffer)[BOOT_SIGNATURE_OFFSET] != BOOT_RECORD_SIGNATURE) 1888c2c66affSColin Finck { 1889c2c66affSColin Finck /* It's not, fail */ 1890c2c66affSColin Finck Status = STATUS_BAD_MASTER_BOOT_RECORD; 1891c2c66affSColin Finck break; 1892c2c66affSColin Finck } 1893c2c66affSColin Finck 1894c2c66affSColin Finck /* Get the partition descriptors and loop them */ 1895c2c66affSColin Finck PartitionDescriptor = (PPARTITION_DESCRIPTOR) 1896c2c66affSColin Finck &(((PUSHORT)Buffer)[PARTITION_TABLE_OFFSET]); 1897c2c66affSColin Finck for (Entry = 1; Entry <= 4; Entry++, PartitionDescriptor++) 1898c2c66affSColin Finck { 1899c2c66affSColin Finck /* Check if it's unused or a container partition */ 1900c2c66affSColin Finck if ((PartitionDescriptor->PartitionType == 1901c2c66affSColin Finck PARTITION_ENTRY_UNUSED) || 1902c2c66affSColin Finck (IsContainerPartition(PartitionDescriptor->PartitionType))) 1903c2c66affSColin Finck { 1904c2c66affSColin Finck /* Go to the next one */ 1905c2c66affSColin Finck continue; 1906c2c66affSColin Finck } 1907c2c66affSColin Finck 1908c2c66affSColin Finck /* It's a valid partition, so increase the partition count */ 1909c2c66affSColin Finck if (++i == PartitionNumber) 1910c2c66affSColin Finck { 1911c2c66affSColin Finck /* We found a match, set the type */ 1912c2c66affSColin Finck PartitionDescriptor->PartitionType = (UCHAR)PartitionType; 1913c2c66affSColin Finck 1914c2c66affSColin Finck /* Reset the reusable event */ 1915*75850abcSThomas Faber KeClearEvent(&Event); 1916c2c66affSColin Finck 1917c2c66affSColin Finck /* Build the write IRP */ 1918c2c66affSColin Finck Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE, 1919c2c66affSColin Finck DeviceObject, 1920c2c66affSColin Finck Buffer, 1921c2c66affSColin Finck BufferSize, 1922c2c66affSColin Finck &Offset, 1923c2c66affSColin Finck &Event, 1924c2c66affSColin Finck &IoStatusBlock); 1925c2c66affSColin Finck if (!Irp) 1926c2c66affSColin Finck { 1927c2c66affSColin Finck /* Fail */ 1928c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES; 1929c2c66affSColin Finck break; 1930c2c66affSColin Finck } 1931c2c66affSColin Finck 1932c2c66affSColin Finck /* Disable volume verification */ 1933c2c66affSColin Finck IoStackLocation = IoGetNextIrpStackLocation(Irp); 1934c2c66affSColin Finck IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 1935c2c66affSColin Finck 1936c2c66affSColin Finck /* Call the driver */ 1937c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp); 1938c2c66affSColin Finck if (Status == STATUS_PENDING) 1939c2c66affSColin Finck { 1940c2c66affSColin Finck /* Wait for completion */ 1941c2c66affSColin Finck KeWaitForSingleObject(&Event, 1942c2c66affSColin Finck Executive, 1943c2c66affSColin Finck KernelMode, 1944c2c66affSColin Finck FALSE, 1945c2c66affSColin Finck NULL); 1946c2c66affSColin Finck Status = IoStatusBlock.Status; 1947c2c66affSColin Finck } 1948c2c66affSColin Finck 1949c2c66affSColin Finck /* We're done, break out of the loop */ 1950c2c66affSColin Finck break; 1951c2c66affSColin Finck } 1952c2c66affSColin Finck } 1953c2c66affSColin Finck 1954c2c66affSColin Finck /* If we looped all the partitions, break out */ 1955c2c66affSColin Finck if (Entry <= NUM_PARTITION_TABLE_ENTRIES) break; 1956c2c66affSColin Finck 1957c2c66affSColin Finck /* Nothing found yet, get the partition array again */ 1958c2c66affSColin Finck PartitionDescriptor = (PPARTITION_DESCRIPTOR) 1959c2c66affSColin Finck &(((PUSHORT)Buffer)[PARTITION_TABLE_OFFSET]); 1960c2c66affSColin Finck for (Entry = 1; Entry <= 4; Entry++, PartitionDescriptor++) 1961c2c66affSColin Finck { 1962c2c66affSColin Finck /* Check if this was a container partition (we skipped these) */ 1963c2c66affSColin Finck if (IsContainerPartition(PartitionDescriptor->PartitionType)) 1964c2c66affSColin Finck { 1965c2c66affSColin Finck /* Update the partition offset */ 1966c2c66affSColin Finck Offset.QuadPart = VolumeOffset.QuadPart + 1967c2c66affSColin Finck GET_STARTING_SECTOR(PartitionDescriptor) * 1968c2c66affSColin Finck SectorSize; 1969c2c66affSColin Finck 1970c2c66affSColin Finck /* If this was the primary partition, update the volume too */ 1971c2c66affSColin Finck if (IsPrimary) VolumeOffset = Offset; 1972c2c66affSColin Finck break; 1973c2c66affSColin Finck } 1974c2c66affSColin Finck } 1975c2c66affSColin Finck 1976c2c66affSColin Finck /* Check if we already searched all the partitions */ 1977c2c66affSColin Finck if (Entry > NUM_PARTITION_TABLE_ENTRIES) 1978c2c66affSColin Finck { 1979c2c66affSColin Finck /* Then we failed to find a good MBR */ 1980c2c66affSColin Finck Status = STATUS_BAD_MASTER_BOOT_RECORD; 1981c2c66affSColin Finck break; 1982c2c66affSColin Finck } 1983c2c66affSColin Finck 1984c2c66affSColin Finck /* Loop the next partitions, which are not primary anymore */ 1985c2c66affSColin Finck IsPrimary = FALSE; 1986c2c66affSColin Finck } while (i < PartitionNumber); 1987c2c66affSColin Finck 1988c2c66affSColin Finck /* Everything done, cleanup */ 1989c2c66affSColin Finck if (Buffer) ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM); 1990c2c66affSColin Finck return Status; 1991c2c66affSColin Finck } 1992c2c66affSColin Finck 1993c2c66affSColin Finck NTSTATUS 1994c2c66affSColin Finck FASTCALL 1995c2c66affSColin Finck xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject, 1996c2c66affSColin Finck IN ULONG SectorSize, 1997c2c66affSColin Finck IN ULONG SectorsPerTrack, 1998c2c66affSColin Finck IN ULONG NumberOfHeads, 1999c2c66affSColin Finck IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer) 2000c2c66affSColin Finck { 2001c2c66affSColin Finck KEVENT Event; 2002c2c66affSColin Finck IO_STATUS_BLOCK IoStatusBlock; 2003c2c66affSColin Finck PIRP Irp; 2004c2c66affSColin Finck NTSTATUS Status = STATUS_SUCCESS; 2005c2c66affSColin Finck ULONG BufferSize; 2006c2c66affSColin Finck PUSHORT Buffer; 2007c2c66affSColin Finck PPTE Entry; 2008c2c66affSColin Finck PPARTITION_TABLE PartitionTable; 2009c2c66affSColin Finck LARGE_INTEGER Offset, NextOffset, ExtendedOffset, SectorOffset; 2010c2c66affSColin Finck LARGE_INTEGER StartOffset, PartitionLength; 2011c2c66affSColin Finck ULONG i, j; 2012c2c66affSColin Finck CCHAR k; 2013c2c66affSColin Finck BOOLEAN IsEzDrive = FALSE, IsSuperFloppy = FALSE, DoRewrite = FALSE, IsMbr; 2014c2c66affSColin Finck ULONG ConventionalCylinders; 2015c2c66affSColin Finck LONGLONG DiskSize; 2016c2c66affSColin Finck PDISK_LAYOUT DiskLayout = (PDISK_LAYOUT)PartitionBuffer; 2017c2c66affSColin Finck PVOID MbrBuffer; 2018c2c66affSColin Finck UCHAR PartitionType; 2019c2c66affSColin Finck PIO_STACK_LOCATION IoStackLocation; 2020c2c66affSColin Finck PPARTITION_INFORMATION PartitionInfo = PartitionBuffer->PartitionEntry; 2021c2c66affSColin Finck PPARTITION_INFORMATION TableEntry; 2022c2c66affSColin Finck ExtendedOffset.QuadPart = NextOffset.QuadPart = Offset.QuadPart = 0; 2023c2c66affSColin Finck PAGED_CODE(); 2024c2c66affSColin Finck 2025c2c66affSColin Finck /* Normalize the buffer size */ 2026c2c66affSColin Finck BufferSize = max(512, SectorSize); 2027c2c66affSColin Finck 2028c2c66affSColin Finck /* Get the partial drive geometry */ 2029c2c66affSColin Finck xHalGetPartialGeometry(DeviceObject, &ConventionalCylinders, &DiskSize); 2030c2c66affSColin Finck 2031c2c66affSColin Finck /* Check for EZ Drive */ 2032c2c66affSColin Finck HalExamineMBR(DeviceObject, BufferSize, 0x55, &MbrBuffer); 2033c2c66affSColin Finck if (MbrBuffer) 2034c2c66affSColin Finck { 2035c2c66affSColin Finck /* EZ Drive found, bias the offset */ 2036c2c66affSColin Finck IsEzDrive = TRUE; 2037c2c66affSColin Finck ExFreePoolWithTag(MbrBuffer, TAG_FILE_SYSTEM); 2038c2c66affSColin Finck Offset.QuadPart = 512; 2039c2c66affSColin Finck } 2040c2c66affSColin Finck 2041c2c66affSColin Finck /* Get the number of bits to shift to multiply by the sector size */ 2042c2c66affSColin Finck for (k = 0; k < 32; k++) if ((SectorSize >> k) == 1) break; 2043c2c66affSColin Finck 2044c2c66affSColin Finck /* Check if there's only one partition */ 2045c2c66affSColin Finck if (PartitionBuffer->PartitionCount == 1) 2046c2c66affSColin Finck { 2047c2c66affSColin Finck /* Check if it has no starting offset or hidden sectors */ 2048c2c66affSColin Finck if (!(PartitionInfo->StartingOffset.QuadPart) && 2049c2c66affSColin Finck !(PartitionInfo->HiddenSectors)) 2050c2c66affSColin Finck { 2051c2c66affSColin Finck /* Then it's a super floppy */ 2052c2c66affSColin Finck IsSuperFloppy = TRUE; 2053c2c66affSColin Finck 2054c2c66affSColin Finck /* Which also means it must be non-bootable FAT-16 */ 2055c2c66affSColin Finck if ((PartitionInfo->PartitionNumber) || 2056c2c66affSColin Finck (PartitionInfo->PartitionType != PARTITION_FAT_16) || 2057c2c66affSColin Finck (PartitionInfo->BootIndicator)) 2058c2c66affSColin Finck { 2059c2c66affSColin Finck /* It's not, so we fail */ 2060c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 2061c2c66affSColin Finck } 2062c2c66affSColin Finck 2063c2c66affSColin Finck /* Check if it needs a rewrite, and disable EZ drive for sure */ 2064c2c66affSColin Finck if (PartitionInfo->RewritePartition) DoRewrite = TRUE; 2065c2c66affSColin Finck IsEzDrive = FALSE; 2066c2c66affSColin Finck } 2067c2c66affSColin Finck } 2068c2c66affSColin Finck 2069c2c66affSColin Finck /* Count the number of partition tables */ 2070c2c66affSColin Finck DiskLayout->TableCount = (PartitionBuffer->PartitionCount + 4 - 1) / 4; 2071c2c66affSColin Finck 2072c2c66affSColin Finck /* Allocate our partition buffer */ 2073c2c66affSColin Finck Buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, TAG_FILE_SYSTEM); 2074c2c66affSColin Finck if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES; 2075c2c66affSColin Finck 2076c2c66affSColin Finck /* Loop the entries */ 2077c2c66affSColin Finck Entry = (PPTE)&Buffer[PARTITION_TABLE_OFFSET]; 2078c2c66affSColin Finck for (i = 0; i < DiskLayout->TableCount; i++) 2079c2c66affSColin Finck { 2080c2c66affSColin Finck /* Set if this is the MBR partition */ 2081c2c66affSColin Finck IsMbr= (BOOLEAN)!i; 2082c2c66affSColin Finck 2083c2c66affSColin Finck /* Initialize th event */ 2084c2c66affSColin Finck KeInitializeEvent(&Event, NotificationEvent, FALSE); 2085c2c66affSColin Finck 2086c2c66affSColin Finck /* Build the read IRP */ 2087c2c66affSColin Finck Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, 2088c2c66affSColin Finck DeviceObject, 2089c2c66affSColin Finck Buffer, 2090c2c66affSColin Finck BufferSize, 2091c2c66affSColin Finck &Offset, 2092c2c66affSColin Finck &Event, 2093c2c66affSColin Finck &IoStatusBlock); 2094c2c66affSColin Finck if (!Irp) 2095c2c66affSColin Finck { 2096c2c66affSColin Finck /* Fail */ 2097c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES; 2098c2c66affSColin Finck break; 2099c2c66affSColin Finck } 2100c2c66affSColin Finck 2101c2c66affSColin Finck /* Make sure to disable volume verification */ 2102c2c66affSColin Finck IoStackLocation = IoGetNextIrpStackLocation(Irp); 2103c2c66affSColin Finck IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 2104c2c66affSColin Finck 2105c2c66affSColin Finck /* Call the driver */ 2106c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp); 2107c2c66affSColin Finck if (Status == STATUS_PENDING) 2108c2c66affSColin Finck { 2109c2c66affSColin Finck /* Wait for completion */ 2110c2c66affSColin Finck KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 2111c2c66affSColin Finck Status = IoStatusBlock.Status; 2112c2c66affSColin Finck } 2113c2c66affSColin Finck 2114c2c66affSColin Finck /* Check for failure */ 2115c2c66affSColin Finck if (!NT_SUCCESS(Status)) break; 2116c2c66affSColin Finck 2117c2c66affSColin Finck /* If we biased for EZ-Drive, unbias now */ 2118c2c66affSColin Finck if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0; 2119c2c66affSColin Finck 2120c2c66affSColin Finck /* Check if this is a normal disk */ 2121c2c66affSColin Finck if (!IsSuperFloppy) 2122c2c66affSColin Finck { 2123c2c66affSColin Finck /* Set the boot record signature */ 2124c2c66affSColin Finck Buffer[BOOT_SIGNATURE_OFFSET] = BOOT_RECORD_SIGNATURE; 2125c2c66affSColin Finck 2126c2c66affSColin Finck /* By default, don't require a rewrite */ 2127c2c66affSColin Finck DoRewrite = FALSE; 2128c2c66affSColin Finck 2129c2c66affSColin Finck /* Check if we don't have an offset */ 2130c2c66affSColin Finck if (!Offset.QuadPart) 2131c2c66affSColin Finck { 2132c2c66affSColin Finck /* Check if the signature doesn't match */ 2133c2c66affSColin Finck if (((PULONG)Buffer)[PARTITION_TABLE_OFFSET / 2 - 1] != 2134c2c66affSColin Finck PartitionBuffer->Signature) 2135c2c66affSColin Finck { 2136c2c66affSColin Finck /* Then write the signature and now w need a rewrite */ 2137c2c66affSColin Finck ((PULONG)Buffer)[PARTITION_TABLE_OFFSET / 2 - 1] = 2138c2c66affSColin Finck PartitionBuffer->Signature; 2139c2c66affSColin Finck DoRewrite = TRUE; 2140c2c66affSColin Finck } 2141c2c66affSColin Finck } 2142c2c66affSColin Finck 2143c2c66affSColin Finck /* Loop the partition table entries */ 2144c2c66affSColin Finck PartitionTable = &DiskLayout->PartitionTable[i]; 2145c2c66affSColin Finck for (j = 0; j < 4; j++) 2146c2c66affSColin Finck { 2147c2c66affSColin Finck /* Get the current entry and type */ 2148c2c66affSColin Finck TableEntry = &PartitionTable->PartitionEntry[j]; 2149c2c66affSColin Finck PartitionType = TableEntry->PartitionType; 2150c2c66affSColin Finck 2151c2c66affSColin Finck /* Check if the entry needs a rewrite */ 2152c2c66affSColin Finck if (TableEntry->RewritePartition) 2153c2c66affSColin Finck { 2154c2c66affSColin Finck /* Then we need one too */ 2155c2c66affSColin Finck DoRewrite = TRUE; 2156c2c66affSColin Finck 2157c2c66affSColin Finck /* Save the type and if it's a bootable partition */ 2158c2c66affSColin Finck Entry[j].PartitionType = TableEntry->PartitionType; 2159c2c66affSColin Finck Entry[j].ActiveFlag = TableEntry->BootIndicator ? 0x80 : 0; 2160c2c66affSColin Finck 2161c2c66affSColin Finck /* Make sure it's used */ 2162c2c66affSColin Finck if (PartitionType != PARTITION_ENTRY_UNUSED) 2163c2c66affSColin Finck { 2164c2c66affSColin Finck /* Make sure it's not a container (unless primary) */ 2165c2c66affSColin Finck if ((IsMbr) || !(IsContainerPartition(PartitionType))) 2166c2c66affSColin Finck { 2167c2c66affSColin Finck /* Use the partition offset */ 2168c2c66affSColin Finck StartOffset.QuadPart = Offset.QuadPart; 2169c2c66affSColin Finck } 2170c2c66affSColin Finck else 2171c2c66affSColin Finck { 2172c2c66affSColin Finck /* Use the extended logical partition offset */ 2173c2c66affSColin Finck StartOffset.QuadPart = ExtendedOffset.QuadPart; 2174c2c66affSColin Finck } 2175c2c66affSColin Finck 2176c2c66affSColin Finck /* Set the sector offset */ 2177c2c66affSColin Finck SectorOffset.QuadPart = TableEntry-> 2178c2c66affSColin Finck StartingOffset.QuadPart - 2179c2c66affSColin Finck StartOffset.QuadPart; 2180c2c66affSColin Finck 2181c2c66affSColin Finck /* Now calculate the starting sector */ 2182c2c66affSColin Finck StartOffset.QuadPart = SectorOffset.QuadPart >> k; 2183c2c66affSColin Finck Entry[j].StartingSector = StartOffset.LowPart; 2184c2c66affSColin Finck 2185c2c66affSColin Finck /* As well as the length */ 2186c2c66affSColin Finck PartitionLength.QuadPart = TableEntry->PartitionLength. 2187c2c66affSColin Finck QuadPart >> k; 2188c2c66affSColin Finck Entry[j].PartitionLength = PartitionLength.LowPart; 2189c2c66affSColin Finck 2190c2c66affSColin Finck /* Calculate the CHS values */ 2191c2c66affSColin Finck HalpCalculateChsValues(&TableEntry->StartingOffset, 2192c2c66affSColin Finck &TableEntry->PartitionLength, 2193c2c66affSColin Finck k, 2194c2c66affSColin Finck SectorsPerTrack, 2195c2c66affSColin Finck NumberOfHeads, 2196c2c66affSColin Finck ConventionalCylinders, 2197c2c66affSColin Finck (PPARTITION_DESCRIPTOR) 2198c2c66affSColin Finck &Entry[j]); 2199c2c66affSColin Finck } 2200c2c66affSColin Finck else 2201c2c66affSColin Finck { 2202c2c66affSColin Finck /* Otherwise set up an empty entry */ 2203c2c66affSColin Finck Entry[j].StartingSector = 0; 2204c2c66affSColin Finck Entry[j].PartitionLength = 0; 2205c2c66affSColin Finck Entry[j].StartingTrack = 0; 2206c2c66affSColin Finck Entry[j].EndingTrack = 0; 2207c2c66affSColin Finck Entry[j].StartingCylinder = 0; 2208c2c66affSColin Finck Entry[j].EndingCylinder = 0; 2209c2c66affSColin Finck } 2210c2c66affSColin Finck } 2211c2c66affSColin Finck 2212c2c66affSColin Finck /* Check if this is a container partition */ 2213c2c66affSColin Finck if (IsContainerPartition(PartitionType)) 2214c2c66affSColin Finck { 2215c2c66affSColin Finck /* Then update the offset to use */ 2216c2c66affSColin Finck NextOffset = TableEntry->StartingOffset; 2217c2c66affSColin Finck } 2218c2c66affSColin Finck } 2219c2c66affSColin Finck } 2220c2c66affSColin Finck 2221c2c66affSColin Finck /* Check if we need to write back the buffer */ 2222c2c66affSColin Finck if (DoRewrite) 2223c2c66affSColin Finck { 2224c2c66affSColin Finck /* We don't need to do this again */ 2225c2c66affSColin Finck DoRewrite = FALSE; 2226c2c66affSColin Finck 2227c2c66affSColin Finck /* Initialize the event */ 2228c2c66affSColin Finck KeInitializeEvent(&Event, NotificationEvent, FALSE); 2229c2c66affSColin Finck 2230c2c66affSColin Finck /* If we unbiased for EZ-Drive, rebias now */ 2231c2c66affSColin Finck if ((IsEzDrive) && !(Offset.QuadPart)) Offset.QuadPart = 512; 2232c2c66affSColin Finck 2233c2c66affSColin Finck /* Build the write IRP */ 2234c2c66affSColin Finck Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE, 2235c2c66affSColin Finck DeviceObject, 2236c2c66affSColin Finck Buffer, 2237c2c66affSColin Finck BufferSize, 2238c2c66affSColin Finck &Offset, 2239c2c66affSColin Finck &Event, 2240c2c66affSColin Finck &IoStatusBlock); 2241c2c66affSColin Finck if (!Irp) 2242c2c66affSColin Finck { 2243c2c66affSColin Finck /* Fail */ 2244c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES; 2245c2c66affSColin Finck break; 2246c2c66affSColin Finck } 2247c2c66affSColin Finck 2248c2c66affSColin Finck /* Make sure to disable volume verification */ 2249c2c66affSColin Finck IoStackLocation = IoGetNextIrpStackLocation(Irp); 2250c2c66affSColin Finck IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 2251c2c66affSColin Finck 2252c2c66affSColin Finck /* Call the driver */ 2253c2c66affSColin Finck Status = IoCallDriver(DeviceObject, Irp); 2254c2c66affSColin Finck if (Status == STATUS_PENDING) 2255c2c66affSColin Finck { 2256c2c66affSColin Finck /* Wait for completion */ 2257c2c66affSColin Finck KeWaitForSingleObject(&Event, 2258c2c66affSColin Finck Executive, 2259c2c66affSColin Finck KernelMode, 2260c2c66affSColin Finck FALSE, 2261c2c66affSColin Finck NULL); 2262c2c66affSColin Finck Status = IoStatusBlock.Status; 2263c2c66affSColin Finck } 2264c2c66affSColin Finck 2265c2c66affSColin Finck /* Check for failure */ 2266c2c66affSColin Finck if (!NT_SUCCESS(Status)) break; 2267c2c66affSColin Finck 2268c2c66affSColin Finck /* If we biased for EZ-Drive, unbias now */ 2269c2c66affSColin Finck if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0; 2270c2c66affSColin Finck } 2271c2c66affSColin Finck 2272c2c66affSColin Finck /* Update the partition offset and set the extended offset if needed */ 2273c2c66affSColin Finck Offset = NextOffset; 2274c2c66affSColin Finck if (IsMbr) ExtendedOffset = NextOffset; 2275c2c66affSColin Finck } 2276c2c66affSColin Finck 2277c2c66affSColin Finck /* If we had a buffer, free it, then return status */ 2278c2c66affSColin Finck if (Buffer) ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM); 2279c2c66affSColin Finck return Status; 2280c2c66affSColin Finck } 2281c2c66affSColin Finck 2282c2c66affSColin Finck /* PUBLIC FUNCTIONS **********************************************************/ 2283c2c66affSColin Finck 2284c2c66affSColin Finck /* 2285c2c66affSColin Finck * @implemented 2286c2c66affSColin Finck */ 2287c2c66affSColin Finck VOID 2288c2c66affSColin Finck FASTCALL 2289c2c66affSColin Finck HalExamineMBR(IN PDEVICE_OBJECT DeviceObject, 2290c2c66affSColin Finck IN ULONG SectorSize, 2291c2c66affSColin Finck IN ULONG MbrTypeIdentifier, 2292c2c66affSColin Finck OUT PVOID *MbrBuffer) 2293c2c66affSColin Finck { 2294c2c66affSColin Finck HALDISPATCH->HalExamineMBR(DeviceObject, 2295c2c66affSColin Finck SectorSize, 2296c2c66affSColin Finck MbrTypeIdentifier, 2297c2c66affSColin Finck MbrBuffer); 2298c2c66affSColin Finck } 2299c2c66affSColin Finck 2300c2c66affSColin Finck /* 2301c2c66affSColin Finck * @implemented 2302c2c66affSColin Finck */ 2303c2c66affSColin Finck NTSTATUS 2304c2c66affSColin Finck FASTCALL 2305c2c66affSColin Finck IoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject, 2306c2c66affSColin Finck IN ULONG SectorSize, 2307c2c66affSColin Finck IN BOOLEAN ReturnRecognizedPartitions, 2308c2c66affSColin Finck IN OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer) 2309c2c66affSColin Finck { 2310c2c66affSColin Finck return HALDISPATCH->HalIoReadPartitionTable(DeviceObject, 2311c2c66affSColin Finck SectorSize, 2312c2c66affSColin Finck ReturnRecognizedPartitions, 2313c2c66affSColin Finck PartitionBuffer); 2314c2c66affSColin Finck } 2315c2c66affSColin Finck 2316c2c66affSColin Finck /* 2317c2c66affSColin Finck * @implemented 2318c2c66affSColin Finck */ 2319c2c66affSColin Finck NTSTATUS 2320c2c66affSColin Finck FASTCALL 2321c2c66affSColin Finck IoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject, 2322c2c66affSColin Finck IN ULONG SectorSize, 2323c2c66affSColin Finck IN ULONG PartitionNumber, 2324c2c66affSColin Finck IN ULONG PartitionType) 2325c2c66affSColin Finck { 2326c2c66affSColin Finck return HALDISPATCH->HalIoSetPartitionInformation(DeviceObject, 2327c2c66affSColin Finck SectorSize, 2328c2c66affSColin Finck PartitionNumber, 2329c2c66affSColin Finck PartitionType); 2330c2c66affSColin Finck } 2331c2c66affSColin Finck 2332c2c66affSColin Finck /* 2333c2c66affSColin Finck * @implemented 2334c2c66affSColin Finck */ 2335c2c66affSColin Finck NTSTATUS 2336c2c66affSColin Finck FASTCALL 2337c2c66affSColin Finck IoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject, 2338c2c66affSColin Finck IN ULONG SectorSize, 2339c2c66affSColin Finck IN ULONG SectorsPerTrack, 2340c2c66affSColin Finck IN ULONG NumberOfHeads, 2341c2c66affSColin Finck IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer) 2342c2c66affSColin Finck { 2343c2c66affSColin Finck return HALDISPATCH->HalIoWritePartitionTable(DeviceObject, 2344c2c66affSColin Finck SectorSize, 2345c2c66affSColin Finck SectorsPerTrack, 2346c2c66affSColin Finck NumberOfHeads, 2347c2c66affSColin Finck PartitionBuffer); 2348c2c66affSColin Finck } 2349c2c66affSColin Finck 2350c2c66affSColin Finck /* 2351c2c66affSColin Finck * @implemented 2352c2c66affSColin Finck */ 2353c2c66affSColin Finck VOID 2354c2c66affSColin Finck FASTCALL 2355c2c66affSColin Finck IoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock, 2356c2c66affSColin Finck IN PSTRING NtDeviceName, 2357c2c66affSColin Finck OUT PUCHAR NtSystemPath, 2358c2c66affSColin Finck OUT PSTRING NtSystemPathString) 2359c2c66affSColin Finck { 2360c2c66affSColin Finck HALDISPATCH->HalIoAssignDriveLetters(LoaderBlock, 2361c2c66affSColin Finck NtDeviceName, 2362c2c66affSColin Finck NtSystemPath, 2363c2c66affSColin Finck NtSystemPathString); 2364c2c66affSColin Finck } 2365c2c66affSColin Finck 2366c2c66affSColin Finck /* EOF */ 2367