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