1 /* 2 * PROJECT: Partition manager driver 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Main file 5 * COPYRIGHT: 2020 Victor Perevertkin (victor.perevertkin@reactos.org) 6 */ 7 8 /* The Partition Manager Driver in ReactOS complements disk.sys/classpnp.sys drivers 9 * (which are derived from Windows 10 drivers) so does not do exactly what Windows 2003 partmgr.sys 10 * does. Here is acts like both partition and volume manager, because volmgr.sys does not (yet) 11 * exist in ReactOS. Thus handles some IOCTL_VOLUME_*, and IOCTL_MOUNTMGR_* IOCTLs. 12 */ 13 14 #include "partmgr.h" 15 16 17 static 18 CODE_SEG("PAGE") 19 PDRIVE_LAYOUT_INFORMATION 20 PartMgrConvertExtendedToLayout( 21 _In_ CONST PDRIVE_LAYOUT_INFORMATION_EX LayoutEx) 22 { 23 PDRIVE_LAYOUT_INFORMATION Layout; 24 PPARTITION_INFORMATION Partition; 25 PPARTITION_INFORMATION_EX PartitionEx; 26 27 PAGED_CODE(); 28 29 ASSERT(LayoutEx); 30 31 if (LayoutEx->PartitionStyle != PARTITION_STYLE_MBR) 32 { 33 ASSERT(FALSE); 34 return NULL; 35 } 36 37 size_t layoutSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry[0]) + 38 LayoutEx->PartitionCount * sizeof (PARTITION_INFORMATION); 39 40 Layout = ExAllocatePoolWithTag(PagedPool, layoutSize, TAG_PARTMGR); 41 42 if (Layout == NULL) 43 { 44 return NULL; 45 } 46 47 Layout->Signature = LayoutEx->Mbr.Signature; 48 Layout->PartitionCount = LayoutEx->PartitionCount; 49 50 for (UINT32 i = 0; i < LayoutEx->PartitionCount; i++) 51 { 52 Partition = &Layout->PartitionEntry[i]; 53 PartitionEx = &LayoutEx->PartitionEntry[i]; 54 55 Partition->StartingOffset = PartitionEx->StartingOffset; 56 Partition->PartitionLength = PartitionEx->PartitionLength; 57 Partition->RewritePartition = PartitionEx->RewritePartition; 58 Partition->PartitionNumber = PartitionEx->PartitionNumber; 59 60 Partition->PartitionType = PartitionEx->Mbr.PartitionType; 61 Partition->BootIndicator = PartitionEx->Mbr.BootIndicator; 62 Partition->RecognizedPartition = PartitionEx->Mbr.RecognizedPartition; 63 Partition->HiddenSectors = PartitionEx->Mbr.HiddenSectors; 64 } 65 66 return Layout; 67 } 68 69 static 70 CODE_SEG("PAGE") 71 PDRIVE_LAYOUT_INFORMATION_EX 72 PartMgrConvertLayoutToExtended( 73 _In_ CONST PDRIVE_LAYOUT_INFORMATION Layout) 74 { 75 PDRIVE_LAYOUT_INFORMATION_EX layoutEx; 76 77 PAGED_CODE(); 78 79 ASSERT(Layout != NULL); 80 81 size_t layoutSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[0]) + 82 Layout->PartitionCount * sizeof (PARTITION_INFORMATION_EX); 83 84 layoutEx = ExAllocatePoolUninitialized(PagedPool, layoutSize, TAG_PARTMGR); 85 86 if (layoutEx == NULL) 87 { 88 return NULL; 89 } 90 91 layoutEx->PartitionStyle = PARTITION_STYLE_MBR; 92 layoutEx->PartitionCount = Layout->PartitionCount; 93 layoutEx->Mbr.Signature = Layout->Signature; 94 95 for (UINT32 i = 0; i < Layout->PartitionCount; i++) 96 { 97 PPARTITION_INFORMATION part = &Layout->PartitionEntry[i]; 98 99 layoutEx->PartitionEntry[i] = (PARTITION_INFORMATION_EX) { 100 .PartitionStyle = PARTITION_STYLE_MBR, 101 .StartingOffset = part->StartingOffset, 102 .PartitionLength = part->PartitionLength, 103 .RewritePartition = part->RewritePartition, 104 .PartitionNumber = part->PartitionNumber, 105 .Mbr = { 106 .PartitionType = part->PartitionType, 107 .BootIndicator = part->BootIndicator, 108 .RecognizedPartition = part->RecognizedPartition, 109 .HiddenSectors = part->HiddenSectors, 110 } 111 }; 112 } 113 114 return layoutEx; 115 } 116 117 static 118 CODE_SEG("PAGE") 119 VOID 120 PartMgrUpdatePartitionDevices( 121 _In_ PFDO_EXTENSION FdoExtension, 122 _Inout_ PDRIVE_LAYOUT_INFORMATION_EX NewLayout) 123 { 124 NTSTATUS status; 125 PSINGLE_LIST_ENTRY curEntry, prevEntry; 126 UINT32 totalPartitions = 0; 127 128 // Clear the partition numbers from the list entries 129 for (UINT32 i = 0; i < NewLayout->PartitionCount; i++) 130 { 131 NewLayout->PartitionEntry[i].PartitionNumber = 0; 132 } 133 134 // iterate over old partition list 135 prevEntry = &FdoExtension->PartitionList; 136 curEntry = FdoExtension->PartitionList.Next; 137 while (curEntry != NULL) 138 { 139 PPARTITION_EXTENSION partExt = CONTAINING_RECORD(curEntry, PARTITION_EXTENSION, ListEntry); 140 UINT32 partNumber = 0; // count detected partitions for device symlinks 141 BOOLEAN found = FALSE; 142 PPARTITION_INFORMATION_EX partEntry; 143 144 // trying to find this partition in returned layout 145 for (UINT32 i = 0; i < NewLayout->PartitionCount; i++) 146 { 147 partEntry = &NewLayout->PartitionEntry[i]; 148 149 // skip unused and container partitions 150 if (NewLayout->PartitionStyle == PARTITION_STYLE_MBR && 151 (partEntry->Mbr.PartitionType == PARTITION_ENTRY_UNUSED || 152 IsContainerPartition(partEntry->Mbr.PartitionType))) 153 { 154 continue; 155 } 156 157 partNumber++; 158 159 // skip already found partitions 160 if (partEntry->PartitionNumber) 161 { 162 continue; 163 } 164 165 // skip if partitions are not equal 166 if (partEntry->StartingOffset.QuadPart != partExt->StartingOffset || 167 partEntry->PartitionLength.QuadPart != partExt->PartitionLength) 168 { 169 continue; 170 } 171 172 // found matching partition - processing it 173 found = TRUE; 174 break; 175 } 176 177 if (found) 178 { 179 // update (possibly changed) partition metadata 180 if (NewLayout->PartitionStyle == PARTITION_STYLE_MBR) 181 { 182 partExt->Mbr.PartitionType = partEntry->Mbr.PartitionType; 183 partExt->Mbr.BootIndicator = partEntry->Mbr.BootIndicator; 184 } 185 else 186 { 187 partExt->Gpt.PartitionType = partEntry->Gpt.PartitionType; 188 partExt->Gpt.PartitionId = partEntry->Gpt.PartitionId; 189 partExt->Gpt.Attributes = partEntry->Gpt.Attributes; 190 191 RtlCopyMemory(partExt->Gpt.Name, partEntry->Gpt.Name, sizeof(partExt->Gpt.Name)); 192 } 193 194 partExt->OnDiskNumber = partNumber; 195 partEntry->PartitionNumber = partNumber; // mark it as a found one 196 totalPartitions++; 197 } 198 else 199 { 200 // detach the device from the list 201 prevEntry->Next = curEntry->Next; 202 curEntry = prevEntry; 203 partExt->Attached = FALSE; 204 205 // enumerated PDOs will receive IRP_MN_REMOVE_DEVICE 206 if (!partExt->IsEnumerated) 207 { 208 PartitionHandleRemove(partExt, TRUE); 209 } 210 } 211 212 prevEntry = curEntry; 213 curEntry = curEntry->Next; 214 } 215 216 UINT32 partNumber = 0; 217 UINT32 pdoNumber = 1; 218 219 // now looking through remaining "new" partitions 220 for (UINT32 i = 0; i < NewLayout->PartitionCount; i++) 221 { 222 PPARTITION_INFORMATION_EX partEntry = &NewLayout->PartitionEntry[i]; 223 224 // again, skip unused and container partitions 225 if (NewLayout->PartitionStyle == PARTITION_STYLE_MBR && 226 (partEntry->Mbr.PartitionType == PARTITION_ENTRY_UNUSED || 227 IsContainerPartition(partEntry->Mbr.PartitionType))) 228 { 229 continue; 230 } 231 232 partNumber++; 233 234 // and skip processed partitions 235 if (partEntry->PartitionNumber != 0) 236 { 237 continue; 238 } 239 240 // find the first free PDO index 241 for (PSINGLE_LIST_ENTRY curEntry = FdoExtension->PartitionList.Next; 242 curEntry != NULL; 243 curEntry = curEntry->Next) 244 { 245 PPARTITION_EXTENSION partExt = CONTAINING_RECORD(curEntry, 246 PARTITION_EXTENSION, 247 ListEntry); 248 249 if (partExt->DetectedNumber == pdoNumber) 250 { 251 // found a matching pdo number - restart the search 252 curEntry = FdoExtension->PartitionList.Next; 253 pdoNumber++; 254 } 255 } 256 257 partEntry->PartitionNumber = partNumber; 258 259 PDEVICE_OBJECT partitionDevice; 260 status = PartitionCreateDevice(FdoExtension->DeviceObject, 261 partEntry, 262 pdoNumber, 263 NewLayout->PartitionStyle, 264 &partitionDevice); 265 266 if (!NT_SUCCESS(status)) 267 { 268 partEntry->PartitionNumber = 0; 269 continue; 270 } 271 272 totalPartitions++; 273 274 // insert the structure to the partition list 275 curEntry = FdoExtension->PartitionList.Next; 276 prevEntry = NULL; 277 while (curEntry != NULL) 278 { 279 PPARTITION_EXTENSION curPart = CONTAINING_RECORD(curEntry, 280 PARTITION_EXTENSION, 281 ListEntry); 282 if (curPart->OnDiskNumber < partNumber) 283 { 284 prevEntry = curEntry; 285 curEntry = curPart->ListEntry.Next; 286 } 287 else 288 { // we found where to put the partition 289 break; 290 } 291 } 292 293 PPARTITION_EXTENSION partExt = partitionDevice->DeviceExtension; 294 295 if (prevEntry) 296 { 297 // insert after prevEntry 298 partExt->ListEntry.Next = prevEntry->Next; 299 prevEntry->Next = &partExt->ListEntry; 300 } 301 else 302 { 303 // insert in the beginning 304 partExt->ListEntry.Next = FdoExtension->PartitionList.Next; 305 FdoExtension->PartitionList.Next = &partExt->ListEntry; 306 } 307 308 partExt->Attached = TRUE; 309 } 310 311 FdoExtension->EnumeratedPartitionsTotal = totalPartitions; 312 } 313 314 // requires partitioning lock held 315 static 316 CODE_SEG("PAGE") 317 NTSTATUS 318 PartMgrGetDriveLayout( 319 _In_ PFDO_EXTENSION FdoExtension, 320 _Out_ PDRIVE_LAYOUT_INFORMATION_EX *DriveLayout) 321 { 322 PAGED_CODE(); 323 324 if (FdoExtension->LayoutValid) 325 { 326 *DriveLayout = FdoExtension->LayoutCache; 327 return STATUS_SUCCESS; 328 } 329 330 PDRIVE_LAYOUT_INFORMATION_EX layoutEx = NULL; 331 NTSTATUS status = IoReadPartitionTableEx(FdoExtension->LowerDevice, &layoutEx); 332 333 if (!NT_SUCCESS(status)) 334 { 335 return status; 336 } 337 338 if (FdoExtension->LayoutCache) 339 { 340 ExFreePool(FdoExtension->LayoutCache); 341 } 342 343 FdoExtension->LayoutCache = layoutEx; 344 FdoExtension->LayoutValid = TRUE; 345 346 *DriveLayout = layoutEx; 347 348 return status; 349 } 350 351 static 352 CODE_SEG("PAGE") 353 NTSTATUS 354 FdoIoctlDiskGetDriveGeometryEx( 355 _In_ PFDO_EXTENSION FdoExtension, 356 _In_ PIRP Irp) 357 { 358 PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp); 359 360 PAGED_CODE(); 361 362 // We're patching the DISK_PARTITION_INFO part of the returned structure 363 // as disk.sys doesn't really know about the partition table on a disk 364 365 PDISK_GEOMETRY_EX_INTERNAL geometryEx = Irp->AssociatedIrp.SystemBuffer; 366 size_t outBufferLength = ioStack->Parameters.DeviceIoControl.OutputBufferLength; 367 NTSTATUS status; 368 369 status = IssueSyncIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, 370 FdoExtension->LowerDevice, 371 NULL, 372 0, 373 geometryEx, 374 outBufferLength, 375 FALSE); 376 377 if (!NT_SUCCESS(status)) 378 { 379 return status; 380 } 381 382 // if DISK_PARTITION_INFO fits the output size 383 if (outBufferLength >= FIELD_OFFSET(DISK_GEOMETRY_EX_INTERNAL, Detection)) 384 { 385 PartMgrAcquireLayoutLock(FdoExtension); 386 387 geometryEx->Partition.SizeOfPartitionInfo = sizeof(geometryEx->Partition); 388 geometryEx->Partition.PartitionStyle = FdoExtension->DiskData.PartitionStyle; 389 390 switch (geometryEx->Partition.PartitionStyle) 391 { 392 case PARTITION_STYLE_MBR: 393 geometryEx->Partition.Mbr.Signature = FdoExtension->DiskData.Mbr.Signature; 394 // checksum? 395 break; 396 397 case PARTITION_STYLE_GPT: 398 geometryEx->Partition.Gpt.DiskId = FdoExtension->DiskData.Gpt.DiskId; 399 break; 400 401 default: 402 RtlZeroMemory(&geometryEx->Partition, sizeof(geometryEx->Partition)); 403 } 404 405 PartMgrReleaseLayoutLock(FdoExtension); 406 } 407 408 // the logic is copied from disk.sys 409 Irp->IoStatus.Information = min(outBufferLength, sizeof(DISK_GEOMETRY_EX_INTERNAL)); 410 411 return status; 412 } 413 414 static 415 CODE_SEG("PAGE") 416 NTSTATUS 417 FdoIoctlDiskGetPartitionInfo( 418 _In_ PFDO_EXTENSION FdoExtension, 419 _In_ PIRP Irp) 420 { 421 PPARTITION_INFORMATION partInfo = Irp->AssociatedIrp.SystemBuffer; 422 423 PAGED_CODE(); 424 425 if (!VerifyIrpOutBufferSize(Irp, sizeof(*partInfo))) 426 { 427 return STATUS_BUFFER_TOO_SMALL; 428 } 429 430 PartMgrAcquireLayoutLock(FdoExtension); 431 432 *partInfo = (PARTITION_INFORMATION){ 433 .PartitionType = PARTITION_ENTRY_UNUSED, 434 .StartingOffset.QuadPart = 0, 435 .PartitionLength.QuadPart = FdoExtension->DiskData.DiskSize, 436 .HiddenSectors = 0, 437 .PartitionNumber = 0, 438 .BootIndicator = FALSE, 439 .RewritePartition = FALSE, 440 .RecognizedPartition = FALSE, 441 }; 442 443 PartMgrReleaseLayoutLock(FdoExtension); 444 445 Irp->IoStatus.Information = sizeof(*partInfo); 446 return STATUS_SUCCESS; 447 } 448 449 static 450 CODE_SEG("PAGE") 451 NTSTATUS 452 FdoIoctlDiskGetPartitionInfoEx( 453 _In_ PFDO_EXTENSION FdoExtension, 454 _In_ PIRP Irp) 455 { 456 PPARTITION_INFORMATION_EX partInfoEx = Irp->AssociatedIrp.SystemBuffer; 457 458 PAGED_CODE(); 459 460 if (!VerifyIrpOutBufferSize(Irp, sizeof(*partInfoEx))) 461 { 462 return STATUS_BUFFER_TOO_SMALL; 463 } 464 465 PartMgrAcquireLayoutLock(FdoExtension); 466 467 // most of the fields a zeroed for Partition0 468 *partInfoEx = (PARTITION_INFORMATION_EX){ 469 .PartitionLength.QuadPart = FdoExtension->DiskData.DiskSize, 470 .PartitionStyle = FdoExtension->DiskData.PartitionStyle, 471 }; 472 473 PartMgrReleaseLayoutLock(FdoExtension); 474 475 Irp->IoStatus.Information = sizeof(*partInfoEx); 476 return STATUS_SUCCESS; 477 } 478 479 static 480 CODE_SEG("PAGE") 481 NTSTATUS 482 FdoIoctlDiskGetDriveLayout( 483 _In_ PFDO_EXTENSION FdoExtension, 484 _In_ PIRP Irp) 485 { 486 PAGED_CODE(); 487 488 PartMgrAcquireLayoutLock(FdoExtension); 489 490 PDRIVE_LAYOUT_INFORMATION_EX layoutEx; 491 NTSTATUS status = PartMgrGetDriveLayout(FdoExtension, &layoutEx); 492 493 if (!NT_SUCCESS(status)) 494 { 495 PartMgrReleaseLayoutLock(FdoExtension); 496 return status; 497 } 498 499 // checking this value from layoutEx in case it has been changed 500 if (layoutEx->PartitionStyle != PARTITION_STYLE_MBR) 501 { 502 PartMgrReleaseLayoutLock(FdoExtension); 503 return STATUS_INVALID_DEVICE_REQUEST; 504 } 505 506 size_t size = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry[0]); 507 size += layoutEx->PartitionCount * sizeof(PARTITION_INFORMATION); 508 509 if (!VerifyIrpOutBufferSize(Irp, size)) 510 { 511 PartMgrReleaseLayoutLock(FdoExtension); 512 return STATUS_BUFFER_TOO_SMALL; 513 } 514 515 PDRIVE_LAYOUT_INFORMATION partitionList = PartMgrConvertExtendedToLayout(layoutEx); 516 517 PartMgrReleaseLayoutLock(FdoExtension); 518 519 if (partitionList == NULL) 520 { 521 Irp->IoStatus.Information = 0; 522 return STATUS_INSUFFICIENT_RESOURCES; 523 } 524 525 RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, partitionList, size); 526 ExFreePoolWithTag(partitionList, TAG_PARTMGR); 527 528 Irp->IoStatus.Information = size; 529 return STATUS_SUCCESS; 530 } 531 532 static 533 CODE_SEG("PAGE") 534 NTSTATUS 535 FdoIoctlDiskGetDriveLayoutEx( 536 _In_ PFDO_EXTENSION FdoExtension, 537 _In_ PIRP Irp) 538 { 539 PAGED_CODE(); 540 541 PartMgrAcquireLayoutLock(FdoExtension); 542 543 PDRIVE_LAYOUT_INFORMATION_EX layoutEx; 544 NTSTATUS status = PartMgrGetDriveLayout(FdoExtension, &layoutEx); 545 if (!NT_SUCCESS(status)) 546 { 547 PartMgrReleaseLayoutLock(FdoExtension); 548 return status; 549 } 550 551 size_t size = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[0]); 552 size += layoutEx->PartitionCount * sizeof(PARTITION_INFORMATION_EX); 553 554 if (!VerifyIrpOutBufferSize(Irp, size)) 555 { 556 PartMgrReleaseLayoutLock(FdoExtension); 557 return STATUS_BUFFER_TOO_SMALL; 558 } 559 560 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, layoutEx, size); 561 562 PartMgrReleaseLayoutLock(FdoExtension); 563 564 Irp->IoStatus.Information = size; 565 return STATUS_SUCCESS; 566 } 567 568 static 569 CODE_SEG("PAGE") 570 NTSTATUS 571 FdoIoctlDiskSetDriveLayout( 572 _In_ PFDO_EXTENSION FdoExtension, 573 _In_ PIRP Irp) 574 { 575 PDRIVE_LAYOUT_INFORMATION layoutInfo = Irp->AssociatedIrp.SystemBuffer; 576 577 PAGED_CODE(); 578 579 if (!VerifyIrpInBufferSize(Irp, sizeof(*layoutInfo))) 580 { 581 return STATUS_INFO_LENGTH_MISMATCH; 582 } 583 584 size_t layoutSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry[0]); 585 layoutSize += layoutInfo->PartitionCount * sizeof(PARTITION_INFORMATION); 586 587 if (!VerifyIrpInBufferSize(Irp, layoutSize)) 588 { 589 return STATUS_INFO_LENGTH_MISMATCH; 590 } 591 592 PDRIVE_LAYOUT_INFORMATION_EX layoutEx = PartMgrConvertLayoutToExtended(layoutInfo); 593 594 if (layoutEx == NULL) 595 { 596 Irp->IoStatus.Information = 0; 597 return STATUS_INSUFFICIENT_RESOURCES; 598 } 599 600 PartMgrAcquireLayoutLock(FdoExtension); 601 602 // this in fact updates the bus relations 603 PartMgrUpdatePartitionDevices(FdoExtension, layoutEx); 604 605 // write the partition table to the disk 606 NTSTATUS status = IoWritePartitionTableEx(FdoExtension->LowerDevice, layoutEx); 607 if (NT_SUCCESS(status)) 608 { 609 // save the layout cache 610 if (FdoExtension->LayoutCache) 611 { 612 ExFreePool(FdoExtension->LayoutCache); 613 } 614 FdoExtension->LayoutCache = layoutEx; 615 FdoExtension->LayoutValid = TRUE; 616 617 // set updated partition numbers 618 for (UINT32 i = 0; i < layoutInfo->PartitionCount; i++) 619 { 620 PPARTITION_INFORMATION part = &layoutInfo->PartitionEntry[i]; 621 622 part->PartitionNumber = layoutEx->PartitionEntry[i].PartitionNumber; 623 } 624 } 625 else 626 { 627 FdoExtension->LayoutValid = FALSE; 628 } 629 630 PartMgrReleaseLayoutLock(FdoExtension); 631 632 IoInvalidateDeviceRelations(FdoExtension->PhysicalDiskDO, BusRelations); 633 634 // notify everyone that the disk layout has changed 635 TARGET_DEVICE_CUSTOM_NOTIFICATION notification; 636 637 notification.Event = GUID_IO_DISK_LAYOUT_CHANGE; 638 notification.Version = 1; 639 notification.Size = FIELD_OFFSET(TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer); 640 notification.FileObject = NULL; 641 notification.NameBufferOffset = -1; 642 643 IoReportTargetDeviceChangeAsynchronous(FdoExtension->PhysicalDiskDO, 644 ¬ification, 645 NULL, 646 NULL); 647 648 Irp->IoStatus.Information = layoutSize; 649 return STATUS_SUCCESS; 650 } 651 652 static 653 CODE_SEG("PAGE") 654 NTSTATUS 655 FdoIoctlDiskSetDriveLayoutEx( 656 _In_ PFDO_EXTENSION FdoExtension, 657 _In_ PIRP Irp) 658 { 659 PDRIVE_LAYOUT_INFORMATION_EX layoutEx, layoutUser = Irp->AssociatedIrp.SystemBuffer; 660 NTSTATUS status; 661 662 PAGED_CODE(); 663 664 if (!VerifyIrpInBufferSize(Irp, sizeof(*layoutUser))) 665 { 666 return STATUS_INFO_LENGTH_MISMATCH; 667 } 668 669 size_t layoutSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[0]); 670 layoutSize += layoutUser->PartitionCount * sizeof(PARTITION_INFORMATION_EX); 671 672 if (!VerifyIrpInBufferSize(Irp, layoutSize)) 673 { 674 return STATUS_INFO_LENGTH_MISMATCH; 675 } 676 677 // we need to copy the structure from the IRP input buffer 678 layoutEx = ExAllocatePoolWithTag(PagedPool, layoutSize, TAG_PARTMGR); 679 if (!layoutEx) 680 { 681 Irp->IoStatus.Information = 0; 682 return STATUS_INSUFFICIENT_RESOURCES; 683 } 684 685 RtlCopyMemory(layoutEx, layoutUser, layoutSize); 686 687 PartMgrAcquireLayoutLock(FdoExtension); 688 689 // if partition count is 0, it's the same as IOCTL_DISK_CREATE_DISK 690 if (layoutEx->PartitionCount == 0) 691 { 692 CREATE_DISK createDisk = {0}; 693 createDisk.PartitionStyle = layoutEx->PartitionStyle; 694 if (createDisk.PartitionStyle == PARTITION_STYLE_MBR) 695 { 696 createDisk.Mbr.Signature = layoutEx->Mbr.Signature; 697 } 698 else if (createDisk.PartitionStyle == PARTITION_STYLE_GPT) 699 { 700 createDisk.Gpt.DiskId = layoutEx->Gpt.DiskId; 701 } 702 703 status = IoCreateDisk(FdoExtension->LowerDevice, &createDisk); 704 } 705 else 706 { 707 // this in fact updates the bus relations 708 PartMgrUpdatePartitionDevices(FdoExtension, layoutEx); 709 710 // write the partition table to the disk 711 status = IoWritePartitionTableEx(FdoExtension->LowerDevice, layoutEx); 712 if (NT_SUCCESS(status)) 713 { 714 // set updated partition numbers 715 for (UINT32 i = 0; i < layoutEx->PartitionCount; i++) 716 { 717 PPARTITION_INFORMATION_EX part = &layoutEx->PartitionEntry[i]; 718 719 part->PartitionNumber = layoutEx->PartitionEntry[i].PartitionNumber; 720 } 721 } 722 } 723 724 // update the layout cache 725 if (NT_SUCCESS(status)) 726 { 727 if (FdoExtension->LayoutCache) 728 { 729 ExFreePool(FdoExtension->LayoutCache); 730 } 731 FdoExtension->LayoutCache = layoutEx; 732 FdoExtension->LayoutValid = TRUE; 733 } 734 else 735 { 736 FdoExtension->LayoutValid = FALSE; 737 } 738 739 PartMgrReleaseLayoutLock(FdoExtension); 740 741 IoInvalidateDeviceRelations(FdoExtension->PhysicalDiskDO, BusRelations); 742 743 // notify everyone that the disk layout has changed 744 TARGET_DEVICE_CUSTOM_NOTIFICATION notification; 745 746 notification.Event = GUID_IO_DISK_LAYOUT_CHANGE; 747 notification.Version = 1; 748 notification.Size = FIELD_OFFSET(TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer); 749 notification.FileObject = NULL; 750 notification.NameBufferOffset = -1; 751 752 IoReportTargetDeviceChangeAsynchronous(FdoExtension->PhysicalDiskDO, 753 ¬ification, 754 NULL, 755 NULL); 756 757 Irp->IoStatus.Information = layoutSize; 758 return STATUS_SUCCESS; 759 } 760 761 static 762 CODE_SEG("PAGE") 763 NTSTATUS 764 FdoIoctlDiskUpdateProperties( 765 _In_ PFDO_EXTENSION FdoExtension, 766 _In_ PIRP Irp) 767 { 768 PAGED_CODE(); 769 770 PartMgrAcquireLayoutLock(FdoExtension); 771 FdoExtension->LayoutValid = FALSE; 772 PartMgrReleaseLayoutLock(FdoExtension); 773 774 IoInvalidateDeviceRelations(FdoExtension->PhysicalDiskDO, BusRelations); 775 return STATUS_SUCCESS; 776 } 777 778 static 779 CODE_SEG("PAGE") 780 NTSTATUS 781 FdoIoctlDiskCreateDisk( 782 _In_ PFDO_EXTENSION FdoExtension, 783 _In_ PIRP Irp) 784 { 785 PAGED_CODE(); 786 787 PCREATE_DISK createDisk = Irp->AssociatedIrp.SystemBuffer; 788 if (!VerifyIrpInBufferSize(Irp, sizeof(*createDisk))) 789 { 790 return STATUS_INFO_LENGTH_MISMATCH; 791 } 792 793 PartMgrAcquireLayoutLock(FdoExtension); 794 795 NTSTATUS status = IoCreateDisk(FdoExtension->LowerDevice, createDisk); 796 797 FdoExtension->LayoutValid = FALSE; 798 PartMgrReleaseLayoutLock(FdoExtension); 799 800 IoInvalidateDeviceRelations(FdoExtension->PhysicalDiskDO, BusRelations); 801 return status; 802 } 803 804 static 805 CODE_SEG("PAGE") 806 NTSTATUS 807 FdoIoctlDiskDeleteDriveLayout( 808 _In_ PFDO_EXTENSION FdoExtension, 809 _In_ PIRP Irp) 810 { 811 CREATE_DISK createDisk = { .PartitionStyle = PARTITION_STYLE_RAW }; 812 813 PAGED_CODE(); 814 815 PartMgrAcquireLayoutLock(FdoExtension); 816 817 NTSTATUS status = IoCreateDisk(FdoExtension->LowerDevice, &createDisk); 818 819 FdoExtension->LayoutValid = FALSE; 820 PartMgrReleaseLayoutLock(FdoExtension); 821 822 IoInvalidateDeviceRelations(FdoExtension->PhysicalDiskDO, BusRelations); 823 return status; 824 } 825 826 static 827 CODE_SEG("PAGE") 828 NTSTATUS 829 FdoHandleStartDevice( 830 _In_ PFDO_EXTENSION FdoExtension, 831 _In_ PIRP Irp) 832 { 833 // obtain the disk device number 834 // this is not expected to change thus not in PartMgrRefreshDiskData 835 STORAGE_DEVICE_NUMBER deviceNumber; 836 NTSTATUS status = IssueSyncIoControlRequest(IOCTL_STORAGE_GET_DEVICE_NUMBER, 837 FdoExtension->LowerDevice, 838 NULL, 839 0, 840 &deviceNumber, 841 sizeof(deviceNumber), 842 FALSE); 843 if (!NT_SUCCESS(status)) 844 { 845 return status; 846 } 847 848 FdoExtension->DiskData.DeviceNumber = deviceNumber.DeviceNumber; 849 850 // register the disk interface 851 // partmgr.sys from Windows 8.1 also registers a mysterious GUID_DEVINTERFACE_HIDDEN_DISK here 852 UNICODE_STRING interfaceName; 853 status = IoRegisterDeviceInterface(FdoExtension->PhysicalDiskDO, 854 &GUID_DEVINTERFACE_DISK, 855 NULL, 856 &interfaceName); 857 858 if(!NT_SUCCESS(status)) 859 { 860 ERR("Failed to register GUID_DEVINTERFACE_DISK, status %x\n", status); 861 return status; 862 } 863 864 FdoExtension->DiskInterfaceName = interfaceName; 865 status = IoSetDeviceInterfaceState(&interfaceName, TRUE); 866 867 INFO("Disk interface %wZ\n", &interfaceName); 868 869 if (!NT_SUCCESS(status)) 870 { 871 RtlFreeUnicodeString(&interfaceName); 872 RtlInitUnicodeString(&FdoExtension->DiskInterfaceName, NULL); 873 } 874 875 return status; 876 } 877 878 // requires partitioning lock held 879 static 880 CODE_SEG("PAGE") 881 NTSTATUS 882 PartMgrRefreshDiskData( 883 _In_ PFDO_EXTENSION FdoExtension) 884 { 885 NTSTATUS status; 886 887 PAGED_CODE(); 888 889 // get the DiskSize and BytesPerSector 890 DISK_GEOMETRY_EX geometryEx; 891 status = IssueSyncIoControlRequest(IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, 892 FdoExtension->LowerDevice, 893 NULL, 894 0, 895 &geometryEx, 896 sizeof(geometryEx), 897 FALSE); 898 if (!NT_SUCCESS(status)) 899 { 900 return status; 901 } 902 903 FdoExtension->DiskData.DiskSize = geometryEx.DiskSize.QuadPart; 904 FdoExtension->DiskData.BytesPerSector = geometryEx.Geometry.BytesPerSector; 905 906 // get the partition style-related info 907 PDRIVE_LAYOUT_INFORMATION_EX layoutEx = NULL; 908 status = PartMgrGetDriveLayout(FdoExtension, &layoutEx); 909 if (!NT_SUCCESS(status)) 910 { 911 return status; 912 } 913 914 FdoExtension->DiskData.PartitionStyle = layoutEx->PartitionStyle; 915 if (FdoExtension->DiskData.PartitionStyle == PARTITION_STYLE_MBR) 916 { 917 FdoExtension->DiskData.Mbr.Signature = layoutEx->Mbr.Signature; 918 // FdoExtension->DiskData.Mbr.Checksum = geometryEx.Partition.Mbr.CheckSum; 919 } 920 else 921 { 922 FdoExtension->DiskData.Gpt.DiskId = layoutEx->Gpt.DiskId; 923 } 924 925 return STATUS_SUCCESS; 926 } 927 928 static 929 CODE_SEG("PAGE") 930 NTSTATUS 931 FdoHandleDeviceRelations( 932 _In_ PFDO_EXTENSION FdoExtension, 933 _In_ PIRP Irp) 934 { 935 PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp); 936 DEVICE_RELATION_TYPE type = ioStack->Parameters.QueryDeviceRelations.Type; 937 938 PAGED_CODE(); 939 940 if (type == BusRelations) 941 { 942 PartMgrAcquireLayoutLock(FdoExtension); 943 944 NTSTATUS status = PartMgrRefreshDiskData(FdoExtension); 945 if (!NT_SUCCESS(status)) 946 { 947 PartMgrReleaseLayoutLock(FdoExtension); 948 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 949 Irp->IoStatus.Information = 0; 950 IoCompleteRequest(Irp, IO_NO_INCREMENT); 951 return Irp->IoStatus.Status; 952 } 953 954 INFO("Partition style %u\n", FdoExtension->DiskData.PartitionStyle); 955 956 // PartMgrAcquireLayoutLock calls PartMgrGetDriveLayout inside 957 // so we're sure here that it returns only cached layout 958 PDRIVE_LAYOUT_INFORMATION_EX layoutEx; 959 PartMgrGetDriveLayout(FdoExtension, &layoutEx); 960 961 PartMgrUpdatePartitionDevices(FdoExtension, layoutEx); 962 963 // now fill the DeviceRelations structure 964 TRACE("Reporting %u partitions\n", FdoExtension->EnumeratedPartitionsTotal); 965 966 PDEVICE_RELATIONS deviceRelations = 967 ExAllocatePoolWithTag(PagedPool, 968 sizeof(DEVICE_RELATIONS) 969 + sizeof(PDEVICE_OBJECT) 970 * (FdoExtension->EnumeratedPartitionsTotal - 1), 971 TAG_PARTMGR); 972 973 if (!deviceRelations) 974 { 975 PartMgrReleaseLayoutLock(FdoExtension); 976 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 977 Irp->IoStatus.Information = 0; 978 IoCompleteRequest(Irp, IO_NO_INCREMENT); 979 return Irp->IoStatus.Status; 980 } 981 982 deviceRelations->Count = 0; 983 984 PSINGLE_LIST_ENTRY curEntry = FdoExtension->PartitionList.Next; 985 while (curEntry != NULL) 986 { 987 PPARTITION_EXTENSION partExt = CONTAINING_RECORD(curEntry, 988 PARTITION_EXTENSION, 989 ListEntry); 990 991 // mark the PDO to know that we don't need to manually delete it 992 partExt->IsEnumerated = TRUE; 993 deviceRelations->Objects[deviceRelations->Count++] = partExt->DeviceObject; 994 ObReferenceObject(partExt->DeviceObject); 995 996 curEntry = partExt->ListEntry.Next; 997 } 998 999 ASSERT(deviceRelations->Count == FdoExtension->EnumeratedPartitionsTotal); 1000 1001 PartMgrReleaseLayoutLock(FdoExtension); 1002 1003 Irp->IoStatus.Information = (ULONG_PTR)deviceRelations; 1004 Irp->IoStatus.Status = STATUS_SUCCESS; 1005 } 1006 1007 IoSkipCurrentIrpStackLocation(Irp); 1008 return IoCallDriver(FdoExtension->LowerDevice, Irp); 1009 } 1010 1011 static 1012 CODE_SEG("PAGE") 1013 NTSTATUS 1014 FdoHandleRemoveDevice( 1015 _In_ PFDO_EXTENSION FdoExtension, 1016 _In_ PIRP Irp) 1017 { 1018 PAGED_CODE(); 1019 1020 if (FdoExtension->DiskInterfaceName.Buffer) 1021 { 1022 IoSetDeviceInterfaceState(&FdoExtension->DiskInterfaceName, FALSE); 1023 RtlFreeUnicodeString(&FdoExtension->DiskInterfaceName); 1024 RtlInitUnicodeString(&FdoExtension->DiskInterfaceName, NULL); 1025 } 1026 1027 // Send the IRP down the stack 1028 IoSkipCurrentIrpStackLocation(Irp); 1029 Irp->IoStatus.Status = STATUS_SUCCESS; 1030 NTSTATUS status = IoCallDriver(FdoExtension->LowerDevice, Irp); 1031 1032 IoDetachDevice(FdoExtension->LowerDevice); 1033 IoDeleteDevice(FdoExtension->DeviceObject); 1034 return status; 1035 } 1036 1037 static 1038 CODE_SEG("PAGE") 1039 NTSTATUS 1040 FdoHandleSurpriseRemoval( 1041 _In_ PFDO_EXTENSION FdoExtension, 1042 _In_ PIRP Irp) 1043 { 1044 PAGED_CODE(); 1045 1046 // all enumerated child devices should receive IRP_MN_REMOVE_DEVICE 1047 // removing only non-enumerated ones here 1048 for (PSINGLE_LIST_ENTRY curEntry = FdoExtension->PartitionList.Next; 1049 curEntry != NULL; 1050 curEntry = curEntry->Next) 1051 { 1052 PPARTITION_EXTENSION partExt = CONTAINING_RECORD(curEntry, 1053 PARTITION_EXTENSION, 1054 ListEntry); 1055 1056 if (partExt->IsEnumerated) 1057 { 1058 PartitionHandleRemove(partExt, TRUE); 1059 } 1060 } 1061 1062 // Send the IRP down the stack 1063 IoSkipCurrentIrpStackLocation(Irp); 1064 Irp->IoStatus.Status = STATUS_SUCCESS; 1065 return IoCallDriver(FdoExtension->LowerDevice, Irp); 1066 } 1067 1068 static 1069 CODE_SEG("PAGE") 1070 NTSTATUS 1071 NTAPI 1072 PartMgrAddDevice( 1073 _In_ PDRIVER_OBJECT DriverObject, 1074 _In_ PDEVICE_OBJECT PhysicalDeviceObject) 1075 { 1076 PDEVICE_OBJECT deviceObject; 1077 1078 PAGED_CODE(); 1079 1080 NTSTATUS status = IoCreateDevice(DriverObject, 1081 sizeof(FDO_EXTENSION), 1082 0, 1083 FILE_DEVICE_BUS_EXTENDER, 1084 FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN, 1085 FALSE, 1086 &deviceObject); 1087 1088 if (!NT_SUCCESS(status)) 1089 { 1090 ERR("Failed to create FDO 0x%x\n", status); 1091 return status; 1092 } 1093 1094 PFDO_EXTENSION deviceExtension = deviceObject->DeviceExtension; 1095 RtlZeroMemory(deviceExtension, sizeof(*deviceExtension)); 1096 1097 deviceExtension->IsFDO = TRUE; 1098 deviceExtension->DeviceObject = deviceObject; 1099 deviceExtension->LowerDevice = IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject); 1100 deviceExtension->PhysicalDiskDO = PhysicalDeviceObject; 1101 KeInitializeEvent(&deviceExtension->SyncEvent, SynchronizationEvent, TRUE); 1102 1103 // the the attaching failed 1104 if (!deviceExtension->LowerDevice) 1105 { 1106 IoDeleteDevice(deviceObject); 1107 1108 return STATUS_DEVICE_REMOVED; 1109 } 1110 deviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE; 1111 1112 // device is initialized 1113 deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 1114 1115 return STATUS_SUCCESS; 1116 } 1117 1118 static 1119 NTSTATUS 1120 NTAPI 1121 PartMgrDeviceControl( 1122 _In_ PDEVICE_OBJECT DeviceObject, 1123 _In_ PIRP Irp) 1124 { 1125 PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp); 1126 PFDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension; 1127 NTSTATUS status; 1128 1129 // Note: IRP_MJ_DEVICE_CONTROL handler in the storage stack must be able to pass IOCTLs 1130 // at an IRQL higher than PASSIVE_LEVEL 1131 1132 INFO("IRP_MJ_DEVICE_CONTROL %p Irp %p IOCTL %x isFdo: %u\n", 1133 DeviceObject, Irp, ioStack->Parameters.DeviceIoControl.IoControlCode, fdoExtension->IsFDO); 1134 1135 if (!fdoExtension->IsFDO) 1136 { 1137 return PartitionHandleDeviceControl(DeviceObject, Irp); 1138 } 1139 1140 switch (ioStack->Parameters.DeviceIoControl.IoControlCode) 1141 { 1142 case IOCTL_DISK_GET_DRIVE_GEOMETRY_EX: 1143 status = FdoIoctlDiskGetDriveGeometryEx(fdoExtension, Irp); 1144 break; 1145 1146 case IOCTL_DISK_GET_PARTITION_INFO: 1147 status = FdoIoctlDiskGetPartitionInfo(fdoExtension, Irp); 1148 break; 1149 1150 case IOCTL_DISK_GET_PARTITION_INFO_EX: 1151 status = FdoIoctlDiskGetPartitionInfoEx(fdoExtension, Irp); 1152 break; 1153 1154 case IOCTL_DISK_GET_DRIVE_LAYOUT: 1155 status = FdoIoctlDiskGetDriveLayout(fdoExtension, Irp); 1156 break; 1157 1158 case IOCTL_DISK_GET_DRIVE_LAYOUT_EX: 1159 status = FdoIoctlDiskGetDriveLayoutEx(fdoExtension, Irp); 1160 break; 1161 1162 case IOCTL_DISK_SET_DRIVE_LAYOUT: 1163 status = FdoIoctlDiskSetDriveLayout(fdoExtension, Irp); 1164 break; 1165 1166 case IOCTL_DISK_SET_DRIVE_LAYOUT_EX: 1167 status = FdoIoctlDiskSetDriveLayoutEx(fdoExtension, Irp); 1168 break; 1169 1170 case IOCTL_DISK_UPDATE_PROPERTIES: 1171 status = FdoIoctlDiskUpdateProperties(fdoExtension, Irp); 1172 break; 1173 1174 case IOCTL_DISK_CREATE_DISK: 1175 status = FdoIoctlDiskCreateDisk(fdoExtension, Irp); 1176 break; 1177 1178 case IOCTL_DISK_DELETE_DRIVE_LAYOUT: 1179 status = FdoIoctlDiskDeleteDriveLayout(fdoExtension, Irp); 1180 break; 1181 // case IOCTL_DISK_GROW_PARTITION: // todo 1182 default: 1183 return ForwardIrpAndForget(DeviceObject, Irp); 1184 } 1185 1186 Irp->IoStatus.Status = status; 1187 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1188 return status; 1189 } 1190 1191 static 1192 CODE_SEG("PAGE") 1193 NTSTATUS 1194 NTAPI 1195 PartMgrPnp( 1196 _In_ PDEVICE_OBJECT DeviceObject, 1197 _In_ PIRP Irp) 1198 { 1199 PAGED_CODE(); 1200 1201 PFDO_EXTENSION fdoExtension = DeviceObject->DeviceExtension; 1202 PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp); 1203 1204 INFO("IRP_MJ_PNP %p Irp %p %s isFDO: %u\n", 1205 DeviceObject, Irp, GetIRPMinorFunctionString(ioStack->MinorFunction), fdoExtension->IsFDO); 1206 1207 if (!fdoExtension->IsFDO) 1208 { 1209 return PartitionHandlePnp(DeviceObject, Irp); 1210 } 1211 1212 switch (ioStack->MinorFunction) { 1213 1214 case IRP_MN_START_DEVICE: 1215 { 1216 NTSTATUS status; 1217 1218 // if this is sent to the FDO so we should forward it down the 1219 // attachment chain before we can start the FDO 1220 1221 if (!IoForwardIrpSynchronously(fdoExtension->LowerDevice, Irp)) 1222 { 1223 status = STATUS_UNSUCCESSFUL; 1224 } 1225 else 1226 { 1227 status = FdoHandleStartDevice(fdoExtension, Irp); 1228 } 1229 1230 Irp->IoStatus.Status = status; 1231 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1232 return status; 1233 } 1234 case IRP_MN_QUERY_DEVICE_RELATIONS: 1235 { 1236 return FdoHandleDeviceRelations(fdoExtension, Irp); 1237 } 1238 case IRP_MN_SURPRISE_REMOVAL: 1239 { 1240 return FdoHandleSurpriseRemoval(fdoExtension, Irp); 1241 } 1242 case IRP_MN_REMOVE_DEVICE: 1243 { 1244 return FdoHandleRemoveDevice(fdoExtension, Irp); 1245 } 1246 case IRP_MN_QUERY_STOP_DEVICE: 1247 case IRP_MN_QUERY_REMOVE_DEVICE: 1248 case IRP_MN_CANCEL_STOP_DEVICE: 1249 case IRP_MN_CANCEL_REMOVE_DEVICE: 1250 case IRP_MN_STOP_DEVICE: 1251 { 1252 Irp->IoStatus.Status = STATUS_SUCCESS; 1253 // fallthrough 1254 } 1255 default: 1256 { 1257 IoSkipCurrentIrpStackLocation(Irp); 1258 return IoCallDriver(fdoExtension->LowerDevice, Irp); 1259 } 1260 } 1261 } 1262 1263 static 1264 NTSTATUS 1265 NTAPI 1266 PartMgrReadWrite( 1267 _In_ PDEVICE_OBJECT DeviceObject, 1268 _In_ PIRP Irp) 1269 { 1270 PPARTITION_EXTENSION partExt = DeviceObject->DeviceExtension; 1271 PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp); 1272 1273 if (!partExt->IsFDO) 1274 { 1275 if (!partExt->IsEnumerated) 1276 { 1277 Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST; 1278 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1279 return STATUS_DEVICE_DOES_NOT_EXIST; 1280 } 1281 else 1282 { 1283 ioStack->Parameters.Read.ByteOffset.QuadPart += partExt->StartingOffset; 1284 } 1285 } 1286 1287 IoSkipCurrentIrpStackLocation(Irp); 1288 return IoCallDriver(partExt->LowerDevice, Irp); 1289 } 1290 1291 DRIVER_DISPATCH PartMgrPower; 1292 NTSTATUS 1293 NTAPI 1294 PartMgrPower( 1295 _In_ PDEVICE_OBJECT DeviceObject, 1296 _In_ PIRP Irp) 1297 { 1298 PPARTITION_EXTENSION partExt = DeviceObject->DeviceExtension; 1299 PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp); 1300 1301 PoStartNextPowerIrp(Irp); 1302 1303 if (!partExt->IsFDO) 1304 { 1305 NTSTATUS status; 1306 1307 if (!partExt->IsEnumerated) 1308 { 1309 status = STATUS_DEVICE_DOES_NOT_EXIST; 1310 } 1311 else if (ioStack->MinorFunction == IRP_MN_SET_POWER || 1312 ioStack->MinorFunction == IRP_MN_QUERY_POWER) 1313 { 1314 status = STATUS_SUCCESS; 1315 } 1316 else 1317 { 1318 status = Irp->IoStatus.Status; 1319 } 1320 1321 Irp->IoStatus.Status = status; 1322 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1323 return status; 1324 } 1325 else 1326 { 1327 IoSkipCurrentIrpStackLocation(Irp); 1328 return PoCallDriver(partExt->LowerDevice, Irp); 1329 } 1330 } 1331 1332 DRIVER_DISPATCH PartMgrShutdownFlush; 1333 NTSTATUS 1334 NTAPI 1335 PartMgrShutdownFlush( 1336 _In_ PDEVICE_OBJECT DeviceObject, 1337 _In_ PIRP Irp) 1338 { 1339 PPARTITION_EXTENSION partExt = DeviceObject->DeviceExtension; 1340 PDEVICE_OBJECT lowerDevice; 1341 1342 // forward to the partition0 device in both cases 1343 if (!partExt->IsFDO) 1344 { 1345 if (!partExt->IsEnumerated) 1346 { 1347 Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST; 1348 IoCompleteRequest(Irp, IO_NO_INCREMENT); 1349 return STATUS_DEVICE_DOES_NOT_EXIST; 1350 } 1351 else 1352 { 1353 PFDO_EXTENSION fdoExtension = partExt->LowerDevice->DeviceExtension; 1354 lowerDevice = fdoExtension->LowerDevice; 1355 } 1356 } 1357 else 1358 { 1359 lowerDevice = partExt->LowerDevice; 1360 } 1361 1362 IoSkipCurrentIrpStackLocation(Irp); 1363 return IoCallDriver(lowerDevice, Irp); 1364 } 1365 1366 CODE_SEG("PAGE") 1367 VOID 1368 NTAPI 1369 PartMgrUnload( 1370 _In_ PDRIVER_OBJECT DriverObject) 1371 { 1372 1373 } 1374 1375 CODE_SEG("INIT") 1376 NTSTATUS 1377 NTAPI 1378 DriverEntry( 1379 _In_ PDRIVER_OBJECT DriverObject, 1380 _In_ PUNICODE_STRING RegistryPath) 1381 { 1382 DriverObject->DriverUnload = PartMgrUnload; 1383 DriverObject->DriverExtension->AddDevice = PartMgrAddDevice; 1384 DriverObject->MajorFunction[IRP_MJ_CREATE] = ForwardIrpAndForget; 1385 DriverObject->MajorFunction[IRP_MJ_CLOSE] = ForwardIrpAndForget; 1386 DriverObject->MajorFunction[IRP_MJ_READ] = PartMgrReadWrite; 1387 DriverObject->MajorFunction[IRP_MJ_WRITE] = PartMgrReadWrite; 1388 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PartMgrDeviceControl; 1389 DriverObject->MajorFunction[IRP_MJ_PNP] = PartMgrPnp; 1390 DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = PartMgrShutdownFlush; 1391 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = PartMgrShutdownFlush; 1392 DriverObject->MajorFunction[IRP_MJ_POWER] = PartMgrPower; 1393 1394 return STATUS_SUCCESS; 1395 } 1396