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