Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendisksup.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/fstub/disksup.c 00005 * PURPOSE: I/O HAL Routines for Disk Access 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 * Eric Kohl 00008 * Casper S. Hornstrup (chorns@users.sourceforge.net) 00009 */ 00010 00011 /* INCLUDES ******************************************************************/ 00012 00013 #include <ntoskrnl.h> 00014 #define NDEBUG 00015 #include <debug.h> 00016 #include <internal/hal.h> 00017 00018 /* DEPRECATED FUNCTIONS ******************************************************/ 00019 00020 #if 1 00021 const WCHAR DiskMountString[] = L"\\DosDevices\\%C:"; 00022 00023 #define AUTO_DRIVE MAXULONG 00024 00025 #define PARTITION_MAGIC 0xaa55 00026 00027 #define EFI_PMBR_OSTYPE_EFI 0xEE 00028 00029 #include <pshpack1.h> 00030 00031 typedef struct _REG_DISK_MOUNT_INFO 00032 { 00033 ULONG Signature; 00034 LARGE_INTEGER StartingOffset; 00035 } REG_DISK_MOUNT_INFO, *PREG_DISK_MOUNT_INFO; 00036 00037 #include <poppack.h> 00038 00039 typedef enum _DISK_MANAGER 00040 { 00041 NoDiskManager, 00042 OntrackDiskManager, 00043 EZ_Drive 00044 } DISK_MANAGER; 00045 00046 static BOOLEAN 00047 HalpAssignDrive(IN PUNICODE_STRING PartitionName, 00048 IN ULONG DriveNumber, 00049 IN UCHAR DriveType, 00050 IN ULONG Signature, 00051 IN LARGE_INTEGER StartingOffset, 00052 IN HANDLE hKey, 00053 IN PUNICODE_STRING BootDevice, 00054 OUT PUCHAR NtSystemPath) 00055 { 00056 WCHAR DriveNameBuffer[16]; 00057 UNICODE_STRING DriveName; 00058 ULONG i; 00059 NTSTATUS Status; 00060 REG_DISK_MOUNT_INFO DiskMountInfo; 00061 00062 DPRINT("HalpAssignDrive()\n"); 00063 00064 if ((DriveNumber != AUTO_DRIVE) && (DriveNumber < 26)) 00065 { 00066 /* Force assignment */ 00067 KeAcquireGuardedMutex(&ObpDeviceMapLock); 00068 if ((ObSystemDeviceMap->DriveMap & (1 << DriveNumber)) != 0) 00069 { 00070 DbgPrint("Drive letter already used!\n"); 00071 KeReleaseGuardedMutex(&ObpDeviceMapLock); 00072 return FALSE; 00073 } 00074 KeReleaseGuardedMutex(&ObpDeviceMapLock); 00075 } 00076 else 00077 { 00078 /* Automatic assignment */ 00079 DriveNumber = AUTO_DRIVE; 00080 KeAcquireGuardedMutex(&ObpDeviceMapLock); 00081 for (i = 2; i < 26; i++) 00082 { 00083 if ((ObSystemDeviceMap->DriveMap & (1 << i)) == 0) 00084 { 00085 DriveNumber = i; 00086 break; 00087 } 00088 } 00089 KeReleaseGuardedMutex(&ObpDeviceMapLock); 00090 00091 if (DriveNumber == AUTO_DRIVE) 00092 { 00093 DbgPrint("No drive letter available!\n"); 00094 return FALSE; 00095 } 00096 } 00097 00098 DPRINT("DriveNumber %d\n", DriveNumber); 00099 00100 /* Build drive name */ 00101 swprintf(DriveNameBuffer, 00102 L"\\??\\%C:", 00103 'A' + DriveNumber); 00104 RtlInitUnicodeString(&DriveName, 00105 DriveNameBuffer); 00106 00107 DPRINT(" %wZ ==> %wZ\n", 00108 &DriveName, 00109 PartitionName); 00110 00111 /* Create symbolic link */ 00112 Status = IoCreateSymbolicLink(&DriveName, 00113 PartitionName); 00114 00115 if (hKey && 00116 DriveType == DOSDEVICE_DRIVE_FIXED && 00117 Signature) 00118 { 00119 DiskMountInfo.Signature = Signature; 00120 DiskMountInfo.StartingOffset = StartingOffset; 00121 swprintf(DriveNameBuffer, DiskMountString, L'A' + DriveNumber); 00122 RtlInitUnicodeString(&DriveName, DriveNameBuffer); 00123 00124 Status = ZwSetValueKey(hKey, 00125 &DriveName, 00126 0, 00127 REG_BINARY, 00128 &DiskMountInfo, 00129 sizeof(DiskMountInfo)); 00130 if (!NT_SUCCESS(Status)) 00131 { 00132 DPRINT1("ZwCreateValueKey failed for %wZ, status=%x\n", &DriveName, Status); 00133 } 00134 } 00135 00136 /* Check if this is a boot partition */ 00137 if (RtlCompareUnicodeString(PartitionName, BootDevice, FALSE) == 0) 00138 { 00139 /* Set NtSystemPath to that partition's disk letter */ 00140 *NtSystemPath = (UCHAR)('A' + DriveNumber); 00141 } 00142 00143 return TRUE; 00144 } 00145 00146 ULONG 00147 xHalpGetRDiskCount(VOID) 00148 { 00149 NTSTATUS Status; 00150 UNICODE_STRING ArcName; 00151 PWCHAR ArcNameBuffer; 00152 OBJECT_ATTRIBUTES ObjectAttributes; 00153 HANDLE DirectoryHandle; 00154 POBJECT_DIRECTORY_INFORMATION DirectoryInfo; 00155 ULONG Skip; 00156 ULONG ResultLength; 00157 ULONG CurrentRDisk; 00158 ULONG RDiskCount; 00159 BOOLEAN First = TRUE; 00160 ULONG Count; 00161 00162 DirectoryInfo = ExAllocatePoolWithTag(PagedPool, 2 * PAGE_SIZE, TAG_FILE_SYSTEM); 00163 if (DirectoryInfo == NULL) 00164 { 00165 return 0; 00166 } 00167 00168 RtlInitUnicodeString(&ArcName, L"\\ArcName"); 00169 InitializeObjectAttributes(&ObjectAttributes, 00170 &ArcName, 00171 0, 00172 NULL, 00173 NULL); 00174 00175 Status = ZwOpenDirectoryObject (&DirectoryHandle, 00176 SYMBOLIC_LINK_ALL_ACCESS, 00177 &ObjectAttributes); 00178 if (!NT_SUCCESS(Status)) 00179 { 00180 DPRINT1("ZwOpenDirectoryObject for %wZ failed, status=%lx\n", &ArcName, Status); 00181 ExFreePoolWithTag(DirectoryInfo, TAG_FILE_SYSTEM); 00182 return 0; 00183 } 00184 00185 RDiskCount = 0; 00186 Skip = 0; 00187 while (NT_SUCCESS(Status)) 00188 { 00189 Status = NtQueryDirectoryObject (DirectoryHandle, 00190 DirectoryInfo, 00191 2 * PAGE_SIZE, 00192 FALSE, 00193 First, 00194 &Skip, 00195 &ResultLength); 00196 First = FALSE; 00197 if (NT_SUCCESS(Status)) 00198 { 00199 Count = 0; 00200 while (DirectoryInfo[Count].Name.Buffer) 00201 { 00202 DPRINT("Count %x\n", Count); 00203 DirectoryInfo[Count].Name.Buffer[DirectoryInfo[Count].Name.Length / sizeof(WCHAR)] = 0; 00204 ArcNameBuffer = DirectoryInfo[Count].Name.Buffer; 00205 if (DirectoryInfo[Count].Name.Length >= sizeof(L"multi(0)disk(0)rdisk(0)") - sizeof(WCHAR) && 00206 !_wcsnicmp(ArcNameBuffer, L"multi(0)disk(0)rdisk(", (sizeof(L"multi(0)disk(0)rdisk(") - sizeof(WCHAR)) / sizeof(WCHAR))) 00207 { 00208 DPRINT("%S\n", ArcNameBuffer); 00209 ArcNameBuffer += (sizeof(L"multi(0)disk(0)rdisk(") - sizeof(WCHAR)) / sizeof(WCHAR); 00210 CurrentRDisk = 0; 00211 while (iswdigit(*ArcNameBuffer)) 00212 { 00213 CurrentRDisk = CurrentRDisk * 10 + *ArcNameBuffer - L'0'; 00214 ArcNameBuffer++; 00215 } 00216 if (!_wcsicmp(ArcNameBuffer, L")") && 00217 CurrentRDisk >= RDiskCount) 00218 { 00219 RDiskCount = CurrentRDisk + 1; 00220 } 00221 } 00222 Count++; 00223 } 00224 } 00225 } 00226 ExFreePoolWithTag(DirectoryInfo, TAG_FILE_SYSTEM); 00227 return RDiskCount; 00228 } 00229 00230 NTSTATUS 00231 xHalpGetDiskNumberFromRDisk(ULONG RDisk, PULONG DiskNumber) 00232 { 00233 WCHAR NameBuffer[80]; 00234 UNICODE_STRING ArcName; 00235 UNICODE_STRING LinkName; 00236 OBJECT_ATTRIBUTES ObjectAttributes; 00237 HANDLE LinkHandle; 00238 NTSTATUS Status; 00239 00240 swprintf(NameBuffer, 00241 L"\\ArcName\\multi(0)disk(0)rdisk(%lu)", 00242 RDisk); 00243 00244 RtlInitUnicodeString(&ArcName, NameBuffer); 00245 InitializeObjectAttributes(&ObjectAttributes, 00246 &ArcName, 00247 0, 00248 NULL, 00249 NULL); 00250 Status = ZwOpenSymbolicLinkObject(&LinkHandle, 00251 SYMBOLIC_LINK_ALL_ACCESS, 00252 &ObjectAttributes); 00253 if (!NT_SUCCESS(Status)) 00254 { 00255 DPRINT1("ZwOpenSymbolicLinkObject failed for %wZ, status=%lx\n", &ArcName, Status); 00256 return Status; 00257 } 00258 00259 LinkName.Buffer = NameBuffer; 00260 LinkName.Length = 0; 00261 LinkName.MaximumLength = sizeof(NameBuffer); 00262 Status = ZwQuerySymbolicLinkObject(LinkHandle, 00263 &LinkName, 00264 NULL); 00265 ZwClose(LinkHandle); 00266 if (!NT_SUCCESS(Status)) 00267 { 00268 DPRINT1("ZwQuerySymbolicLinkObject failed, status=%lx\n", Status); 00269 return Status; 00270 } 00271 if (LinkName.Length < sizeof(L"\\Device\\Harddisk0\\Partition0") - sizeof(WCHAR) || 00272 LinkName.Length >= sizeof(NameBuffer)) 00273 { 00274 return STATUS_UNSUCCESSFUL; 00275 } 00276 00277 NameBuffer[LinkName.Length / sizeof(WCHAR)] = 0; 00278 if (_wcsnicmp(NameBuffer, L"\\Device\\Harddisk", (sizeof(L"\\Device\\Harddisk") - sizeof(WCHAR)) / sizeof(WCHAR))) 00279 { 00280 return STATUS_UNSUCCESSFUL; 00281 } 00282 LinkName.Buffer += (sizeof(L"\\Device\\Harddisk") - sizeof(WCHAR)) / sizeof(WCHAR); 00283 00284 if (!iswdigit(*LinkName.Buffer)) 00285 { 00286 return STATUS_UNSUCCESSFUL; 00287 } 00288 *DiskNumber = 0; 00289 while (iswdigit(*LinkName.Buffer)) 00290 { 00291 *DiskNumber = *DiskNumber * 10 + *LinkName.Buffer - L'0'; 00292 LinkName.Buffer++; 00293 } 00294 if (_wcsicmp(LinkName.Buffer, L"\\Partition0")) 00295 { 00296 return STATUS_UNSUCCESSFUL; 00297 } 00298 return STATUS_SUCCESS; 00299 } 00300 00301 NTSTATUS 00302 FASTCALL 00303 xHalQueryDriveLayout(IN PUNICODE_STRING DeviceName, 00304 OUT PDRIVE_LAYOUT_INFORMATION *LayoutInfo) 00305 { 00306 IO_STATUS_BLOCK StatusBlock; 00307 DISK_GEOMETRY DiskGeometry; 00308 PDEVICE_OBJECT DeviceObject = NULL; 00309 PFILE_OBJECT FileObject; 00310 KEVENT Event; 00311 PIRP Irp; 00312 NTSTATUS Status; 00313 00314 DPRINT("xHalpQueryDriveLayout %wZ %p\n", 00315 DeviceName, 00316 LayoutInfo); 00317 00318 /* Get the drives sector size */ 00319 Status = IoGetDeviceObjectPointer(DeviceName, 00320 FILE_READ_ATTRIBUTES, 00321 &FileObject, 00322 &DeviceObject); 00323 if (!NT_SUCCESS(Status)) 00324 { 00325 DPRINT("Status %x\n", Status); 00326 return(Status); 00327 } 00328 00329 KeInitializeEvent(&Event, 00330 NotificationEvent, 00331 FALSE); 00332 00333 Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY, 00334 DeviceObject, 00335 NULL, 00336 0, 00337 &DiskGeometry, 00338 sizeof(DISK_GEOMETRY), 00339 FALSE, 00340 &Event, 00341 &StatusBlock); 00342 if (Irp == NULL) 00343 { 00344 ObDereferenceObject(FileObject); 00345 return(STATUS_INSUFFICIENT_RESOURCES); 00346 } 00347 00348 Status = IoCallDriver(DeviceObject, 00349 Irp); 00350 if (Status == STATUS_PENDING) 00351 { 00352 KeWaitForSingleObject(&Event, 00353 Executive, 00354 KernelMode, 00355 FALSE, 00356 NULL); 00357 Status = StatusBlock.Status; 00358 } 00359 if (!NT_SUCCESS(Status)) 00360 { 00361 if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) 00362 { 00363 DiskGeometry.BytesPerSector = 512; 00364 } 00365 else 00366 { 00367 ObDereferenceObject(FileObject); 00368 return(Status); 00369 } 00370 } 00371 00372 DPRINT("DiskGeometry.BytesPerSector: %d\n", 00373 DiskGeometry.BytesPerSector); 00374 00375 if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) 00376 { 00377 PDRIVE_LAYOUT_INFORMATION Buffer; 00378 00379 /* Allocate a partition list for a single entry. */ 00380 Buffer = ExAllocatePoolWithTag(NonPagedPool, 00381 sizeof(DRIVE_LAYOUT_INFORMATION), TAG_FILE_SYSTEM); 00382 if (Buffer != NULL) 00383 { 00384 RtlZeroMemory(Buffer, 00385 sizeof(DRIVE_LAYOUT_INFORMATION)); 00386 Buffer->PartitionCount = 1; 00387 *LayoutInfo = Buffer; 00388 00389 Status = STATUS_SUCCESS; 00390 } 00391 else 00392 { 00393 Status = STATUS_UNSUCCESSFUL; 00394 } 00395 } 00396 else 00397 { 00398 /* Read the partition table */ 00399 Status = IoReadPartitionTable(DeviceObject, 00400 DiskGeometry.BytesPerSector, 00401 TRUE, 00402 LayoutInfo); 00403 } 00404 00405 ObDereferenceObject(FileObject); 00406 00407 return(Status); 00408 } 00409 00410 VOID 00411 FASTCALL 00412 xHalIoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock, 00413 IN PSTRING NtDeviceName, 00414 OUT PUCHAR NtSystemPath, 00415 OUT PSTRING NtSystemPathString) 00416 { 00417 PDRIVE_LAYOUT_INFORMATION *LayoutArray; 00418 PCONFIGURATION_INFORMATION ConfigInfo; 00419 OBJECT_ATTRIBUTES ObjectAttributes; 00420 IO_STATUS_BLOCK StatusBlock; 00421 UNICODE_STRING UnicodeString1; 00422 UNICODE_STRING UnicodeString2; 00423 HANDLE FileHandle; 00424 PWSTR Buffer1; 00425 PWSTR Buffer2; 00426 ULONG i, j, k; 00427 ULONG DiskNumber; 00428 ULONG RDisk; 00429 NTSTATUS Status; 00430 HANDLE hKey; 00431 ULONG Length; 00432 PKEY_VALUE_PARTIAL_INFORMATION PartialInformation; 00433 PREG_DISK_MOUNT_INFO DiskMountInfo; 00434 ULONG RDiskCount; 00435 UNICODE_STRING BootDevice; 00436 00437 Status = RtlAnsiStringToUnicodeString(&BootDevice, 00438 NtDeviceName, 00439 TRUE); 00440 00441 DPRINT("xHalIoAssignDriveLetters()\n"); 00442 00443 ConfigInfo = IoGetConfigurationInformation(); 00444 00445 RDiskCount = xHalpGetRDiskCount(); 00446 00447 DPRINT("RDiskCount %d\n", RDiskCount); 00448 00449 Buffer1 = (PWSTR)ExAllocatePoolWithTag(PagedPool, 00450 64 * sizeof(WCHAR), TAG_FILE_SYSTEM); 00451 Buffer2 = (PWSTR)ExAllocatePoolWithTag(PagedPool, 00452 32 * sizeof(WCHAR), TAG_FILE_SYSTEM); 00453 00454 PartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(PagedPool, 00455 sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(REG_DISK_MOUNT_INFO), TAG_FILE_SYSTEM); 00456 00457 if (!Buffer1 || !Buffer2 || !PartialInformation) return; 00458 00459 DiskMountInfo = (PREG_DISK_MOUNT_INFO) PartialInformation->Data; 00460 00461 /* Open or Create the 'MountedDevices' key */ 00462 RtlInitUnicodeString(&UnicodeString1, L"\\Registry\\Machine\\SYSTEM\\MountedDevices"); 00463 InitializeObjectAttributes(&ObjectAttributes, 00464 &UnicodeString1, 00465 OBJ_CASE_INSENSITIVE, 00466 NULL, 00467 NULL); 00468 Status = ZwOpenKey(&hKey, 00469 KEY_ALL_ACCESS, 00470 &ObjectAttributes); 00471 if (!NT_SUCCESS(Status)) 00472 { 00473 Status = ZwCreateKey(&hKey, 00474 KEY_ALL_ACCESS, 00475 &ObjectAttributes, 00476 0, 00477 NULL, 00478 REG_OPTION_NON_VOLATILE, 00479 NULL); 00480 } 00481 if (!NT_SUCCESS(Status)) 00482 { 00483 hKey = NULL; 00484 DPRINT("ZwCreateKey failed for %wZ, status=%x\n", &UnicodeString1, Status); 00485 } 00486 00487 /* Create PhysicalDrive links */ 00488 DPRINT("Physical disk drives: %d\n", ConfigInfo->DiskCount); 00489 for (i = 0; i < ConfigInfo->DiskCount; i++) 00490 { 00491 swprintf(Buffer1, 00492 L"\\Device\\Harddisk%d\\Partition0", 00493 i); 00494 RtlInitUnicodeString(&UnicodeString1, 00495 Buffer1); 00496 00497 InitializeObjectAttributes(&ObjectAttributes, 00498 &UnicodeString1, 00499 0, 00500 NULL, 00501 NULL); 00502 00503 Status = ZwOpenFile(&FileHandle, 00504 FILE_READ_DATA | SYNCHRONIZE, 00505 &ObjectAttributes, 00506 &StatusBlock, 00507 FILE_SHARE_READ, 00508 FILE_SYNCHRONOUS_IO_NONALERT); 00509 if (NT_SUCCESS(Status)) 00510 { 00511 ZwClose(FileHandle); 00512 00513 swprintf(Buffer2, 00514 L"\\??\\PhysicalDrive%d", 00515 i); 00516 RtlInitUnicodeString(&UnicodeString2, 00517 Buffer2); 00518 00519 DPRINT("Creating link: %S ==> %S\n", 00520 Buffer2, 00521 Buffer1); 00522 00523 IoCreateSymbolicLink(&UnicodeString2, 00524 &UnicodeString1); 00525 } 00526 } 00527 00528 /* Initialize layout array */ 00529 if (ConfigInfo->DiskCount == 0) 00530 goto end_assign_disks; 00531 LayoutArray = ExAllocatePoolWithTag(NonPagedPool, 00532 ConfigInfo->DiskCount * sizeof(PDRIVE_LAYOUT_INFORMATION), TAG_FILE_SYSTEM); 00533 if (!LayoutArray) 00534 { 00535 ExFreePoolWithTag(PartialInformation, TAG_FILE_SYSTEM); 00536 ExFreePoolWithTag(Buffer2, TAG_FILE_SYSTEM); 00537 ExFreePoolWithTag(Buffer1, TAG_FILE_SYSTEM); 00538 if (hKey) ZwClose(hKey); 00539 } 00540 00541 RtlZeroMemory(LayoutArray, 00542 ConfigInfo->DiskCount * sizeof(PDRIVE_LAYOUT_INFORMATION)); 00543 for (i = 0; i < ConfigInfo->DiskCount; i++) 00544 { 00545 swprintf(Buffer1, 00546 L"\\Device\\Harddisk%d\\Partition0", 00547 i); 00548 RtlInitUnicodeString(&UnicodeString1, 00549 Buffer1); 00550 00551 Status = xHalQueryDriveLayout(&UnicodeString1, 00552 &LayoutArray[i]); 00553 if (!NT_SUCCESS(Status)) 00554 { 00555 DbgPrint("xHalQueryDriveLayout() failed (Status = 0x%lx)\n", 00556 Status); 00557 LayoutArray[i] = NULL; 00558 continue; 00559 } 00560 /* We don't use the RewritePartition value while mounting the disks. 00561 * We use this value for marking pre-assigned (registry) partitions. 00562 */ 00563 for (j = 0; j < LayoutArray[i]->PartitionCount; j++) 00564 { 00565 LayoutArray[i]->PartitionEntry[j].RewritePartition = FALSE; 00566 } 00567 } 00568 00569 #ifndef NDEBUG 00570 /* Dump layout array */ 00571 for (i = 0; i < ConfigInfo->DiskCount; i++) 00572 { 00573 DPRINT("Harddisk %d:\n", 00574 i); 00575 00576 if (LayoutArray[i] == NULL) 00577 continue; 00578 00579 DPRINT("Logical partitions: %d\n", 00580 LayoutArray[i]->PartitionCount); 00581 00582 for (j = 0; j < LayoutArray[i]->PartitionCount; j++) 00583 { 00584 DPRINT(" %d: nr:%x boot:%x type:%x startblock:%I64u count:%I64u\n", 00585 j, 00586 LayoutArray[i]->PartitionEntry[j].PartitionNumber, 00587 LayoutArray[i]->PartitionEntry[j].BootIndicator, 00588 LayoutArray[i]->PartitionEntry[j].PartitionType, 00589 LayoutArray[i]->PartitionEntry[j].StartingOffset.QuadPart, 00590 LayoutArray[i]->PartitionEntry[j].PartitionLength.QuadPart); 00591 } 00592 } 00593 #endif 00594 00595 /* Assign pre-assigned (registry) partitions */ 00596 if (hKey) 00597 { 00598 for (k = 2; k < 26; k++) 00599 { 00600 swprintf(Buffer1, DiskMountString, L'A' + k); 00601 RtlInitUnicodeString(&UnicodeString1, Buffer1); 00602 Status = ZwQueryValueKey(hKey, 00603 &UnicodeString1, 00604 KeyValuePartialInformation, 00605 PartialInformation, 00606 sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(REG_DISK_MOUNT_INFO), 00607 &Length); 00608 if (NT_SUCCESS(Status) && 00609 PartialInformation->Type == REG_BINARY && 00610 PartialInformation->DataLength == sizeof(REG_DISK_MOUNT_INFO)) 00611 { 00612 DPRINT("%wZ => %08x:%08x%08x\n", &UnicodeString1, DiskMountInfo->Signature, 00613 DiskMountInfo->StartingOffset.u.HighPart, DiskMountInfo->StartingOffset.u.LowPart); 00614 { 00615 BOOLEAN Found = FALSE; 00616 for (i = 0; i < ConfigInfo->DiskCount; i++) 00617 { 00618 DPRINT("%x\n", LayoutArray[i]->Signature); 00619 if (LayoutArray[i] && 00620 LayoutArray[i]->Signature && 00621 LayoutArray[i]->Signature == DiskMountInfo->Signature) 00622 { 00623 for (j = 0; j < LayoutArray[i]->PartitionCount; j++) 00624 { 00625 if (LayoutArray[i]->PartitionEntry[j].StartingOffset.QuadPart == DiskMountInfo->StartingOffset.QuadPart) 00626 { 00627 if (IsRecognizedPartition(LayoutArray[i]->PartitionEntry[j].PartitionType) && 00628 LayoutArray[i]->PartitionEntry[j].RewritePartition == FALSE) 00629 { 00630 swprintf(Buffer2, 00631 L"\\Device\\Harddisk%d\\Partition%d", 00632 i, 00633 LayoutArray[i]->PartitionEntry[j].PartitionNumber); 00634 RtlInitUnicodeString(&UnicodeString2, 00635 Buffer2); 00636 00637 /* Assign drive */ 00638 DPRINT(" %wZ\n", &UnicodeString2); 00639 Found = HalpAssignDrive(&UnicodeString2, 00640 k, 00641 DOSDEVICE_DRIVE_FIXED, 00642 DiskMountInfo->Signature, 00643 DiskMountInfo->StartingOffset, 00644 NULL, 00645 &BootDevice, 00646 NtSystemPath); 00647 /* Mark the partition as assigned */ 00648 LayoutArray[i]->PartitionEntry[j].RewritePartition = TRUE; 00649 } 00650 break; 00651 } 00652 } 00653 } 00654 } 00655 if (Found == FALSE) 00656 { 00657 /* We didn't find a partition for this entry, remove them. */ 00658 Status = ZwDeleteValueKey(hKey, &UnicodeString1); 00659 } 00660 } 00661 } 00662 } 00663 } 00664 00665 /* Assign bootable partition on first harddisk */ 00666 DPRINT("Assigning bootable primary partition on first harddisk:\n"); 00667 if (RDiskCount > 0) 00668 { 00669 Status = xHalpGetDiskNumberFromRDisk(0, &DiskNumber); 00670 if (NT_SUCCESS(Status) && 00671 DiskNumber < ConfigInfo->DiskCount && 00672 LayoutArray[DiskNumber]) 00673 { 00674 /* Search for bootable partition */ 00675 for (j = 0; j < NUM_PARTITION_TABLE_ENTRIES && j < LayoutArray[DiskNumber]->PartitionCount; j++) 00676 { 00677 if ((LayoutArray[DiskNumber]->PartitionEntry[j].BootIndicator == TRUE) && 00678 IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType)) 00679 { 00680 if (LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE) 00681 { 00682 swprintf(Buffer2, 00683 L"\\Device\\Harddisk%lu\\Partition%d", 00684 DiskNumber, 00685 LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber); 00686 RtlInitUnicodeString(&UnicodeString2, 00687 Buffer2); 00688 00689 /* Assign drive */ 00690 DPRINT(" %wZ\n", &UnicodeString2); 00691 HalpAssignDrive(&UnicodeString2, 00692 AUTO_DRIVE, 00693 DOSDEVICE_DRIVE_FIXED, 00694 LayoutArray[DiskNumber]->Signature, 00695 LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset, 00696 hKey, 00697 &BootDevice, 00698 NtSystemPath); 00699 /* Mark the partition as assigned */ 00700 LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE; 00701 } 00702 break; 00703 } 00704 } 00705 } 00706 } 00707 00708 /* Assign remaining primary partitions */ 00709 DPRINT("Assigning remaining primary partitions:\n"); 00710 for (RDisk = 0; RDisk < RDiskCount; RDisk++) 00711 { 00712 Status = xHalpGetDiskNumberFromRDisk(RDisk, &DiskNumber); 00713 if (NT_SUCCESS(Status) && 00714 DiskNumber < ConfigInfo->DiskCount && 00715 LayoutArray[DiskNumber]) 00716 { 00717 /* Search for primary partitions */ 00718 for (j = 0; (j < NUM_PARTITION_TABLE_ENTRIES) && (j < LayoutArray[DiskNumber]->PartitionCount); j++) 00719 { 00720 if (LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE && 00721 IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType)) 00722 { 00723 swprintf(Buffer2, 00724 L"\\Device\\Harddisk%d\\Partition%d", 00725 DiskNumber, 00726 LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber); 00727 RtlInitUnicodeString(&UnicodeString2, 00728 Buffer2); 00729 00730 /* Assign drive */ 00731 DPRINT(" %wZ\n", 00732 &UnicodeString2); 00733 HalpAssignDrive(&UnicodeString2, 00734 AUTO_DRIVE, 00735 DOSDEVICE_DRIVE_FIXED, 00736 LayoutArray[DiskNumber]->Signature, 00737 LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset, 00738 hKey, 00739 &BootDevice, 00740 NtSystemPath); 00741 /* Mark the partition as assigned */ 00742 LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE; 00743 } 00744 } 00745 } 00746 } 00747 00748 /* Assign extended (logical) partitions */ 00749 DPRINT("Assigning extended (logical) partitions:\n"); 00750 for (RDisk = 0; RDisk < RDiskCount; RDisk++) 00751 { 00752 Status = xHalpGetDiskNumberFromRDisk(RDisk, &DiskNumber); 00753 if (NT_SUCCESS(Status) && 00754 DiskNumber < ConfigInfo->DiskCount && 00755 LayoutArray[DiskNumber]) 00756 { 00757 /* Search for extended partitions */ 00758 for (j = NUM_PARTITION_TABLE_ENTRIES; j < LayoutArray[DiskNumber]->PartitionCount; j++) 00759 { 00760 if (IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType) && 00761 LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE && 00762 LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber != 0) 00763 { 00764 swprintf(Buffer2, 00765 L"\\Device\\Harddisk%d\\Partition%d", 00766 DiskNumber, 00767 LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber); 00768 RtlInitUnicodeString(&UnicodeString2, 00769 Buffer2); 00770 00771 /* Assign drive */ 00772 DPRINT(" %wZ\n", 00773 &UnicodeString2); 00774 HalpAssignDrive(&UnicodeString2, 00775 AUTO_DRIVE, 00776 DOSDEVICE_DRIVE_FIXED, 00777 LayoutArray[DiskNumber]->Signature, 00778 LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset, 00779 hKey, 00780 &BootDevice, 00781 NtSystemPath); 00782 /* Mark the partition as assigned */ 00783 LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE; 00784 } 00785 } 00786 } 00787 } 00788 00789 /* Assign remaining primary partitions without an arc-name */ 00790 DPRINT("Assigning remaining primary partitions:\n"); 00791 for (DiskNumber = 0; DiskNumber < ConfigInfo->DiskCount; DiskNumber++) 00792 { 00793 if (LayoutArray[DiskNumber]) 00794 { 00795 /* Search for primary partitions */ 00796 for (j = 0; (j < NUM_PARTITION_TABLE_ENTRIES) && (j < LayoutArray[DiskNumber]->PartitionCount); j++) 00797 { 00798 if (LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE && 00799 IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType)) 00800 { 00801 swprintf(Buffer2, 00802 L"\\Device\\Harddisk%d\\Partition%d", 00803 DiskNumber, 00804 LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber); 00805 RtlInitUnicodeString(&UnicodeString2, 00806 Buffer2); 00807 00808 /* Assign drive */ 00809 DPRINT(" %wZ\n", 00810 &UnicodeString2); 00811 HalpAssignDrive(&UnicodeString2, 00812 AUTO_DRIVE, 00813 DOSDEVICE_DRIVE_FIXED, 00814 LayoutArray[DiskNumber]->Signature, 00815 LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset, 00816 hKey, 00817 &BootDevice, 00818 NtSystemPath); 00819 /* Mark the partition as assigned */ 00820 LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE; 00821 } 00822 } 00823 } 00824 } 00825 00826 /* Assign extended (logical) partitions without an arc-name */ 00827 DPRINT("Assigning extended (logical) partitions:\n"); 00828 for (DiskNumber = 0; DiskNumber < ConfigInfo->DiskCount; DiskNumber++) 00829 { 00830 if (LayoutArray[DiskNumber]) 00831 { 00832 /* Search for extended partitions */ 00833 for (j = NUM_PARTITION_TABLE_ENTRIES; j < LayoutArray[DiskNumber]->PartitionCount; j++) 00834 { 00835 if (IsRecognizedPartition(LayoutArray[DiskNumber]->PartitionEntry[j].PartitionType) && 00836 LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition == FALSE && 00837 LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber != 0) 00838 { 00839 swprintf(Buffer2, 00840 L"\\Device\\Harddisk%d\\Partition%d", 00841 DiskNumber, 00842 LayoutArray[DiskNumber]->PartitionEntry[j].PartitionNumber); 00843 RtlInitUnicodeString(&UnicodeString2, 00844 Buffer2); 00845 00846 /* Assign drive */ 00847 DPRINT(" %wZ\n", 00848 &UnicodeString2); 00849 HalpAssignDrive(&UnicodeString2, 00850 AUTO_DRIVE, 00851 DOSDEVICE_DRIVE_FIXED, 00852 LayoutArray[DiskNumber]->Signature, 00853 LayoutArray[DiskNumber]->PartitionEntry[j].StartingOffset, 00854 hKey, 00855 &BootDevice, 00856 NtSystemPath); 00857 /* Mark the partition as assigned */ 00858 LayoutArray[DiskNumber]->PartitionEntry[j].RewritePartition = TRUE; 00859 } 00860 } 00861 } 00862 } 00863 00864 /* Assign removable disk drives */ 00865 DPRINT("Assigning removable disk drives:\n"); 00866 for (i = 0; i < ConfigInfo->DiskCount; i++) 00867 { 00868 if (LayoutArray[i]) 00869 { 00870 /* Search for virtual partitions */ 00871 if (LayoutArray[i]->PartitionCount == 1 && 00872 LayoutArray[i]->PartitionEntry[0].PartitionType == 0) 00873 { 00874 swprintf(Buffer2, 00875 L"\\Device\\Harddisk%d\\Partition1", 00876 i); 00877 RtlInitUnicodeString(&UnicodeString2, 00878 Buffer2); 00879 00880 /* Assign drive */ 00881 DPRINT(" %wZ\n", 00882 &UnicodeString2); 00883 HalpAssignDrive(&UnicodeString2, 00884 AUTO_DRIVE, 00885 DOSDEVICE_DRIVE_REMOVABLE, 00886 0, 00887 RtlConvertLongToLargeInteger(0), 00888 hKey, 00889 &BootDevice, 00890 NtSystemPath); 00891 } 00892 } 00893 } 00894 00895 /* Free layout array */ 00896 for (i = 0; i < ConfigInfo->DiskCount; i++) 00897 { 00898 if (LayoutArray[i] != NULL) 00899 ExFreePoolWithTag(LayoutArray[i], TAG_FILE_SYSTEM); 00900 } 00901 ExFreePoolWithTag(LayoutArray, TAG_FILE_SYSTEM); 00902 end_assign_disks: 00903 00904 /* Assign floppy drives */ 00905 DPRINT("Floppy drives: %d\n", ConfigInfo->FloppyCount); 00906 for (i = 0; i < ConfigInfo->FloppyCount; i++) 00907 { 00908 swprintf(Buffer1, 00909 L"\\Device\\Floppy%d", 00910 i); 00911 RtlInitUnicodeString(&UnicodeString1, 00912 Buffer1); 00913 00914 /* Assign drive letters A: or B: or first free drive letter */ 00915 DPRINT(" %wZ\n", 00916 &UnicodeString1); 00917 HalpAssignDrive(&UnicodeString1, 00918 (i < 2) ? i : AUTO_DRIVE, 00919 DOSDEVICE_DRIVE_REMOVABLE, 00920 0, 00921 RtlConvertLongToLargeInteger(0), 00922 hKey, 00923 &BootDevice, 00924 NtSystemPath); 00925 } 00926 00927 /* Assign cdrom drives */ 00928 DPRINT("CD-Rom drives: %d\n", ConfigInfo->CdRomCount); 00929 for (i = 0; i < ConfigInfo->CdRomCount; i++) 00930 { 00931 swprintf(Buffer1, 00932 L"\\Device\\CdRom%d", 00933 i); 00934 RtlInitUnicodeString(&UnicodeString1, 00935 Buffer1); 00936 00937 /* Assign first free drive letter */ 00938 DPRINT(" %wZ\n", &UnicodeString1); 00939 HalpAssignDrive(&UnicodeString1, 00940 AUTO_DRIVE, 00941 DOSDEVICE_DRIVE_CDROM, 00942 0, 00943 RtlConvertLongToLargeInteger(0), 00944 hKey, 00945 &BootDevice, 00946 NtSystemPath); 00947 } 00948 00949 /* Anything else to do? */ 00950 00951 ExFreePoolWithTag(PartialInformation, TAG_FILE_SYSTEM); 00952 ExFreePoolWithTag(Buffer2, TAG_FILE_SYSTEM); 00953 ExFreePoolWithTag(Buffer1, TAG_FILE_SYSTEM); 00954 if (hKey) 00955 { 00956 ZwClose(hKey); 00957 } 00958 } 00959 00960 #endif 00961 00962 /* PRIVATE FUNCTIONS *********************************************************/ 00963 00964 NTSTATUS 00965 NTAPI 00966 HalpGetFullGeometry(IN PDEVICE_OBJECT DeviceObject, 00967 IN PDISK_GEOMETRY Geometry, 00968 OUT PULONGLONG RealSectorCount) 00969 { 00970 PIRP Irp; 00971 IO_STATUS_BLOCK IoStatusBlock; 00972 PKEVENT Event; 00973 NTSTATUS Status; 00974 PARTITION_INFORMATION PartitionInfo; 00975 PAGED_CODE(); 00976 00977 /* Allocate a non-paged event */ 00978 Event = ExAllocatePoolWithTag(NonPagedPool, 00979 sizeof(KEVENT), 00980 TAG_FILE_SYSTEM); 00981 if (!Event) return STATUS_INSUFFICIENT_RESOURCES; 00982 00983 /* Initialize it */ 00984 KeInitializeEvent(Event, NotificationEvent, FALSE); 00985 00986 /* Build the IRP */ 00987 Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY, 00988 DeviceObject, 00989 NULL, 00990 0UL, 00991 Geometry, 00992 sizeof(DISK_GEOMETRY), 00993 FALSE, 00994 Event, 00995 &IoStatusBlock); 00996 if (!Irp) 00997 { 00998 /* Fail, free the event */ 00999 ExFreePoolWithTag(Event, TAG_FILE_SYSTEM); 01000 return STATUS_INSUFFICIENT_RESOURCES; 01001 } 01002 01003 /* Call the driver and check if it's pending */ 01004 Status = IoCallDriver(DeviceObject, Irp); 01005 if (Status == STATUS_PENDING) 01006 { 01007 /* Wait on the driver */ 01008 KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL); 01009 Status = IoStatusBlock.Status; 01010 } 01011 01012 /* Check if the driver returned success */ 01013 if(NT_SUCCESS(Status)) 01014 { 01015 /* Build another IRP */ 01016 Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO, 01017 DeviceObject, 01018 NULL, 01019 0UL, 01020 &PartitionInfo, 01021 sizeof(PARTITION_INFORMATION), 01022 FALSE, 01023 Event, 01024 &IoStatusBlock); 01025 if (!Irp) 01026 { 01027 /* Fail, free the event */ 01028 ExFreePoolWithTag(Event, TAG_FILE_SYSTEM); 01029 return STATUS_INSUFFICIENT_RESOURCES; 01030 } 01031 01032 /* Call the driver and check if it's pending */ 01033 Status = IoCallDriver(DeviceObject, Irp); 01034 if (Status == STATUS_PENDING) 01035 { 01036 /* Wait on the driver */ 01037 KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL); 01038 Status = IoStatusBlock.Status; 01039 } 01040 01041 /* Check if the driver returned success */ 01042 if(NT_SUCCESS(Status)) 01043 { 01044 /* Get the number of sectors */ 01045 *RealSectorCount = (PartitionInfo.PartitionLength.QuadPart / 01046 Geometry->BytesPerSector); 01047 } 01048 } 01049 01050 /* Free the event and return the Status */ 01051 ExFreePoolWithTag(Event, TAG_FILE_SYSTEM); 01052 return Status; 01053 } 01054 01055 BOOLEAN 01056 NTAPI 01057 HalpIsValidPartitionEntry(IN PPARTITION_DESCRIPTOR Entry, 01058 IN ULONGLONG MaxOffset, 01059 IN ULONGLONG MaxSector) 01060 { 01061 ULONGLONG EndingSector; 01062 PAGED_CODE(); 01063 01064 /* Unused partitions are considered valid */ 01065 if (Entry->PartitionType == PARTITION_ENTRY_UNUSED) return TRUE; 01066 01067 /* Get the last sector of the partition */ 01068 EndingSector = GET_STARTING_SECTOR(Entry) + GET_PARTITION_LENGTH(Entry); 01069 01070 /* Check if it's more then the maximum sector */ 01071 if (EndingSector > MaxSector) 01072 { 01073 /* Invalid partition */ 01074 DPRINT1("FSTUB: entry is invalid\n"); 01075 DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry)); 01076 DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry)); 01077 DPRINT1("FSTUB: end %#I64x\n", EndingSector); 01078 DPRINT1("FSTUB: max %#I64x\n", MaxSector); 01079 return FALSE; 01080 } 01081 else if(GET_STARTING_SECTOR(Entry) > MaxOffset) 01082 { 01083 /* Invalid partition */ 01084 DPRINT1("FSTUB: entry is invalid\n"); 01085 DPRINT1("FSTUB: offset %#08lx\n", GET_STARTING_SECTOR(Entry)); 01086 DPRINT1("FSTUB: length %#08lx\n", GET_PARTITION_LENGTH(Entry)); 01087 DPRINT1("FSTUB: end %#I64x\n", EndingSector); 01088 DPRINT1("FSTUB: maxOffset %#I64x\n", MaxOffset); 01089 return FALSE; 01090 } 01091 01092 /* It's fine, return success */ 01093 return TRUE; 01094 } 01095 01096 VOID 01097 NTAPI 01098 HalpCalculateChsValues(IN PLARGE_INTEGER PartitionOffset, 01099 IN PLARGE_INTEGER PartitionLength, 01100 IN CCHAR ShiftCount, 01101 IN ULONG SectorsPerTrack, 01102 IN ULONG NumberOfTracks, 01103 IN ULONG ConventionalCylinders, 01104 OUT PPARTITION_DESCRIPTOR PartitionDescriptor) 01105 { 01106 LARGE_INTEGER FirstSector, SectorCount; 01107 ULONG LastSector, Remainder, SectorsPerCylinder; 01108 ULONG StartingCylinder, EndingCylinder; 01109 ULONG StartingTrack, EndingTrack; 01110 ULONG StartingSector, EndingSector; 01111 PAGED_CODE(); 01112 01113 /* Calculate the number of sectors for each cylinder */ 01114 SectorsPerCylinder = SectorsPerTrack * NumberOfTracks; 01115 01116 /* Calculate the first sector, and the sector count */ 01117 FirstSector.QuadPart = PartitionOffset->QuadPart >> ShiftCount; 01118 SectorCount.QuadPart = PartitionLength->QuadPart >> ShiftCount; 01119 01120 /* Now calculate the last sector */ 01121 LastSector = FirstSector.LowPart + SectorCount.LowPart - 1; 01122 01123 /* Calculate the first and last cylinders */ 01124 StartingCylinder = FirstSector.LowPart / SectorsPerCylinder; 01125 EndingCylinder = LastSector / SectorsPerCylinder; 01126 01127 /* Set the default number of cylinders */ 01128 if (!ConventionalCylinders) ConventionalCylinders = 1024; 01129 01130 /* Normalize the values */ 01131 if (StartingCylinder >= ConventionalCylinders) 01132 { 01133 /* Set the maximum to 1023 */ 01134 StartingCylinder = ConventionalCylinders - 1; 01135 } 01136 if (EndingCylinder >= ConventionalCylinders) 01137 { 01138 /* Set the maximum to 1023 */ 01139 EndingCylinder = ConventionalCylinders - 1; 01140 } 01141 01142 /* Calculate the starting head and sector that still remain */ 01143 Remainder = FirstSector.LowPart % SectorsPerCylinder; 01144 StartingTrack = Remainder / SectorsPerTrack; 01145 StartingSector = Remainder % SectorsPerTrack; 01146 01147 /* Calculate the ending head and sector that still remain */ 01148 Remainder = LastSector % SectorsPerCylinder; 01149 EndingTrack = Remainder / SectorsPerTrack; 01150 EndingSector = Remainder % SectorsPerTrack; 01151 01152 /* Set cylinder data for the MSB */ 01153 PartitionDescriptor->StartingCylinderMsb = (UCHAR)StartingCylinder; 01154 PartitionDescriptor->EndingCylinderMsb = (UCHAR)EndingCylinder; 01155 01156 /* Set the track data */ 01157 PartitionDescriptor->StartingTrack = (UCHAR)StartingTrack; 01158 PartitionDescriptor->EndingTrack = (UCHAR)EndingTrack; 01159 01160 /* Update cylinder data for the LSB */ 01161 StartingCylinder = ((StartingSector + 1) & 0x3F) | 01162 ((StartingCylinder >> 2) & 0xC0); 01163 EndingCylinder = ((EndingSector + 1) & 0x3F) | 01164 ((EndingCylinder >> 2) & 0xC0); 01165 01166 /* Set the cylinder data for the LSB */ 01167 PartitionDescriptor->StartingCylinderLsb = (UCHAR)StartingCylinder; 01168 PartitionDescriptor->EndingCylinderLsb = (UCHAR)EndingCylinder; 01169 } 01170 01171 VOID 01172 FASTCALL 01173 xHalGetPartialGeometry(IN PDEVICE_OBJECT DeviceObject, 01174 IN PULONG ConventionalCylinders, 01175 IN PLONGLONG DiskSize) 01176 { 01177 PDISK_GEOMETRY DiskGeometry = NULL; 01178 PIO_STATUS_BLOCK IoStatusBlock = NULL; 01179 PKEVENT Event = NULL; 01180 PIRP Irp; 01181 NTSTATUS Status; 01182 01183 /* Set defaults */ 01184 *ConventionalCylinders = 0; 01185 *DiskSize = 0; 01186 01187 /* Allocate the structure in nonpaged pool */ 01188 DiskGeometry = ExAllocatePoolWithTag(NonPagedPool, 01189 sizeof(DISK_GEOMETRY), 01190 TAG_FILE_SYSTEM); 01191 if (!DiskGeometry) goto Cleanup; 01192 01193 /* Allocate the status block in nonpaged pool */ 01194 IoStatusBlock = ExAllocatePoolWithTag(NonPagedPool, 01195 sizeof(IO_STATUS_BLOCK), 01196 TAG_FILE_SYSTEM); 01197 if (!IoStatusBlock) goto Cleanup; 01198 01199 /* Allocate the event in nonpaged pool too */ 01200 Event = ExAllocatePoolWithTag(NonPagedPool, 01201 sizeof(KEVENT), 01202 TAG_FILE_SYSTEM); 01203 if (!Event) goto Cleanup; 01204 01205 /* Initialize the event */ 01206 KeInitializeEvent(Event, NotificationEvent, FALSE); 01207 01208 /* Build the IRP */ 01209 Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY, 01210 DeviceObject, 01211 NULL, 01212 0, 01213 DiskGeometry, 01214 sizeof(DISK_GEOMETRY), 01215 FALSE, 01216 Event, 01217 IoStatusBlock); 01218 if (!Irp) goto Cleanup; 01219 01220 /* Now call the driver */ 01221 Status = IoCallDriver(DeviceObject, Irp); 01222 if (Status == STATUS_PENDING) 01223 { 01224 /* Wait for it to complete */ 01225 KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL); 01226 Status = IoStatusBlock->Status; 01227 } 01228 01229 /* Check driver status */ 01230 if (NT_SUCCESS(Status)) 01231 { 01232 /* Return the cylinder count */ 01233 *ConventionalCylinders = DiskGeometry->Cylinders.LowPart; 01234 01235 /* Make sure it's not larger then 1024 */ 01236 if (DiskGeometry->Cylinders.LowPart >= 1024) 01237 { 01238 /* Otherwise, normalize the value */ 01239 *ConventionalCylinders = 1024; 01240 } 01241 01242 /* Calculate the disk size */ 01243 *DiskSize = DiskGeometry->Cylinders.QuadPart * 01244 DiskGeometry->TracksPerCylinder * 01245 DiskGeometry->SectorsPerTrack * 01246 DiskGeometry->BytesPerSector; 01247 } 01248 01249 Cleanup: 01250 /* Free all the pointers */ 01251 if (Event) ExFreePoolWithTag(Event, TAG_FILE_SYSTEM); 01252 if (IoStatusBlock) ExFreePoolWithTag(IoStatusBlock, TAG_FILE_SYSTEM); 01253 if (DiskGeometry) ExFreePoolWithTag(DiskGeometry, TAG_FILE_SYSTEM); 01254 return; 01255 } 01256 01257 VOID 01258 FASTCALL 01259 xHalExamineMBR(IN PDEVICE_OBJECT DeviceObject, 01260 IN ULONG SectorSize, 01261 IN ULONG MbrTypeIdentifier, 01262 OUT PVOID *MbrBuffer) 01263 { 01264 LARGE_INTEGER Offset; 01265 PUCHAR Buffer; 01266 ULONG BufferSize; 01267 KEVENT Event; 01268 IO_STATUS_BLOCK IoStatusBlock; 01269 PIRP Irp; 01270 PPARTITION_DESCRIPTOR PartitionDescriptor; 01271 NTSTATUS Status; 01272 PIO_STACK_LOCATION IoStackLocation; 01273 Offset.QuadPart = 0; 01274 01275 /* Assume failure */ 01276 *MbrBuffer = NULL; 01277 01278 /* Normalize the buffer size */ 01279 BufferSize = max(SectorSize, 512); 01280 01281 /* Allocate the buffer */ 01282 Buffer = ExAllocatePoolWithTag(NonPagedPool, 01283 PAGE_SIZE > BufferSize ? 01284 PAGE_SIZE : BufferSize, 01285 TAG_FILE_SYSTEM); 01286 if (!Buffer) return; 01287 01288 /* Initialize the Event */ 01289 KeInitializeEvent(&Event, NotificationEvent, FALSE); 01290 01291 /* Build the IRP */ 01292 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, 01293 DeviceObject, 01294 Buffer, 01295 BufferSize, 01296 &Offset, 01297 &Event, 01298 &IoStatusBlock); 01299 if (!Irp) 01300 { 01301 /* Failed */ 01302 ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM); 01303 return; 01304 } 01305 01306 /* Make sure to override volume verification */ 01307 IoStackLocation = IoGetNextIrpStackLocation(Irp); 01308 IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 01309 01310 /* Call the driver */ 01311 Status = IoCallDriver(DeviceObject, Irp); 01312 if (Status == STATUS_PENDING) 01313 { 01314 /* Wait for completion */ 01315 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 01316 Status = IoStatusBlock.Status; 01317 } 01318 01319 /* Check driver Status */ 01320 if (NT_SUCCESS(Status)) 01321 { 01322 /* Validate the MBR Signature */ 01323 if (((PUSHORT)Buffer)[BOOT_SIGNATURE_OFFSET] != BOOT_RECORD_SIGNATURE) 01324 { 01325 /* Failed */ 01326 ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM); 01327 return; 01328 } 01329 01330 /* Get the partition entry */ 01331 PartitionDescriptor = (PPARTITION_DESCRIPTOR) 01332 &(((PUSHORT)Buffer)[PARTITION_TABLE_OFFSET]); 01333 01334 /* Make sure it's what the caller wanted */ 01335 if (PartitionDescriptor->PartitionType != MbrTypeIdentifier) 01336 { 01337 /* It's not, free our buffer */ 01338 ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM); 01339 } 01340 else 01341 { 01342 /* Check if this is a secondary entry */ 01343 if (PartitionDescriptor->PartitionType == 0x54) 01344 { 01345 /* Return our buffer, but at sector 63 */ 01346 *(PULONG)Buffer = 63; 01347 *MbrBuffer = Buffer; 01348 } 01349 else if (PartitionDescriptor->PartitionType == 0x55) 01350 { 01351 /* EZ Drive, return the buffer directly */ 01352 *MbrBuffer = Buffer; 01353 } 01354 else 01355 { 01356 /* Otherwise crash on debug builds */ 01357 ASSERT(PartitionDescriptor->PartitionType == 0x55); 01358 } 01359 } 01360 } 01361 } 01362 01363 VOID 01364 NTAPI 01365 FstubFixupEfiPartition(IN PPARTITION_DESCRIPTOR PartitionDescriptor, 01366 IN ULONGLONG MaxOffset) 01367 { 01368 ULONG PartitionMaxOffset, PartitionLength; 01369 PAGED_CODE(); 01370 01371 /* Compute partition length (according to MBR entry) */ 01372 PartitionMaxOffset = GET_STARTING_SECTOR(PartitionDescriptor) + GET_PARTITION_LENGTH(PartitionDescriptor); 01373 /* In case the partition length goes beyond disk size... */ 01374 if (PartitionMaxOffset > MaxOffset) 01375 { 01376 /* Resize partition to its maximum real length */ 01377 PartitionLength = (ULONG)(PartitionMaxOffset - GET_STARTING_SECTOR(PartitionDescriptor)); 01378 SET_PARTITION_LENGTH(PartitionDescriptor, PartitionLength); 01379 } 01380 } 01381 01382 NTSTATUS 01383 FASTCALL 01384 xHalIoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject, 01385 IN ULONG SectorSize, 01386 IN BOOLEAN ReturnRecognizedPartitions, 01387 IN OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer) 01388 { 01389 KEVENT Event; 01390 IO_STATUS_BLOCK IoStatusBlock; 01391 PIRP Irp; 01392 PPARTITION_DESCRIPTOR PartitionDescriptor; 01393 CCHAR Entry; 01394 NTSTATUS Status; 01395 PPARTITION_INFORMATION PartitionInfo; 01396 PUCHAR Buffer = NULL; 01397 ULONG BufferSize = 2048, InputSize; 01398 PDRIVE_LAYOUT_INFORMATION DriveLayoutInfo = NULL; 01399 LONG j = -1, i = -1, k; 01400 DISK_GEOMETRY DiskGeometry; 01401 LONGLONG EndSector, MaxSector, StartOffset; 01402 ULONGLONG MaxOffset; 01403 LARGE_INTEGER Offset, VolumeOffset; 01404 BOOLEAN IsPrimary = TRUE, IsEzDrive = FALSE, MbrFound = FALSE; 01405 BOOLEAN IsValid, IsEmpty = TRUE; 01406 PVOID MbrBuffer; 01407 PIO_STACK_LOCATION IoStackLocation; 01408 PBOOT_SECTOR_INFO BootSectorInfo = (PBOOT_SECTOR_INFO)Buffer; 01409 UCHAR PartitionType; 01410 LARGE_INTEGER HiddenSectors64; 01411 VolumeOffset.QuadPart = Offset.QuadPart = 0; 01412 PAGED_CODE(); 01413 01414 /* Allocate the buffer */ 01415 *PartitionBuffer = ExAllocatePoolWithTag(NonPagedPool, 01416 BufferSize, 01417 TAG_FILE_SYSTEM); 01418 if (!(*PartitionBuffer)) return STATUS_INSUFFICIENT_RESOURCES; 01419 01420 /* Normalize the buffer size */ 01421 InputSize = max(512, SectorSize); 01422 01423 /* Check for EZ Drive */ 01424 HalExamineMBR(DeviceObject, InputSize, 0x55, &MbrBuffer); 01425 if (MbrBuffer) 01426 { 01427 /* EZ Drive found, bias the offset */ 01428 IsEzDrive = TRUE; 01429 ExFreePoolWithTag(MbrBuffer, TAG_FILE_SYSTEM); 01430 Offset.QuadPart = 512; 01431 } 01432 01433 /* Get drive geometry */ 01434 Status = HalpGetFullGeometry(DeviceObject, &DiskGeometry, &MaxOffset); 01435 if (!NT_SUCCESS(Status)) 01436 { 01437 ExFreePoolWithTag(*PartitionBuffer, TAG_FILE_SYSTEM); 01438 *PartitionBuffer = NULL; 01439 return Status; 01440 } 01441 01442 /* Get the end and maximum sector */ 01443 EndSector = MaxOffset; 01444 MaxSector = MaxOffset << 1; 01445 DPRINT("FSTUB: MaxOffset = %#I64x, MaxSector = %#I64x\n", 01446 MaxOffset, MaxSector); 01447 01448 /* Allocate our buffer */ 01449 Buffer = ExAllocatePoolWithTag(NonPagedPool, InputSize, TAG_FILE_SYSTEM); 01450 if (!Buffer) 01451 { 01452 /* Fail, free the input buffer */ 01453 ExFreePoolWithTag(*PartitionBuffer, TAG_FILE_SYSTEM); 01454 *PartitionBuffer = NULL; 01455 return STATUS_INSUFFICIENT_RESOURCES; 01456 } 01457 01458 /* Start partition loop */ 01459 do 01460 { 01461 /* Assume the partition is valid */ 01462 IsValid = TRUE; 01463 01464 /* Initialize the event */ 01465 KeInitializeEvent(&Event, NotificationEvent, FALSE); 01466 01467 /* Clear the buffer and build the IRP */ 01468 RtlZeroMemory(Buffer, InputSize); 01469 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, 01470 DeviceObject, 01471 Buffer, 01472 InputSize, 01473 &Offset, 01474 &Event, 01475 &IoStatusBlock); 01476 if (!Irp) 01477 { 01478 /* Failed */ 01479 Status = STATUS_INSUFFICIENT_RESOURCES; 01480 break; 01481 } 01482 01483 /* Make sure to disable volume verification */ 01484 IoStackLocation = IoGetNextIrpStackLocation(Irp); 01485 IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 01486 01487 /* Call the driver */ 01488 Status = IoCallDriver(DeviceObject, Irp); 01489 if (Status == STATUS_PENDING) 01490 { 01491 /* Wait for completion */ 01492 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 01493 Status = IoStatusBlock.Status; 01494 } 01495 01496 /* Normalize status code and check for failure */ 01497 if (Status == STATUS_NO_DATA_DETECTED) Status = STATUS_SUCCESS; 01498 if (!NT_SUCCESS(Status)) break; 01499 01500 /* If we biased for EZ-Drive, unbias now */ 01501 if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0; 01502 01503 /* Make sure this is a valid MBR */ 01504 if (((PUSHORT)Buffer)[BOOT_SIGNATURE_OFFSET] != BOOT_RECORD_SIGNATURE) 01505 { 01506 /* It's not, fail */ 01507 DPRINT1("FSTUB: (IoReadPartitionTable) No 0xaa55 found in " 01508 "partition table %d\n", j + 1); 01509 break; 01510 } 01511 01512 /* At this point we have a valid MBR */ 01513 MbrFound = TRUE; 01514 01515 /* Check if we weren't given an offset */ 01516 if (!Offset.QuadPart) 01517 { 01518 /* Then read the signature off the disk */ 01519 (*PartitionBuffer)->Signature = ((PULONG)Buffer) 01520 [PARTITION_TABLE_OFFSET / 2 - 1]; 01521 } 01522 01523 /* Get the partition descriptor array */ 01524 PartitionDescriptor = (PPARTITION_DESCRIPTOR) 01525 &(((PUSHORT)Buffer)[PARTITION_TABLE_OFFSET]); 01526 01527 /* Start looping partitions */ 01528 j++; 01529 DPRINT("FSTUB: Partition Table %d:\n", j); 01530 for (Entry = 1, k = 0; Entry <= 4; Entry++, PartitionDescriptor++) 01531 { 01532 /* Get the partition type */ 01533 PartitionType = PartitionDescriptor->PartitionType; 01534 01535 /* Print debug messages */ 01536 DPRINT("Partition Entry %d,%d: type %#x %s\n", 01537 j, 01538 Entry, 01539 PartitionType, 01540 (PartitionDescriptor->ActiveFlag) ? "Active" : ""); 01541 DPRINT("\tOffset %#08lx for %#08lx Sectors\n", 01542 GET_STARTING_SECTOR(PartitionDescriptor), 01543 GET_PARTITION_LENGTH(PartitionDescriptor)); 01544 01545 /* Check whether we're facing a protective MBR */ 01546 if (PartitionType == EFI_PMBR_OSTYPE_EFI) 01547 { 01548 /* Partition length might be bigger than disk size */ 01549 FstubFixupEfiPartition(PartitionDescriptor, 01550 MaxOffset); 01551 } 01552 01553 /* Make sure that the partition is valid, unless it's the first */ 01554 if (!(HalpIsValidPartitionEntry(PartitionDescriptor, 01555 MaxOffset, 01556 MaxSector)) && !(j)) 01557 { 01558 /* It's invalid, so fail */ 01559 IsValid = FALSE; 01560 break; 01561 } 01562 01563 /* Check if it's a container */ 01564 if (IsContainerPartition(PartitionType)) 01565 { 01566 /* Increase the count of containers */ 01567 if (++k != 1) 01568 { 01569 /* More then one table is invalid */ 01570 DPRINT1("FSTUB: Multiple container partitions found in " 01571 "partition table %d\n - table is invalid\n", 01572 j); 01573 IsValid = FALSE; 01574 break; 01575 } 01576 } 01577 01578 /* Check if the partition is supposedly empty */ 01579 if (IsEmpty) 01580 { 01581 /* But check if it actually has a start and/or length */ 01582 if ((GET_STARTING_SECTOR(PartitionDescriptor)) || 01583 (GET_PARTITION_LENGTH(PartitionDescriptor))) 01584 { 01585 /* So then it's not really empty */ 01586 IsEmpty = FALSE; 01587 } 01588 } 01589 01590 /* Check if the caller wanted only recognized partitions */ 01591 if (ReturnRecognizedPartitions) 01592 { 01593 /* Then check if this one is unused, or a container */ 01594 if ((PartitionType == PARTITION_ENTRY_UNUSED) || 01595 IsContainerPartition(PartitionType)) 01596 { 01597 /* Skip it, since the caller doesn't want it */ 01598 continue; 01599 } 01600 } 01601 01602 /* Increase the structure count and check if they can fit */ 01603 if ((sizeof(DRIVE_LAYOUT_INFORMATION) + 01604 (++i * sizeof(PARTITION_INFORMATION))) > 01605 BufferSize) 01606 { 01607 /* Allocate a new buffer that's twice as big */ 01608 DriveLayoutInfo = ExAllocatePoolWithTag(NonPagedPool, 01609 BufferSize << 1, 01610 TAG_FILE_SYSTEM); 01611 if (!DriveLayoutInfo) 01612 { 01613 /* Out of memory, unto this extra structure */ 01614 --i; 01615 Status = STATUS_INSUFFICIENT_RESOURCES; 01616 break; 01617 } 01618 01619 /* Copy the contents of the old buffer */ 01620 RtlMoveMemory(DriveLayoutInfo, 01621 *PartitionBuffer, 01622 BufferSize); 01623 01624 /* Free the old buffer and set this one as the new one */ 01625 ExFreePoolWithTag(*PartitionBuffer, TAG_FILE_SYSTEM); 01626 *PartitionBuffer = DriveLayoutInfo; 01627 01628 /* Double the size */ 01629 BufferSize <<= 1; 01630 } 01631 01632 /* Now get the current structure being filled and initialize it */ 01633 PartitionInfo = &(*PartitionBuffer)->PartitionEntry[i]; 01634 PartitionInfo->PartitionType = PartitionType; 01635 PartitionInfo->RewritePartition = FALSE; 01636 01637 /* Check if we're dealing with a partition that's in use */ 01638 if (PartitionType != PARTITION_ENTRY_UNUSED) 01639 { 01640 /* Check if it's bootable */ 01641 PartitionInfo->BootIndicator = PartitionDescriptor-> 01642 ActiveFlag & 0x80 ? 01643 TRUE : FALSE; 01644 01645 /* Check if its' a container */ 01646 if (IsContainerPartition(PartitionType)) 01647 { 01648 /* Then don't recognize it and use the volume offset */ 01649 PartitionInfo->RecognizedPartition = FALSE; 01650 StartOffset = VolumeOffset.QuadPart; 01651 } 01652 else 01653 { 01654 /* Then recognize it and use the partition offset */ 01655 PartitionInfo->RecognizedPartition = TRUE; 01656 StartOffset = Offset.QuadPart; 01657 } 01658 01659 /* Get the starting offset */ 01660 PartitionInfo->StartingOffset.QuadPart = 01661 StartOffset + 01662 UInt32x32To64(GET_STARTING_SECTOR(PartitionDescriptor), 01663 SectorSize); 01664 01665 /* Calculate the number of hidden sectors */ 01666 HiddenSectors64.QuadPart = (PartitionInfo-> 01667 StartingOffset.QuadPart - 01668 StartOffset) / 01669 SectorSize; 01670 PartitionInfo->HiddenSectors = HiddenSectors64.LowPart; 01671 01672 /* Get the partition length */ 01673 PartitionInfo->PartitionLength.QuadPart = 01674 UInt32x32To64(GET_PARTITION_LENGTH(PartitionDescriptor), 01675 SectorSize); 01676 01677 /* FIXME: REACTOS HACK */ 01678 PartitionInfo->PartitionNumber = i + 1; 01679 } 01680 else 01681 { 01682 /* Otherwise, clear all the relevant fields */ 01683 PartitionInfo->BootIndicator = FALSE; 01684 PartitionInfo->RecognizedPartition = FALSE; 01685 PartitionInfo->StartingOffset.QuadPart = 0; 01686 PartitionInfo->PartitionLength.QuadPart = 0; 01687 PartitionInfo->HiddenSectors = 0; 01688 01689 /* FIXME: REACTOS HACK */ 01690 PartitionInfo->PartitionNumber = 0; 01691 } 01692 } 01693 01694 /* Finish debug log, and check for failure */ 01695 DPRINT("\n"); 01696 if (!NT_SUCCESS(Status)) break; 01697 01698 /* Also check if we hit an invalid entry here */ 01699 if (!IsValid) 01700 { 01701 /* We did, so break out of the loop minus one entry */ 01702 j--; 01703 break; 01704 } 01705 01706 /* Reset the offset */ 01707 Offset.QuadPart = 0; 01708 01709 /* Go back to the descriptor array and loop it */ 01710 PartitionDescriptor = (PPARTITION_DESCRIPTOR) 01711 &(((PUSHORT)Buffer)[PARTITION_TABLE_OFFSET]); 01712 for (Entry = 1; Entry <= 4; Entry++, PartitionDescriptor++) 01713 { 01714 /* Check if this is a container partition, since we skipped them */ 01715 if (IsContainerPartition(PartitionDescriptor->PartitionType)) 01716 { 01717 /* Get its offset */ 01718 Offset.QuadPart = VolumeOffset.QuadPart + 01719 UInt32x32To64( 01720 GET_STARTING_SECTOR(PartitionDescriptor), 01721 SectorSize); 01722 01723 /* If this is a primary partition, this is the volume offset */ 01724 if (IsPrimary) VolumeOffset = Offset; 01725 01726 /* Also update the maximum sector */ 01727 MaxSector = GET_PARTITION_LENGTH(PartitionDescriptor); 01728 DPRINT1("FSTUB: MaxSector now = %#08lx\n", MaxSector); 01729 break; 01730 } 01731 } 01732 01733 /* Loop the next partitions, which are not primary anymore */ 01734 IsPrimary = FALSE; 01735 } while (Offset.HighPart | Offset.LowPart); 01736 01737 /* Check if this is a removable device that's probably a super-floppy */ 01738 if ((DiskGeometry.MediaType == RemovableMedia) && 01739 !(j) && 01740 (MbrFound) && 01741 (IsEmpty)) 01742 { 01743 /* Read the jump bytes to detect super-floppy */ 01744 if ((BootSectorInfo->JumpByte[0] == 0xeb) || 01745 (BootSectorInfo->JumpByte[0] == 0xe9)) 01746 { 01747 /* Super floppes don't have typical MBRs, so skip them */ 01748 DPRINT1("FSTUB: Jump byte %#x found along with empty partition " 01749 "table - disk is a super floppy and has no valid MBR\n", 01750 BootSectorInfo->JumpByte); 01751 j = -1; 01752 } 01753 } 01754 01755 /* Check if we're still at partition -1 */ 01756 if (j == -1) 01757 { 01758 /* The likely cause is the super floppy detection above */ 01759 if ((MbrFound) || (DiskGeometry.MediaType == RemovableMedia)) 01760 { 01761 /* Print out debugging information */ 01762 DPRINT1("FSTUB: Drive %#p has no valid MBR. Make it into a " 01763 "super-floppy\n", 01764 DeviceObject); 01765 DPRINT1("FSTUB: Drive has %#08lx sectors and is %#016I64x " 01766 "bytes large\n", 01767 EndSector, EndSector * DiskGeometry.BytesPerSector); 01768 01769 /* We should at least have some sectors */ 01770 if (EndSector > 0) 01771 { 01772 /* Get the entry we'll use */ 01773 PartitionInfo = &(*PartitionBuffer)->PartitionEntry[0]; 01774 01775 /* Fill it out with data for a super-floppy */ 01776 PartitionInfo->RewritePartition = FALSE; 01777 PartitionInfo->RecognizedPartition = TRUE; 01778 PartitionInfo->PartitionType = PARTITION_FAT_16; 01779 PartitionInfo->BootIndicator = FALSE; 01780 PartitionInfo->HiddenSectors = 0; 01781 PartitionInfo->StartingOffset.QuadPart = 0; 01782 PartitionInfo->PartitionLength.QuadPart = (EndSector * 01783 DiskGeometry. 01784 BytesPerSector); 01785 01786 /* FIXME: REACTOS HACK */ 01787 PartitionInfo->PartitionNumber = 0; 01788 01789 /* Set the signature and set the count back to 0 */ 01790 (*PartitionBuffer)->Signature = 1; 01791 i = 0; 01792 } 01793 } 01794 else 01795 { 01796 /* Otherwise, this isn't a super floppy, so set an invalid count */ 01797 i = -1; 01798 } 01799 } 01800 01801 /* Set the partition count */ 01802 (*PartitionBuffer)->PartitionCount = ++i; 01803 01804 /* If we have no count, delete the signature */ 01805 if (!i) (*PartitionBuffer)->Signature = 0; 01806 01807 /* Free the buffer and check for success */ 01808 if (Buffer) ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM); 01809 if (!NT_SUCCESS(Status)) ExFreePoolWithTag(*PartitionBuffer, TAG_FILE_SYSTEM); 01810 01811 /* Return status */ 01812 return Status; 01813 } 01814 01815 NTSTATUS 01816 FASTCALL 01817 xHalIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject, 01818 IN ULONG SectorSize, 01819 IN ULONG PartitionNumber, 01820 IN ULONG PartitionType) 01821 { 01822 PIRP Irp; 01823 KEVENT Event; 01824 IO_STATUS_BLOCK IoStatusBlock; 01825 NTSTATUS Status; 01826 LARGE_INTEGER Offset, VolumeOffset; 01827 PUCHAR Buffer = NULL; 01828 ULONG BufferSize; 01829 ULONG i = 0; 01830 ULONG Entry; 01831 PPARTITION_DESCRIPTOR PartitionDescriptor; 01832 BOOLEAN IsPrimary = TRUE, IsEzDrive = FALSE; 01833 PVOID MbrBuffer; 01834 PIO_STACK_LOCATION IoStackLocation; 01835 VolumeOffset.QuadPart = Offset.QuadPart = 0; 01836 PAGED_CODE(); 01837 01838 /* Normalize the buffer size */ 01839 BufferSize = max(512, SectorSize); 01840 01841 /* Check for EZ Drive */ 01842 HalExamineMBR(DeviceObject, BufferSize, 0x55, &MbrBuffer); 01843 if (MbrBuffer) 01844 { 01845 /* EZ Drive found, bias the offset */ 01846 IsEzDrive = TRUE; 01847 ExFreePoolWithTag(MbrBuffer, TAG_FILE_SYSTEM); 01848 Offset.QuadPart = 512; 01849 } 01850 01851 /* Allocate our partition buffer */ 01852 Buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, TAG_FILE_SYSTEM); 01853 if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES; 01854 01855 /* Initialize the event we'll use and loop partitions */ 01856 KeInitializeEvent(&Event, NotificationEvent, FALSE); 01857 do 01858 { 01859 /* Reset the event since we reuse it */ 01860 KeResetEvent(&Event); 01861 01862 /* Build the read IRP */ 01863 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, 01864 DeviceObject, 01865 Buffer, 01866 BufferSize, 01867 &Offset, 01868 &Event, 01869 &IoStatusBlock); 01870 if (!Irp) 01871 { 01872 /* Fail */ 01873 Status = STATUS_INSUFFICIENT_RESOURCES; 01874 break; 01875 } 01876 01877 /* Make sure to disable volume verification */ 01878 IoStackLocation = IoGetNextIrpStackLocation(Irp); 01879 IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 01880 01881 /* Call the driver */ 01882 Status = IoCallDriver(DeviceObject, Irp); 01883 if (Status == STATUS_PENDING) 01884 { 01885 /* Wait for completion */ 01886 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 01887 Status = IoStatusBlock.Status; 01888 } 01889 01890 /* Check for failure */ 01891 if (!NT_SUCCESS(Status)) break; 01892 01893 /* If we biased for EZ-Drive, unbias now */ 01894 if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0; 01895 01896 /* Make sure this is a valid MBR */ 01897 if (((PUSHORT)Buffer)[BOOT_SIGNATURE_OFFSET] != BOOT_RECORD_SIGNATURE) 01898 { 01899 /* It's not, fail */ 01900 Status = STATUS_BAD_MASTER_BOOT_RECORD; 01901 break; 01902 } 01903 01904 /* Get the partition descriptors and loop them */ 01905 PartitionDescriptor = (PPARTITION_DESCRIPTOR) 01906 &(((PUSHORT)Buffer)[PARTITION_TABLE_OFFSET]); 01907 for (Entry = 1; Entry <= 4; Entry++, PartitionDescriptor++) 01908 { 01909 /* Check if it's unused or a container partition */ 01910 if ((PartitionDescriptor->PartitionType == 01911 PARTITION_ENTRY_UNUSED) || 01912 (IsContainerPartition(PartitionDescriptor->PartitionType))) 01913 { 01914 /* Go to the next one */ 01915 continue; 01916 } 01917 01918 /* It's a valid partition, so increase the partition count */ 01919 if (++i == PartitionNumber) 01920 { 01921 /* We found a match, set the type */ 01922 PartitionDescriptor->PartitionType = (UCHAR)PartitionType; 01923 01924 /* Reset the reusable event */ 01925 KeResetEvent(&Event); 01926 01927 /* Build the write IRP */ 01928 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE, 01929 DeviceObject, 01930 Buffer, 01931 BufferSize, 01932 &Offset, 01933 &Event, 01934 &IoStatusBlock); 01935 if (!Irp) 01936 { 01937 /* Fail */ 01938 Status = STATUS_INSUFFICIENT_RESOURCES; 01939 break; 01940 } 01941 01942 /* Disable volume verification */ 01943 IoStackLocation = IoGetNextIrpStackLocation(Irp); 01944 IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 01945 01946 /* Call the driver */ 01947 Status = IoCallDriver(DeviceObject, Irp); 01948 if (Status == STATUS_PENDING) 01949 { 01950 /* Wait for completion */ 01951 KeWaitForSingleObject(&Event, 01952 Executive, 01953 KernelMode, 01954 FALSE, 01955 NULL); 01956 Status = IoStatusBlock.Status; 01957 } 01958 01959 /* We're done, break out of the loop */ 01960 break; 01961 } 01962 } 01963 01964 /* If we looped all the partitions, break out */ 01965 if (Entry <= NUM_PARTITION_TABLE_ENTRIES) break; 01966 01967 /* Nothing found yet, get the partition array again */ 01968 PartitionDescriptor = (PPARTITION_DESCRIPTOR) 01969 &(((PUSHORT)Buffer)[PARTITION_TABLE_OFFSET]); 01970 for (Entry = 1; Entry <= 4; Entry++, PartitionDescriptor++) 01971 { 01972 /* Check if this was a container partition (we skipped these) */ 01973 if (IsContainerPartition(PartitionDescriptor->PartitionType)) 01974 { 01975 /* Update the partition offset */ 01976 Offset.QuadPart = VolumeOffset.QuadPart + 01977 GET_STARTING_SECTOR(PartitionDescriptor) * 01978 SectorSize; 01979 01980 /* If this was the primary partition, update the volume too */ 01981 if (IsPrimary) VolumeOffset = Offset; 01982 break; 01983 } 01984 } 01985 01986 /* Check if we already searched all the partitions */ 01987 if (Entry > NUM_PARTITION_TABLE_ENTRIES) 01988 { 01989 /* Then we failed to find a good MBR */ 01990 Status = STATUS_BAD_MASTER_BOOT_RECORD; 01991 break; 01992 } 01993 01994 /* Loop the next partitions, which are not primary anymore */ 01995 IsPrimary = FALSE; 01996 } while (i < PartitionNumber); 01997 01998 /* Everything done, cleanup */ 01999 if (Buffer) ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM); 02000 return Status; 02001 } 02002 02003 NTSTATUS 02004 FASTCALL 02005 xHalIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject, 02006 IN ULONG SectorSize, 02007 IN ULONG SectorsPerTrack, 02008 IN ULONG NumberOfHeads, 02009 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer) 02010 { 02011 KEVENT Event; 02012 IO_STATUS_BLOCK IoStatusBlock; 02013 PIRP Irp; 02014 NTSTATUS Status = STATUS_SUCCESS; 02015 ULONG BufferSize; 02016 PUSHORT Buffer; 02017 PPTE Entry; 02018 PPARTITION_TABLE PartitionTable; 02019 LARGE_INTEGER Offset, NextOffset, ExtendedOffset, SectorOffset; 02020 LARGE_INTEGER StartOffset, PartitionLength; 02021 ULONG i, j; 02022 CCHAR k; 02023 BOOLEAN IsEzDrive = FALSE, IsSuperFloppy = FALSE, DoRewrite = FALSE, IsMbr; 02024 ULONG ConventionalCylinders; 02025 LONGLONG DiskSize; 02026 PDISK_LAYOUT DiskLayout = (PDISK_LAYOUT)PartitionBuffer; 02027 PVOID MbrBuffer; 02028 UCHAR PartitionType; 02029 PIO_STACK_LOCATION IoStackLocation; 02030 PPARTITION_INFORMATION PartitionInfo = PartitionBuffer->PartitionEntry; 02031 PPARTITION_INFORMATION TableEntry; 02032 ExtendedOffset.QuadPart = NextOffset.QuadPart = Offset.QuadPart = 0; 02033 PAGED_CODE(); 02034 02035 /* Normalize the buffer size */ 02036 BufferSize = max(512, SectorSize); 02037 02038 /* Get the partial drive geometry */ 02039 xHalGetPartialGeometry(DeviceObject, &ConventionalCylinders, &DiskSize); 02040 02041 /* Check for EZ Drive */ 02042 HalExamineMBR(DeviceObject, BufferSize, 0x55, &MbrBuffer); 02043 if (MbrBuffer) 02044 { 02045 /* EZ Drive found, bias the offset */ 02046 IsEzDrive = TRUE; 02047 ExFreePoolWithTag(MbrBuffer, TAG_FILE_SYSTEM); 02048 Offset.QuadPart = 512; 02049 } 02050 02051 /* Get the number of bits to shift to multiply by the sector size */ 02052 for (k = 0; k < 32; k++) if ((SectorSize >> k) == 1) break; 02053 02054 /* Check if there's only one partition */ 02055 if (PartitionBuffer->PartitionCount == 1) 02056 { 02057 /* Check if it has no starting offset or hidden sectors */ 02058 if (!(PartitionInfo->StartingOffset.QuadPart) && 02059 !(PartitionInfo->HiddenSectors)) 02060 { 02061 /* Then it's a super floppy */ 02062 IsSuperFloppy = TRUE; 02063 02064 /* Which also means it must be non-bootable FAT-16 */ 02065 if ((PartitionInfo->PartitionNumber) || 02066 (PartitionInfo->PartitionType != PARTITION_FAT_16) || 02067 (PartitionInfo->BootIndicator)) 02068 { 02069 /* It's not, so we fail */ 02070 return STATUS_INVALID_PARAMETER; 02071 } 02072 02073 /* Check if it needs a rewrite, and disable EZ drive for sure */ 02074 if (PartitionInfo->RewritePartition) DoRewrite = TRUE; 02075 IsEzDrive = FALSE; 02076 } 02077 } 02078 02079 /* Count the number of partition tables */ 02080 DiskLayout->TableCount = (PartitionBuffer->PartitionCount + 4 - 1) / 4; 02081 02082 /* Allocate our partition buffer */ 02083 Buffer = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, TAG_FILE_SYSTEM); 02084 if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES; 02085 02086 /* Loop the entries */ 02087 Entry = (PPTE)&Buffer[PARTITION_TABLE_OFFSET]; 02088 for (i = 0; i < DiskLayout->TableCount; i++) 02089 { 02090 /* Set if this is the MBR partition */ 02091 IsMbr= (BOOLEAN)!i; 02092 02093 /* Initialize th event */ 02094 KeInitializeEvent(&Event, NotificationEvent, FALSE); 02095 02096 /* Build the read IRP */ 02097 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, 02098 DeviceObject, 02099 Buffer, 02100 BufferSize, 02101 &Offset, 02102 &Event, 02103 &IoStatusBlock); 02104 if (!Irp) 02105 { 02106 /* Fail */ 02107 Status = STATUS_INSUFFICIENT_RESOURCES; 02108 break; 02109 } 02110 02111 /* Make sure to disable volume verification */ 02112 IoStackLocation = IoGetNextIrpStackLocation(Irp); 02113 IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 02114 02115 /* Call the driver */ 02116 Status = IoCallDriver(DeviceObject, Irp); 02117 if (Status == STATUS_PENDING) 02118 { 02119 /* Wait for completion */ 02120 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 02121 Status = IoStatusBlock.Status; 02122 } 02123 02124 /* Check for failure */ 02125 if (!NT_SUCCESS(Status)) break; 02126 02127 /* If we biased for EZ-Drive, unbias now */ 02128 if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0; 02129 02130 /* Check if this is a normal disk */ 02131 if (!IsSuperFloppy) 02132 { 02133 /* Set the boot record signature */ 02134 Buffer[BOOT_SIGNATURE_OFFSET] = BOOT_RECORD_SIGNATURE; 02135 02136 /* By default, don't require a rewrite */ 02137 DoRewrite = FALSE; 02138 02139 /* Check if we don't have an offset */ 02140 if (!Offset.QuadPart) 02141 { 02142 /* Check if the signature doesn't match */ 02143 if (((PULONG)Buffer)[PARTITION_TABLE_OFFSET / 2 - 1] != 02144 PartitionBuffer->Signature) 02145 { 02146 /* Then write the signature and now w need a rewrite */ 02147 ((PULONG)Buffer)[PARTITION_TABLE_OFFSET / 2 - 1] = 02148 PartitionBuffer->Signature; 02149 DoRewrite = TRUE; 02150 } 02151 } 02152 02153 /* Loop the partition table entries */ 02154 PartitionTable = &DiskLayout->PartitionTable[i]; 02155 for (j = 0; j < 4; j++) 02156 { 02157 /* Get the current entry and type */ 02158 TableEntry = &PartitionTable->PartitionEntry[j]; 02159 PartitionType = TableEntry->PartitionType; 02160 02161 /* Check if the entry needs a rewrite */ 02162 if (TableEntry->RewritePartition) 02163 { 02164 /* Then we need one too */ 02165 DoRewrite = TRUE; 02166 02167 /* Save the type and if it's a bootable partition */ 02168 Entry[j].PartitionType = TableEntry->PartitionType; 02169 Entry[j].ActiveFlag = TableEntry->BootIndicator ? 0x80 : 0; 02170 02171 /* Make sure it's used */ 02172 if (PartitionType != PARTITION_ENTRY_UNUSED) 02173 { 02174 /* Make sure it's not a container (unless primary) */ 02175 if ((IsMbr) || !(IsContainerPartition(PartitionType))) 02176 { 02177 /* Use the partition offset */ 02178 StartOffset.QuadPart = Offset.QuadPart; 02179 } 02180 else 02181 { 02182 /* Use the extended logical partition offset */ 02183 StartOffset.QuadPart = ExtendedOffset.QuadPart; 02184 } 02185 02186 /* Set the sector offset */ 02187 SectorOffset.QuadPart = TableEntry-> 02188 StartingOffset.QuadPart - 02189 StartOffset.QuadPart; 02190 02191 /* Now calculate the starting sector */ 02192 StartOffset.QuadPart = SectorOffset.QuadPart >> k; 02193 Entry[j].StartingSector = StartOffset.LowPart; 02194 02195 /* As well as the length */ 02196 PartitionLength.QuadPart = TableEntry->PartitionLength. 02197 QuadPart >> k; 02198 Entry[j].PartitionLength = PartitionLength.LowPart; 02199 02200 /* Calculate the CHS values */ 02201 HalpCalculateChsValues(&TableEntry->StartingOffset, 02202 &TableEntry->PartitionLength, 02203 k, 02204 SectorsPerTrack, 02205 NumberOfHeads, 02206 ConventionalCylinders, 02207 (PPARTITION_DESCRIPTOR) 02208 &Entry[j]); 02209 } 02210 else 02211 { 02212 /* Otherwise set up an empty entry */ 02213 Entry[j].StartingSector = 0; 02214 Entry[j].PartitionLength = 0; 02215 Entry[j].StartingTrack = 0; 02216 Entry[j].EndingTrack = 0; 02217 Entry[j].StartingCylinder = 0; 02218 Entry[j].EndingCylinder = 0; 02219 } 02220 } 02221 02222 /* Check if this is a container partition */ 02223 if (IsContainerPartition(PartitionType)) 02224 { 02225 /* Then update the offset to use */ 02226 NextOffset = TableEntry->StartingOffset; 02227 } 02228 } 02229 } 02230 02231 /* Check if we need to write back the buffer */ 02232 if (DoRewrite) 02233 { 02234 /* We don't need to do this again */ 02235 DoRewrite = FALSE; 02236 02237 /* Initialize the event */ 02238 KeInitializeEvent(&Event, NotificationEvent, FALSE); 02239 02240 /* If we unbiased for EZ-Drive, rebias now */ 02241 if ((IsEzDrive) && !(Offset.QuadPart)) Offset.QuadPart = 512; 02242 02243 /* Build the write IRP */ 02244 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE, 02245 DeviceObject, 02246 Buffer, 02247 BufferSize, 02248 &Offset, 02249 &Event, 02250 &IoStatusBlock); 02251 if (!Irp) 02252 { 02253 /* Fail */ 02254 Status = STATUS_INSUFFICIENT_RESOURCES; 02255 break; 02256 } 02257 02258 /* Make sure to disable volume verification */ 02259 IoStackLocation = IoGetNextIrpStackLocation(Irp); 02260 IoStackLocation->Flags |= SL_OVERRIDE_VERIFY_VOLUME; 02261 02262 /* Call the driver */ 02263 Status = IoCallDriver(DeviceObject, Irp); 02264 if (Status == STATUS_PENDING) 02265 { 02266 /* Wait for completion */ 02267 KeWaitForSingleObject(&Event, 02268 Executive, 02269 KernelMode, 02270 FALSE, 02271 NULL); 02272 Status = IoStatusBlock.Status; 02273 } 02274 02275 /* Check for failure */ 02276 if (!NT_SUCCESS(Status)) break; 02277 02278 /* If we biased for EZ-Drive, unbias now */ 02279 if (IsEzDrive && (Offset.QuadPart == 512)) Offset.QuadPart = 0; 02280 } 02281 02282 /* Update the partition offset and set the extended offset if needed */ 02283 Offset = NextOffset; 02284 if (IsMbr) ExtendedOffset = NextOffset; 02285 } 02286 02287 /* If we had a buffer, free it, then return status */ 02288 if (Buffer) ExFreePoolWithTag(Buffer, TAG_FILE_SYSTEM); 02289 return Status; 02290 } 02291 02292 /* PUBLIC FUNCTIONS **********************************************************/ 02293 02294 /* 02295 * @implemented 02296 */ 02297 VOID 02298 FASTCALL 02299 HalExamineMBR(IN PDEVICE_OBJECT DeviceObject, 02300 IN ULONG SectorSize, 02301 IN ULONG MbrTypeIdentifier, 02302 OUT PVOID *MbrBuffer) 02303 { 02304 HALDISPATCH->HalExamineMBR(DeviceObject, 02305 SectorSize, 02306 MbrTypeIdentifier, 02307 MbrBuffer); 02308 } 02309 02310 /* 02311 * @implemented 02312 */ 02313 NTSTATUS 02314 FASTCALL 02315 IoReadPartitionTable(IN PDEVICE_OBJECT DeviceObject, 02316 IN ULONG SectorSize, 02317 IN BOOLEAN ReturnRecognizedPartitions, 02318 IN OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer) 02319 { 02320 return HALDISPATCH->HalIoReadPartitionTable(DeviceObject, 02321 SectorSize, 02322 ReturnRecognizedPartitions, 02323 PartitionBuffer); 02324 } 02325 02326 /* 02327 * @implemented 02328 */ 02329 NTSTATUS 02330 FASTCALL 02331 IoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject, 02332 IN ULONG SectorSize, 02333 IN ULONG PartitionNumber, 02334 IN ULONG PartitionType) 02335 { 02336 return HALDISPATCH->HalIoSetPartitionInformation(DeviceObject, 02337 SectorSize, 02338 PartitionNumber, 02339 PartitionType); 02340 } 02341 02342 /* 02343 * @implemented 02344 */ 02345 NTSTATUS 02346 FASTCALL 02347 IoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject, 02348 IN ULONG SectorSize, 02349 IN ULONG SectorsPerTrack, 02350 IN ULONG NumberOfHeads, 02351 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer) 02352 { 02353 return HALDISPATCH->HalIoWritePartitionTable(DeviceObject, 02354 SectorSize, 02355 SectorsPerTrack, 02356 NumberOfHeads, 02357 PartitionBuffer); 02358 } 02359 02360 /* 02361 * @implemented 02362 */ 02363 VOID 02364 FASTCALL 02365 IoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock, 02366 IN PSTRING NtDeviceName, 02367 OUT PUCHAR NtSystemPath, 02368 OUT PSTRING NtSystemPathString) 02369 { 02370 HALDISPATCH->HalIoAssignDriveLetters(LoaderBlock, 02371 NtDeviceName, 02372 NtSystemPath, 02373 NtSystemPathString); 02374 } 02375 02376 /* EOF */ Generated on Mon May 28 2012 04:37:07 for ReactOS by
1.7.6.1
|