1 /* 2 * PROJECT: Partition manager driver 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Partition device code 5 * COPYRIGHT: 2020 Victor Perevertkin (victor.perevertkin@reactos.org) 6 */ 7 8 #include "partmgr.h" 9 10 static const WCHAR PartitionSymLinkFormat[] = L"\\Device\\Harddisk%u\\Partition%u"; 11 12 13 CODE_SEG("PAGE") 14 NTSTATUS 15 PartitionCreateDevice( 16 _In_ PDEVICE_OBJECT FDObject, 17 _In_ PPARTITION_INFORMATION_EX PartitionEntry, 18 _In_ UINT32 PdoNumber, 19 _In_ PARTITION_STYLE PartitionStyle, 20 _Out_ PDEVICE_OBJECT *PDO) 21 { 22 PAGED_CODE(); 23 24 static UINT32 HarddiskVolumeNextId = 1; // this is 1-based 25 26 WCHAR nameBuf[64]; 27 UNICODE_STRING deviceName; 28 29 // create the device object 30 31 swprintf(nameBuf, L"\\Device\\HarddiskVolume%u", HarddiskVolumeNextId++); 32 RtlCreateUnicodeString(&deviceName, nameBuf); 33 34 PDEVICE_OBJECT partitionDevice; 35 NTSTATUS status = IoCreateDevice(FDObject->DriverObject, 36 sizeof(PARTITION_EXTENSION), 37 &deviceName, 38 FILE_DEVICE_DISK, 39 FILE_DEVICE_SECURE_OPEN, 40 FALSE, 41 &partitionDevice); 42 43 if (!NT_SUCCESS(status)) 44 { 45 ERR("Unable to create device object %wZ\n", &deviceName); 46 return status; 47 } 48 49 INFO("Created device object %p %wZ\n", partitionDevice, &deviceName); 50 51 PPARTITION_EXTENSION partExt = partitionDevice->DeviceExtension; 52 RtlZeroMemory(partExt, sizeof(*partExt)); 53 54 partitionDevice->StackSize = FDObject->StackSize; 55 partitionDevice->Flags |= DO_DIRECT_IO; 56 57 if (PartitionStyle == PARTITION_STYLE_MBR) 58 { 59 partExt->Mbr.PartitionType = PartitionEntry->Mbr.PartitionType; 60 partExt->Mbr.BootIndicator = PartitionEntry->Mbr.BootIndicator; 61 partExt->Mbr.HiddenSectors = PartitionEntry->Mbr.HiddenSectors; 62 } 63 else 64 { 65 partExt->Gpt.PartitionType = PartitionEntry->Gpt.PartitionType; 66 partExt->Gpt.PartitionId = PartitionEntry->Gpt.PartitionType; 67 partExt->Gpt.Attributes = PartitionEntry->Gpt.Attributes; 68 69 RtlCopyMemory(partExt->Gpt.Name, PartitionEntry->Gpt.Name, sizeof(partExt->Gpt.Name)); 70 } 71 72 partExt->DeviceName = deviceName; 73 partExt->StartingOffset = PartitionEntry->StartingOffset.QuadPart; 74 partExt->PartitionLength = PartitionEntry->PartitionLength.QuadPart; 75 partExt->OnDiskNumber = PartitionEntry->PartitionNumber; // the "physical" partition number 76 partExt->DetectedNumber = PdoNumber; // counts only partitions with PDO created 77 78 partExt->DeviceObject = partitionDevice; 79 partExt->LowerDevice = FDObject; 80 81 partitionDevice->Flags &= ~DO_DEVICE_INITIALIZING; 82 83 *PDO = partitionDevice; 84 85 return status; 86 } 87 88 static 89 CODE_SEG("PAGE") 90 NTSTATUS 91 PartitionHandleStartDevice( 92 _In_ PPARTITION_EXTENSION PartExt, 93 _In_ PIRP Irp) 94 { 95 PAGED_CODE(); 96 97 // fix the damn kernel! 98 if (PartExt->DeviceRemoved) 99 { 100 DPRINT1("IRP_MN_START_DEVICE after IRP_MN_REMOVE_DEVICE!\n"); 101 return STATUS_SUCCESS; 102 } 103 104 // first, create a symbolic link for our device 105 WCHAR nameBuf[64]; 106 UNICODE_STRING partitionSymlink, interfaceName; 107 PFDO_EXTENSION fdoExtension = PartExt->LowerDevice->DeviceExtension; 108 109 // \\Device\\Harddisk%u\\Partition%u 110 swprintf(nameBuf, PartitionSymLinkFormat, 111 fdoExtension->DiskData.DeviceNumber, PartExt->DetectedNumber); 112 113 if (!RtlCreateUnicodeString(&partitionSymlink, nameBuf)) 114 { 115 return STATUS_INSUFFICIENT_RESOURCES; 116 } 117 118 NTSTATUS status = IoCreateSymbolicLink(&partitionSymlink, &PartExt->DeviceName); 119 120 if (!NT_SUCCESS(status)) 121 { 122 return status; 123 } 124 125 PartExt->SymlinkCreated = TRUE; 126 127 TRACE("Symlink created %wZ -> %wZ\n", &PartExt->DeviceName, &partitionSymlink); 128 129 // our partition device will have two interfaces: 130 // GUID_DEVINTERFACE_PARTITION and GUID_DEVINTERFACE_VOLUME 131 // the former one is used to notify mountmgr about new device 132 133 status = IoRegisterDeviceInterface(PartExt->DeviceObject, 134 &GUID_DEVINTERFACE_PARTITION, 135 NULL, 136 &interfaceName); 137 138 if (!NT_SUCCESS(status)) 139 { 140 return status; 141 } 142 143 PartExt->PartitionInterfaceName = interfaceName; 144 status = IoSetDeviceInterfaceState(&interfaceName, TRUE); 145 146 INFO("Partition interface %wZ\n", &interfaceName); 147 148 if (!NT_SUCCESS(status)) 149 { 150 RtlFreeUnicodeString(&interfaceName); 151 RtlInitUnicodeString(&PartExt->PartitionInterfaceName, NULL); 152 return status; 153 } 154 155 status = IoRegisterDeviceInterface(PartExt->DeviceObject, 156 &GUID_DEVINTERFACE_VOLUME, 157 NULL, 158 &interfaceName); 159 160 if (!NT_SUCCESS(status)) 161 { 162 return status; 163 } 164 165 PartExt->VolumeInterfaceName = interfaceName; 166 status = IoSetDeviceInterfaceState(&interfaceName, TRUE); 167 168 INFO("Volume interface %wZ\n", &interfaceName); 169 170 if (!NT_SUCCESS(status)) 171 { 172 RtlFreeUnicodeString(&interfaceName); 173 RtlInitUnicodeString(&PartExt->VolumeInterfaceName, NULL); 174 return status; 175 } 176 177 return STATUS_SUCCESS; 178 } 179 180 CODE_SEG("PAGE") 181 NTSTATUS 182 PartitionHandleRemove( 183 _In_ PPARTITION_EXTENSION PartExt, 184 _In_ BOOLEAN FinalRemove) 185 { 186 NTSTATUS status; 187 188 PAGED_CODE(); 189 190 // remove the symbolic link 191 if (PartExt->SymlinkCreated) 192 { 193 WCHAR nameBuf[64]; 194 UNICODE_STRING partitionSymlink; 195 PFDO_EXTENSION fdoExtension = PartExt->LowerDevice->DeviceExtension; 196 197 swprintf(nameBuf, PartitionSymLinkFormat, 198 fdoExtension->DiskData.DeviceNumber, PartExt->DetectedNumber); 199 200 RtlInitUnicodeString(&partitionSymlink, nameBuf); 201 202 status = IoDeleteSymbolicLink(&partitionSymlink); 203 204 if (!NT_SUCCESS(status)) 205 { 206 return status; 207 } 208 PartExt->SymlinkCreated = FALSE; 209 210 INFO("Symlink removed %wZ -> %wZ\n", &PartExt->DeviceName, &partitionSymlink); 211 } 212 213 // release device interfaces 214 if (PartExt->PartitionInterfaceName.Buffer) 215 { 216 status = IoSetDeviceInterfaceState(&PartExt->PartitionInterfaceName, FALSE); 217 if (!NT_SUCCESS(status)) 218 { 219 return status; 220 } 221 RtlFreeUnicodeString(&PartExt->PartitionInterfaceName); 222 RtlInitUnicodeString(&PartExt->PartitionInterfaceName, NULL); 223 } 224 225 if (PartExt->VolumeInterfaceName.Buffer) 226 { 227 status = IoSetDeviceInterfaceState(&PartExt->VolumeInterfaceName, FALSE); 228 if (!NT_SUCCESS(status)) 229 { 230 return status; 231 } 232 RtlFreeUnicodeString(&PartExt->VolumeInterfaceName); 233 RtlInitUnicodeString(&PartExt->VolumeInterfaceName, NULL); 234 } 235 236 if (FinalRemove) 237 { 238 // fix the damn kernel! 239 if (PartExt->DeviceRemoved) 240 { 241 DPRINT1("Double IRP_MN_REMOVE_DEVICE!\n"); 242 return STATUS_SUCCESS; 243 } 244 245 PartExt->DeviceRemoved = TRUE; 246 247 ASSERT(PartExt->DeviceName.Buffer); 248 if (PartExt->DeviceName.Buffer) 249 { 250 INFO("Removed device %wZ\n", &PartExt->DeviceName); 251 RtlFreeUnicodeString(&PartExt->DeviceName); 252 } 253 254 IoDeleteDevice(PartExt->DeviceObject); 255 } 256 257 return STATUS_SUCCESS; 258 } 259 260 static 261 CODE_SEG("PAGE") 262 NTSTATUS 263 PartitionHandleDeviceRelations( 264 _In_ PPARTITION_EXTENSION PartExt, 265 _In_ PIRP Irp) 266 { 267 PAGED_CODE(); 268 269 // fix the damn kernel! 270 if (PartExt->DeviceRemoved) 271 { 272 DPRINT1("QDR after device removal!\n"); 273 return STATUS_DEVICE_DOES_NOT_EXIST; 274 } 275 276 PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp); 277 DEVICE_RELATION_TYPE type = ioStack->Parameters.QueryDeviceRelations.Type; 278 279 if (type == TargetDeviceRelation) 280 { 281 // Device relations has one entry built in to it's size. 282 PDEVICE_RELATIONS deviceRelations = 283 ExAllocatePoolZero(PagedPool, sizeof(DEVICE_RELATIONS), TAG_PARTMGR); 284 285 if (deviceRelations != NULL) 286 { 287 deviceRelations->Count = 1; 288 deviceRelations->Objects[0] = PartExt->DeviceObject; 289 ObReferenceObject(deviceRelations->Objects[0]); 290 291 Irp->IoStatus.Information = (ULONG_PTR)deviceRelations; 292 return STATUS_SUCCESS; 293 } 294 else 295 { 296 return STATUS_INSUFFICIENT_RESOURCES; 297 } 298 } 299 else 300 { 301 Irp->IoStatus.Information = 0; 302 return Irp->IoStatus.Status; 303 } 304 } 305 306 static 307 CODE_SEG("PAGE") 308 NTSTATUS 309 PartitionHandleQueryId( 310 _In_ PPARTITION_EXTENSION PartExt, 311 _In_ PIRP Irp) 312 { 313 PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp); 314 BUS_QUERY_ID_TYPE idType = ioStack->Parameters.QueryId.IdType; 315 UNICODE_STRING idString; 316 NTSTATUS status; 317 318 PAGED_CODE(); 319 320 switch (idType) 321 { 322 case BusQueryDeviceID: 323 status = RtlCreateUnicodeString(&idString, L"STORAGE\\Partition") 324 ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; 325 break; 326 case BusQueryHardwareIDs: 327 case BusQueryCompatibleIDs: 328 { 329 static WCHAR volumeID[] = L"STORAGE\\Volume\0"; 330 331 idString.Buffer = ExAllocatePoolWithTag(PagedPool, sizeof(volumeID), TAG_PARTMGR); 332 RtlCopyMemory(idString.Buffer, volumeID, sizeof(volumeID)); 333 334 status = STATUS_SUCCESS; 335 break; 336 } 337 case BusQueryInstanceID: 338 { 339 WCHAR string[64]; 340 PFDO_EXTENSION fdoExtension = PartExt->LowerDevice->DeviceExtension; 341 342 PartMgrAcquireLayoutLock(fdoExtension); 343 344 if (fdoExtension->DiskData.PartitionStyle == PARTITION_STYLE_MBR) 345 { 346 swprintf(string, L"S%08lx_O%I64x_L%I64x", 347 fdoExtension->DiskData.Mbr.Signature, 348 PartExt->StartingOffset, 349 PartExt->PartitionLength); 350 } 351 else 352 { 353 swprintf(string, 354 L"S%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02xS_O%I64x_L%I64x", 355 fdoExtension->DiskData.Gpt.DiskId.Data1, 356 fdoExtension->DiskData.Gpt.DiskId.Data2, 357 fdoExtension->DiskData.Gpt.DiskId.Data3, 358 fdoExtension->DiskData.Gpt.DiskId.Data4[0], 359 fdoExtension->DiskData.Gpt.DiskId.Data4[1], 360 fdoExtension->DiskData.Gpt.DiskId.Data4[2], 361 fdoExtension->DiskData.Gpt.DiskId.Data4[3], 362 fdoExtension->DiskData.Gpt.DiskId.Data4[4], 363 fdoExtension->DiskData.Gpt.DiskId.Data4[5], 364 fdoExtension->DiskData.Gpt.DiskId.Data4[6], 365 fdoExtension->DiskData.Gpt.DiskId.Data4[7], 366 PartExt->StartingOffset, 367 PartExt->PartitionLength); 368 } 369 370 PartMgrReleaseLayoutLock(fdoExtension); 371 372 status = RtlCreateUnicodeString(&idString, string) 373 ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; 374 break; 375 } 376 default: 377 status = STATUS_NOT_SUPPORTED; 378 break; 379 } 380 381 Irp->IoStatus.Information = NT_SUCCESS(status) ? (ULONG_PTR) idString.Buffer : 0; 382 return status; 383 } 384 385 static 386 CODE_SEG("PAGE") 387 NTSTATUS 388 PartitionHandleQueryCapabilities( 389 _In_ PPARTITION_EXTENSION PartExt, 390 _In_ PIRP Irp) 391 { 392 PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp); 393 PDEVICE_CAPABILITIES devCaps = ioStack->Parameters.DeviceCapabilities.Capabilities; 394 395 PAGED_CODE(); 396 ASSERT(devCaps); 397 398 devCaps->SilentInstall = TRUE; 399 devCaps->RawDeviceOK = TRUE; 400 devCaps->NoDisplayInUI = TRUE; 401 devCaps->Address = PartExt->OnDiskNumber; 402 devCaps->UniqueID = 1; 403 404 return STATUS_SUCCESS; 405 } 406 407 CODE_SEG("PAGE") 408 NTSTATUS 409 PartitionHandlePnp( 410 _In_ PDEVICE_OBJECT DeviceObject, 411 _In_ PIRP Irp) 412 { 413 PPARTITION_EXTENSION partExt = DeviceObject->DeviceExtension; 414 PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp); 415 NTSTATUS status; 416 417 PAGED_CODE(); 418 419 switch (ioStack->MinorFunction) 420 { 421 case IRP_MN_START_DEVICE: 422 { 423 status = PartitionHandleStartDevice(partExt, Irp); 424 break; 425 } 426 case IRP_MN_QUERY_DEVICE_RELATIONS: 427 { 428 status = PartitionHandleDeviceRelations(partExt, Irp); 429 break; 430 } 431 case IRP_MN_QUERY_STOP_DEVICE: 432 case IRP_MN_QUERY_REMOVE_DEVICE: 433 case IRP_MN_CANCEL_STOP_DEVICE: 434 case IRP_MN_CANCEL_REMOVE_DEVICE: 435 case IRP_MN_STOP_DEVICE: 436 { 437 status = STATUS_SUCCESS; 438 break; 439 } 440 case IRP_MN_SURPRISE_REMOVAL: 441 { 442 status = PartitionHandleRemove(partExt, FALSE); 443 break; 444 } 445 case IRP_MN_REMOVE_DEVICE: 446 { 447 status = PartitionHandleRemove(partExt, TRUE); 448 break; 449 } 450 case IRP_MN_QUERY_ID: 451 { 452 status = PartitionHandleQueryId(partExt, Irp); 453 break; 454 } 455 case IRP_MN_QUERY_CAPABILITIES: 456 { 457 status = PartitionHandleQueryCapabilities(partExt, Irp); 458 break; 459 } 460 default: 461 { 462 Irp->IoStatus.Information = 0; 463 status = STATUS_NOT_SUPPORTED; 464 } 465 } 466 467 Irp->IoStatus.Status = status; 468 IoCompleteRequest(Irp, IO_NO_INCREMENT); 469 return status; 470 } 471 472 NTSTATUS 473 PartitionHandleDeviceControl( 474 _In_ PDEVICE_OBJECT DeviceObject, 475 _In_ PIRP Irp) 476 { 477 PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp); 478 PPARTITION_EXTENSION partExt = DeviceObject->DeviceExtension; 479 PFDO_EXTENSION fdoExtension = partExt->LowerDevice->DeviceExtension; 480 NTSTATUS status; 481 482 ASSERT(!partExt->IsFDO); 483 484 if (!partExt->IsEnumerated) 485 { 486 Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST; 487 IoCompleteRequest(Irp, IO_NO_INCREMENT); 488 return STATUS_DEVICE_DOES_NOT_EXIST; 489 } 490 491 switch (ioStack->Parameters.DeviceIoControl.IoControlCode) 492 { 493 // disk stuff 494 case IOCTL_DISK_GET_PARTITION_INFO: 495 { 496 if (!VerifyIrpOutBufferSize(Irp, sizeof(PARTITION_INFORMATION))) 497 { 498 status = STATUS_BUFFER_TOO_SMALL; 499 break; 500 } 501 502 PartMgrAcquireLayoutLock(fdoExtension); 503 504 // not supported on anything other than MBR 505 if (fdoExtension->DiskData.PartitionStyle != PARTITION_STYLE_MBR) 506 { 507 status = STATUS_INVALID_DEVICE_REQUEST; 508 PartMgrReleaseLayoutLock(fdoExtension); 509 break; 510 } 511 512 PPARTITION_INFORMATION partInfo = Irp->AssociatedIrp.SystemBuffer; 513 514 *partInfo = (PARTITION_INFORMATION){ 515 .PartitionType = partExt->Mbr.PartitionType, 516 .StartingOffset.QuadPart = partExt->StartingOffset, 517 .PartitionLength.QuadPart = partExt->PartitionLength, 518 .HiddenSectors = partExt->Mbr.HiddenSectors, 519 .PartitionNumber = partExt->DetectedNumber, 520 .BootIndicator = partExt->Mbr.BootIndicator, 521 .RecognizedPartition = partExt->Mbr.RecognizedPartition, 522 .RewritePartition = FALSE, 523 }; 524 525 PartMgrReleaseLayoutLock(fdoExtension); 526 527 Irp->IoStatus.Information = sizeof(*partInfo); 528 status = STATUS_SUCCESS; 529 break; 530 } 531 case IOCTL_DISK_GET_PARTITION_INFO_EX: 532 { 533 if (!VerifyIrpOutBufferSize(Irp, sizeof(PARTITION_INFORMATION_EX))) 534 { 535 status = STATUS_BUFFER_TOO_SMALL; 536 break; 537 } 538 539 PPARTITION_INFORMATION_EX partInfoEx = Irp->AssociatedIrp.SystemBuffer; 540 541 PartMgrAcquireLayoutLock(fdoExtension); 542 543 *partInfoEx = (PARTITION_INFORMATION_EX){ 544 .StartingOffset.QuadPart = partExt->StartingOffset, 545 .PartitionLength.QuadPart = partExt->PartitionLength, 546 .PartitionNumber = partExt->DetectedNumber, 547 .PartitionStyle = fdoExtension->DiskData.PartitionStyle, 548 .RewritePartition = FALSE, 549 }; 550 551 if (fdoExtension->DiskData.PartitionStyle == PARTITION_STYLE_MBR) 552 { 553 partInfoEx->Mbr = (PARTITION_INFORMATION_MBR){ 554 .PartitionType = partExt->Mbr.PartitionType, 555 .HiddenSectors = partExt->Mbr.HiddenSectors, 556 .BootIndicator = partExt->Mbr.BootIndicator, 557 .RecognizedPartition = partExt->Mbr.RecognizedPartition, 558 }; 559 } 560 else 561 { 562 partInfoEx->Gpt = (PARTITION_INFORMATION_GPT){ 563 .PartitionType = partExt->Gpt.PartitionType, 564 .PartitionId = partExt->Gpt.PartitionId, 565 .Attributes = partExt->Gpt.Attributes, 566 }; 567 568 RtlCopyMemory(partInfoEx->Gpt.Name, 569 partExt->Gpt.Name, 570 sizeof(partInfoEx->Gpt.Name)); 571 } 572 573 PartMgrReleaseLayoutLock(fdoExtension); 574 575 Irp->IoStatus.Information = sizeof(*partInfoEx); 576 status = STATUS_SUCCESS; 577 break; 578 } 579 case IOCTL_DISK_SET_PARTITION_INFO: 580 { 581 PSET_PARTITION_INFORMATION inputBuffer = Irp->AssociatedIrp.SystemBuffer; 582 if (!VerifyIrpInBufferSize(Irp, sizeof(*inputBuffer))) 583 { 584 status = STATUS_INFO_LENGTH_MISMATCH; 585 break; 586 } 587 588 PartMgrAcquireLayoutLock(fdoExtension); 589 590 // these functions use on disk numbers, not detected ones 591 status = IoSetPartitionInformation(fdoExtension->LowerDevice, 592 fdoExtension->DiskData.BytesPerSector, 593 partExt->OnDiskNumber, 594 inputBuffer->PartitionType); 595 596 if (NT_SUCCESS(status)) 597 { 598 partExt->Mbr.PartitionType = inputBuffer->PartitionType; 599 } 600 601 PartMgrReleaseLayoutLock(fdoExtension); 602 603 Irp->IoStatus.Information = 0; 604 break; 605 } 606 case IOCTL_DISK_SET_PARTITION_INFO_EX: 607 { 608 PSET_PARTITION_INFORMATION_EX inputBuffer = Irp->AssociatedIrp.SystemBuffer; 609 if (!VerifyIrpInBufferSize(Irp, sizeof(*inputBuffer))) 610 { 611 status = STATUS_INFO_LENGTH_MISMATCH; 612 break; 613 } 614 615 PartMgrAcquireLayoutLock(fdoExtension); 616 617 // these functions use on disk numbers, not detected ones 618 status = IoSetPartitionInformationEx(fdoExtension->LowerDevice, 619 partExt->OnDiskNumber, 620 inputBuffer); 621 622 if (NT_SUCCESS(status)) 623 { 624 if (fdoExtension->DiskData.PartitionStyle == PARTITION_STYLE_MBR) 625 { 626 partExt->Mbr.PartitionType = inputBuffer->Mbr.PartitionType; 627 } 628 else 629 { 630 partExt->Gpt.PartitionType = inputBuffer->Gpt.PartitionType; 631 partExt->Gpt.PartitionId = inputBuffer->Gpt.PartitionId; 632 partExt->Gpt.Attributes = inputBuffer->Gpt.Attributes; 633 634 RtlMoveMemory(partExt->Gpt.Name, 635 inputBuffer->Gpt.Name, 636 sizeof(partExt->Gpt.Name)); 637 } 638 } 639 640 PartMgrReleaseLayoutLock(fdoExtension); 641 642 Irp->IoStatus.Information = 0; 643 break; 644 } 645 case IOCTL_DISK_GET_LENGTH_INFO: 646 { 647 PGET_LENGTH_INFORMATION lengthInfo = Irp->AssociatedIrp.SystemBuffer; 648 if (!VerifyIrpOutBufferSize(Irp, sizeof(*lengthInfo))) 649 { 650 status = STATUS_BUFFER_TOO_SMALL; 651 break; 652 } 653 654 PartMgrAcquireLayoutLock(fdoExtension); 655 656 lengthInfo->Length.QuadPart = partExt->PartitionLength; 657 658 PartMgrReleaseLayoutLock(fdoExtension); 659 660 status = STATUS_SUCCESS; 661 Irp->IoStatus.Information = sizeof(*lengthInfo); 662 break; 663 } 664 case IOCTL_DISK_VERIFY: 665 { 666 PVERIFY_INFORMATION verifyInfo = Irp->AssociatedIrp.SystemBuffer; 667 if (!VerifyIrpInBufferSize(Irp, sizeof(*verifyInfo))) 668 { 669 status = STATUS_INFO_LENGTH_MISMATCH; 670 break; 671 } 672 673 // Partition device should just adjust the starting offset 674 verifyInfo->StartingOffset.QuadPart += partExt->StartingOffset; 675 return ForwardIrpAndForget(DeviceObject, Irp); 676 } 677 case IOCTL_DISK_UPDATE_PROPERTIES: 678 { 679 fdoExtension->LayoutValid = FALSE; 680 IoInvalidateDeviceRelations(fdoExtension->PhysicalDiskDO, BusRelations); 681 682 status = STATUS_SUCCESS; 683 break; 684 } 685 case IOCTL_STORAGE_MEDIA_REMOVAL: 686 { 687 return ForwardIrpAndForget(DeviceObject, Irp); 688 } 689 // volume stuff (most of that should be in volmgr.sys one it is implemented) 690 case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS: 691 { 692 PVOLUME_DISK_EXTENTS volExts = Irp->AssociatedIrp.SystemBuffer; 693 694 // we fill only one extent entry so sizeof(*volExts) is enough 695 if (!VerifyIrpOutBufferSize(Irp, sizeof(*volExts))) 696 { 697 status = STATUS_BUFFER_TOO_SMALL; 698 break; 699 } 700 701 PartMgrAcquireLayoutLock(fdoExtension); 702 703 // the only type of volume we support right now is disk partition 704 // so this structure is simple 705 706 *volExts = (VOLUME_DISK_EXTENTS) { 707 .NumberOfDiskExtents = 1, 708 .Extents = {{ 709 .DiskNumber = fdoExtension->DiskData.DeviceNumber, 710 .StartingOffset.QuadPart = partExt->StartingOffset, 711 .ExtentLength.QuadPart = partExt->PartitionLength 712 }} 713 }; 714 715 PartMgrReleaseLayoutLock(fdoExtension); 716 717 status = STATUS_SUCCESS; 718 Irp->IoStatus.Information = sizeof(*volExts); 719 break; 720 } 721 case IOCTL_VOLUME_ONLINE: 722 { 723 status = STATUS_SUCCESS; 724 break; 725 } 726 case IOCTL_VOLUME_GET_GPT_ATTRIBUTES: 727 { 728 PVOLUME_GET_GPT_ATTRIBUTES_INFORMATION gptAttrs = Irp->AssociatedIrp.SystemBuffer; 729 if (!VerifyIrpOutBufferSize(Irp, sizeof(*gptAttrs))) 730 { 731 status = STATUS_BUFFER_TOO_SMALL; 732 break; 733 } 734 735 // not supported on anything other than GPT 736 if (fdoExtension->DiskData.PartitionStyle != PARTITION_STYLE_GPT) 737 { 738 status = STATUS_INVALID_DEVICE_REQUEST; 739 break; 740 } 741 742 gptAttrs->GptAttributes = partExt->Gpt.Attributes; 743 744 status = STATUS_SUCCESS; 745 Irp->IoStatus.Information = sizeof(*gptAttrs); 746 break; 747 } 748 // mountmgr stuff 749 case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME: 750 { 751 PMOUNTDEV_NAME name = Irp->AssociatedIrp.SystemBuffer; 752 753 if (!VerifyIrpOutBufferSize(Irp, sizeof(USHORT))) 754 { 755 status = STATUS_BUFFER_TOO_SMALL; 756 break; 757 } 758 759 name->NameLength = partExt->DeviceName.Length; 760 761 // return NameLength back 762 if (!VerifyIrpOutBufferSize(Irp, sizeof(USHORT) + name->NameLength)) 763 { 764 Irp->IoStatus.Information = sizeof(USHORT); 765 status = STATUS_BUFFER_OVERFLOW; 766 break; 767 } 768 769 RtlCopyMemory(name->Name, partExt->DeviceName.Buffer, name->NameLength); 770 771 status = STATUS_SUCCESS; 772 Irp->IoStatus.Information = sizeof(USHORT) + name->NameLength; 773 break; 774 } 775 case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID: 776 { 777 PMOUNTDEV_UNIQUE_ID uniqueId = Irp->AssociatedIrp.SystemBuffer; 778 779 if (!partExt->VolumeInterfaceName.Buffer) 780 { 781 status = STATUS_INVALID_PARAMETER; 782 break; 783 } 784 785 if (!VerifyIrpOutBufferSize(Irp, sizeof(USHORT))) 786 { 787 status = STATUS_BUFFER_TOO_SMALL; 788 break; 789 } 790 791 uniqueId->UniqueIdLength = partExt->VolumeInterfaceName.Length; 792 793 // return UniqueIdLength back 794 if (!VerifyIrpOutBufferSize(Irp, sizeof(USHORT) + uniqueId->UniqueIdLength)) 795 { 796 Irp->IoStatus.Information = sizeof(USHORT); 797 status = STATUS_BUFFER_OVERFLOW; 798 break; 799 } 800 801 RtlCopyMemory(uniqueId->UniqueId, 802 partExt->VolumeInterfaceName.Buffer, 803 uniqueId->UniqueIdLength); 804 805 status = STATUS_SUCCESS; 806 Irp->IoStatus.Information = sizeof(USHORT) + uniqueId->UniqueIdLength; 807 break; 808 } 809 default: 810 return ForwardIrpAndForget(DeviceObject, Irp); 811 } 812 813 Irp->IoStatus.Status = status; 814 IoCompleteRequest(Irp, IO_NO_INCREMENT); 815 return status; 816 } 817