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