ReactOS 0.4.16-dev-112-g52265ae
partition.c File Reference
#include "partmgr.h"
Include dependency graph for partition.c:

Go to the source code of this file.

Functions

NTSTATUS PartitionCreateDevice (_In_ PDEVICE_OBJECT FDObject, _In_ PPARTITION_INFORMATION_EX PartitionEntry, _In_ UINT32 PdoNumber, _In_ PARTITION_STYLE PartitionStyle, _Out_ PDEVICE_OBJECT *PDO)
 
static NTSTATUS PartitionHandleStartDevice (_In_ PPARTITION_EXTENSION PartExt, _In_ PIRP Irp)
 
static NTSTATUS VolumeDeleteMountPoints (_In_ PPARTITION_EXTENSION PartExt)
 Notifies MountMgr to delete all mount points associated with the given volume.
 
NTSTATUS PartitionHandleRemove (_In_ PPARTITION_EXTENSION PartExt, _In_ BOOLEAN FinalRemove)
 
static NTSTATUS PartitionHandleDeviceRelations (_In_ PPARTITION_EXTENSION PartExt, _In_ PIRP Irp)
 
static NTSTATUS PartitionHandleQueryId (_In_ PPARTITION_EXTENSION PartExt, _In_ PIRP Irp)
 
static NTSTATUS PartitionHandleQueryCapabilities (_In_ PPARTITION_EXTENSION PartExt, _In_ PIRP Irp)
 
NTSTATUS PartitionHandlePnp (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp)
 
NTSTATUS PartitionHandleDeviceControl (_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp)
 

Variables

static const WCHAR PartitionSymLinkFormat [] = L"\\Device\\Harddisk%lu\\Partition%lu"
 

Function Documentation

◆ PartitionCreateDevice()

NTSTATUS PartitionCreateDevice ( _In_ PDEVICE_OBJECT  FDObject,
_In_ PPARTITION_INFORMATION_EX  PartitionEntry,
_In_ UINT32  PdoNumber,
_In_ PARTITION_STYLE  PartitionStyle,
_Out_ PDEVICE_OBJECT PDO 
)

Definition at line 15 of file partition.c.

21{
22 PAGED_CODE();
23
24 static UINT32 HarddiskVolumeNextId = 1; // this is 1-based
25
26 WCHAR nameBuf[64];
27 UNICODE_STRING deviceName;
28 UINT32 volumeNum;
29
30 // create the device object
31
32 volumeNum = HarddiskVolumeNextId++;
33 swprintf(nameBuf, L"\\Device\\HarddiskVolume%lu", volumeNum);
34 RtlCreateUnicodeString(&deviceName, nameBuf);
35
36 PDEVICE_OBJECT partitionDevice;
37 NTSTATUS status = IoCreateDevice(FDObject->DriverObject,
38 sizeof(PARTITION_EXTENSION),
39 &deviceName,
42 FALSE,
43 &partitionDevice);
44
45 if (!NT_SUCCESS(status))
46 {
47 ERR("Unable to create device object %wZ\n", &deviceName);
48 return status;
49 }
50
51 INFO("Created device object %p %wZ\n", partitionDevice, &deviceName);
52
53 PPARTITION_EXTENSION partExt = partitionDevice->DeviceExtension;
54 RtlZeroMemory(partExt, sizeof(*partExt));
55
56 partitionDevice->StackSize = FDObject->StackSize;
57 partitionDevice->Flags |= DO_DIRECT_IO;
58
59 if (PartitionStyle == PARTITION_STYLE_MBR)
60 {
61 partExt->Mbr.PartitionType = PartitionEntry->Mbr.PartitionType;
62 partExt->Mbr.BootIndicator = PartitionEntry->Mbr.BootIndicator;
63 partExt->Mbr.HiddenSectors = PartitionEntry->Mbr.HiddenSectors;
64 }
65 else
66 {
67 partExt->Gpt.PartitionType = PartitionEntry->Gpt.PartitionType;
68 partExt->Gpt.PartitionId = PartitionEntry->Gpt.PartitionId;
69 partExt->Gpt.Attributes = PartitionEntry->Gpt.Attributes;
70
71 RtlCopyMemory(partExt->Gpt.Name, PartitionEntry->Gpt.Name, sizeof(partExt->Gpt.Name));
72 }
73
74 partExt->DeviceName = deviceName;
75 partExt->StartingOffset = PartitionEntry->StartingOffset.QuadPart;
76 partExt->PartitionLength = PartitionEntry->PartitionLength.QuadPart;
77 partExt->OnDiskNumber = PartitionEntry->PartitionNumber; // the "physical" partition number
78 partExt->DetectedNumber = PdoNumber; // counts only partitions with PDO created
79 partExt->VolumeNumber = volumeNum;
80
81 partExt->DeviceObject = partitionDevice;
82 partExt->LowerDevice = FDObject;
83
84 partitionDevice->Flags &= ~DO_DEVICE_INITIALIZING;
85
86 *PDO = partitionDevice;
87
88 return status;
89}
#define PAGED_CODE()
unsigned int UINT32
LONG NTSTATUS
Definition: precomp.h:26
#define ERR(fmt,...)
Definition: precomp.h:57
#define FILE_DEVICE_SECURE_OPEN
Definition: cdrw_usr.h:46
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define swprintf
Definition: precomp.h:40
#define INFO
Definition: debug.h:89
#define DO_DIRECT_IO
Definition: env_spec_w32.h:396
@ PARTITION_STYLE_MBR
Definition: imports.h:201
NTSTATUS NTAPI IoCreateDevice(IN PDRIVER_OBJECT DriverObject, IN ULONG DeviceExtensionSize, IN PUNICODE_STRING DeviceName, IN DEVICE_TYPE DeviceType, IN ULONG DeviceCharacteristics, IN BOOLEAN Exclusive, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1031
#define L(x)
Definition: ntvdm.h:50
#define FILE_DEVICE_DISK
Definition: winioctl.h:52
PVOID DeviceExtension
Definition: env_spec_w32.h:418
UINT64 StartingOffset
Definition: partmgr.h:96
struct _PARTITION_EXTENSION::@1330::@1333 Mbr
PDEVICE_OBJECT LowerDevice
Definition: partmgr.h:93
struct _PARTITION_EXTENSION::@1330::@1332 Gpt
UINT32 DetectedNumber
Definition: partmgr.h:101
UNICODE_STRING DeviceName
Definition: partmgr.h:125
UINT64 PartitionLength
Definition: partmgr.h:97
PDEVICE_OBJECT DeviceObject
Definition: partmgr.h:92
Definition: ps.c:97
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by PartMgrUpdatePartitionDevices().

◆ PartitionHandleDeviceControl()

NTSTATUS PartitionHandleDeviceControl ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ PIRP  Irp 
)

Definition at line 563 of file partition.c.

566{
568 PPARTITION_EXTENSION partExt = DeviceObject->DeviceExtension;
569 PFDO_EXTENSION fdoExtension = partExt->LowerDevice->DeviceExtension;
571
572 ASSERT(!partExt->IsFDO);
573
574 if (!partExt->IsEnumerated)
575 {
576 Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
579 }
580
581 switch (ioStack->Parameters.DeviceIoControl.IoControlCode)
582 {
583 // disk stuff
585 {
587 {
589 break;
590 }
591
592 PartMgrAcquireLayoutLock(fdoExtension);
593
594 // not supported on anything other than MBR
595 if (fdoExtension->DiskData.PartitionStyle != PARTITION_STYLE_MBR)
596 {
598 PartMgrReleaseLayoutLock(fdoExtension);
599 break;
600 }
601
602 PPARTITION_INFORMATION partInfo = Irp->AssociatedIrp.SystemBuffer;
603
604 *partInfo = (PARTITION_INFORMATION){
605 .PartitionType = partExt->Mbr.PartitionType,
606 .StartingOffset.QuadPart = partExt->StartingOffset,
607 .PartitionLength.QuadPart = partExt->PartitionLength,
608 .HiddenSectors = partExt->Mbr.HiddenSectors,
609 .PartitionNumber = partExt->DetectedNumber,
610 .BootIndicator = partExt->Mbr.BootIndicator,
611 .RecognizedPartition = partExt->Mbr.RecognizedPartition,
612 .RewritePartition = FALSE,
613 };
614
615 PartMgrReleaseLayoutLock(fdoExtension);
616
617 Irp->IoStatus.Information = sizeof(*partInfo);
619 break;
620 }
622 {
624 {
626 break;
627 }
628
629 PPARTITION_INFORMATION_EX partInfoEx = Irp->AssociatedIrp.SystemBuffer;
630
631 PartMgrAcquireLayoutLock(fdoExtension);
632
633 *partInfoEx = (PARTITION_INFORMATION_EX){
635 .PartitionLength.QuadPart = partExt->PartitionLength,
636 .PartitionNumber = partExt->DetectedNumber,
637 .PartitionStyle = fdoExtension->DiskData.PartitionStyle,
638 .RewritePartition = FALSE,
639 };
640
641 if (fdoExtension->DiskData.PartitionStyle == PARTITION_STYLE_MBR)
642 {
643 partInfoEx->Mbr = (PARTITION_INFORMATION_MBR){
644 .PartitionType = partExt->Mbr.PartitionType,
645 .HiddenSectors = partExt->Mbr.HiddenSectors,
646 .BootIndicator = partExt->Mbr.BootIndicator,
647 .RecognizedPartition = partExt->Mbr.RecognizedPartition,
648 };
649 }
650 else
651 {
652 partInfoEx->Gpt = (PARTITION_INFORMATION_GPT){
653 .PartitionType = partExt->Gpt.PartitionType,
654 .PartitionId = partExt->Gpt.PartitionId,
655 .Attributes = partExt->Gpt.Attributes,
656 };
657
658 RtlCopyMemory(partInfoEx->Gpt.Name,
659 partExt->Gpt.Name,
660 sizeof(partInfoEx->Gpt.Name));
661 }
662
663 PartMgrReleaseLayoutLock(fdoExtension);
664
665 Irp->IoStatus.Information = sizeof(*partInfoEx);
667 break;
668 }
670 {
671 PSET_PARTITION_INFORMATION inputBuffer = Irp->AssociatedIrp.SystemBuffer;
672 if (!VerifyIrpInBufferSize(Irp, sizeof(*inputBuffer)))
673 {
675 break;
676 }
677
678 PartMgrAcquireLayoutLock(fdoExtension);
679
680 // these functions use on disk numbers, not detected ones
682 fdoExtension->DiskData.BytesPerSector,
683 partExt->OnDiskNumber,
684 inputBuffer->PartitionType);
685
686 if (NT_SUCCESS(status))
687 {
688 partExt->Mbr.PartitionType = inputBuffer->PartitionType;
689 }
690
691 PartMgrReleaseLayoutLock(fdoExtension);
692
693 Irp->IoStatus.Information = 0;
694 break;
695 }
697 {
698 PSET_PARTITION_INFORMATION_EX inputBuffer = Irp->AssociatedIrp.SystemBuffer;
699 if (!VerifyIrpInBufferSize(Irp, sizeof(*inputBuffer)))
700 {
702 break;
703 }
704
705 PartMgrAcquireLayoutLock(fdoExtension);
706
707 // these functions use on disk numbers, not detected ones
709 partExt->OnDiskNumber,
710 inputBuffer);
711
712 if (NT_SUCCESS(status))
713 {
714 if (fdoExtension->DiskData.PartitionStyle == PARTITION_STYLE_MBR)
715 {
716 partExt->Mbr.PartitionType = inputBuffer->Mbr.PartitionType;
717 }
718 else
719 {
720 partExt->Gpt.PartitionType = inputBuffer->Gpt.PartitionType;
721 partExt->Gpt.PartitionId = inputBuffer->Gpt.PartitionId;
722 partExt->Gpt.Attributes = inputBuffer->Gpt.Attributes;
723
724 RtlMoveMemory(partExt->Gpt.Name,
725 inputBuffer->Gpt.Name,
726 sizeof(partExt->Gpt.Name));
727 }
728 }
729
730 PartMgrReleaseLayoutLock(fdoExtension);
731
732 Irp->IoStatus.Information = 0;
733 break;
734 }
736 {
737 PGET_LENGTH_INFORMATION lengthInfo = Irp->AssociatedIrp.SystemBuffer;
738 if (!VerifyIrpOutBufferSize(Irp, sizeof(*lengthInfo)))
739 {
741 break;
742 }
743
744 PartMgrAcquireLayoutLock(fdoExtension);
745
746 lengthInfo->Length.QuadPart = partExt->PartitionLength;
747
748 PartMgrReleaseLayoutLock(fdoExtension);
749
751 Irp->IoStatus.Information = sizeof(*lengthInfo);
752 break;
753 }
755 {
756 PVERIFY_INFORMATION verifyInfo = Irp->AssociatedIrp.SystemBuffer;
757 if (!VerifyIrpInBufferSize(Irp, sizeof(*verifyInfo)))
758 {
760 break;
761 }
762
763 // Partition device should just adjust the starting offset
764 verifyInfo->StartingOffset.QuadPart += partExt->StartingOffset;
766 }
768 {
769 fdoExtension->LayoutValid = FALSE;
771
773 break;
774 }
776 {
778 }
779 // volume stuff (most of that should be in volmgr.sys once it is implemented)
781 {
782 PVOLUME_DISK_EXTENTS volExts = Irp->AssociatedIrp.SystemBuffer;
783
784 // we fill only one extent entry so sizeof(*volExts) is enough
785 if (!VerifyIrpOutBufferSize(Irp, sizeof(*volExts)))
786 {
788 break;
789 }
790
791 PartMgrAcquireLayoutLock(fdoExtension);
792
793 // the only type of volume we support right now is disk partition
794 // so this structure is simple
795
796 *volExts = (VOLUME_DISK_EXTENTS) {
798 .Extents = {{
799 .DiskNumber = fdoExtension->DiskData.DeviceNumber,
800 .StartingOffset.QuadPart = partExt->StartingOffset,
801 .ExtentLength.QuadPart = partExt->PartitionLength
802 }}
803 };
804
805 PartMgrReleaseLayoutLock(fdoExtension);
806
808 Irp->IoStatus.Information = sizeof(*volExts);
809 break;
810 }
812 {
813 PVOLUME_NUMBER volNum = Irp->AssociatedIrp.SystemBuffer;
814 if (!VerifyIrpOutBufferSize(Irp, sizeof(*volNum)))
815 {
817 break;
818 }
819
820 PartMgrAcquireLayoutLock(fdoExtension);
821
822 volNum->VolumeNumber = partExt->VolumeNumber;
824 L"VOLMGR ", // Must be 8 space-padded characters
825 sizeof(volNum->VolumeManagerName));
826
827 PartMgrReleaseLayoutLock(fdoExtension);
828
830 Irp->IoStatus.Information = sizeof(*volNum);
831 break;
832 }
834 {
835 // The only type of volume we support right now is disk partition
836 // so we just return success. A more robust algorithm would be
837 // to check whether the volume has only one single extent, that
838 // covers the whole partition on which it lies upon. If this is
839 // not the case, return STATUS_UNSUCCESSFUL instead.
841 break;
842 }
844 {
846 break;
847 }
849 {
850 PVOLUME_GET_GPT_ATTRIBUTES_INFORMATION gptAttrs = Irp->AssociatedIrp.SystemBuffer;
851 if (!VerifyIrpOutBufferSize(Irp, sizeof(*gptAttrs)))
852 {
854 break;
855 }
856
857 // not supported on anything other than GPT
858 if (fdoExtension->DiskData.PartitionStyle != PARTITION_STYLE_GPT)
859 {
861 break;
862 }
863
864 gptAttrs->GptAttributes = partExt->Gpt.Attributes;
865
867 Irp->IoStatus.Information = sizeof(*gptAttrs);
868 break;
869 }
870 // mountmgr notifications (these should be in volmgr.sys once it is implemented)
872 {
873 PMOUNTDEV_NAME name = Irp->AssociatedIrp.SystemBuffer;
874
875 if (!VerifyIrpOutBufferSize(Irp, sizeof(USHORT)))
876 {
878 break;
879 }
880
881 name->NameLength = partExt->DeviceName.Length;
882
883 // return NameLength back
884 if (!VerifyIrpOutBufferSize(Irp, sizeof(USHORT) + name->NameLength))
885 {
886 Irp->IoStatus.Information = sizeof(USHORT);
888 break;
889 }
890
891 RtlCopyMemory(name->Name, partExt->DeviceName.Buffer, name->NameLength);
892
894 Irp->IoStatus.Information = sizeof(USHORT) + name->NameLength;
895 break;
896 }
898 {
899 const SIZE_T headerSize = FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId);
900 PMOUNTDEV_UNIQUE_ID uniqueId = Irp->AssociatedIrp.SystemBuffer;
902 PUNICODE_STRING InterfaceName;
903
904 // Check whether the minimal header size was provided
905 if (!VerifyIrpOutBufferSize(Irp, headerSize))
906 {
908 break;
909 }
910
911 PartMgrAcquireLayoutLock(fdoExtension);
912
913 InterfaceName = &partExt->VolumeInterfaceName;
914 if (fdoExtension->IsSuperFloppy)
915 InterfaceName = &fdoExtension->DiskInterfaceName;
916
917 // Calculate and return the necessary data size
918 if ((fdoExtension->DiskData.PartitionStyle == PARTITION_STYLE_MBR) &&
919 !fdoExtension->IsSuperFloppy)
920 {
921 uniqueId->UniqueIdLength = sizeof(basicVolId->Mbr);
922 }
923 else if (fdoExtension->DiskData.PartitionStyle == PARTITION_STYLE_GPT)
924 {
925 uniqueId->UniqueIdLength = sizeof(basicVolId->Gpt);
926 }
927 else
928 {
929 if (!InterfaceName->Buffer || !InterfaceName->Length)
930 {
931 PartMgrReleaseLayoutLock(fdoExtension);
933 break;
934 }
935 uniqueId->UniqueIdLength = InterfaceName->Length;
936 }
937
938 // Return UniqueIdLength back
939 if (!VerifyIrpOutBufferSize(Irp, headerSize + uniqueId->UniqueIdLength))
940 {
941 PartMgrReleaseLayoutLock(fdoExtension);
942 Irp->IoStatus.Information = headerSize;
944 break;
945 }
946
947 //
948 // Write the UniqueId
949 //
950 // Format:
951 // - Basic volume on MBR disk: disk Mbr.Signature + partition StartingOffset (length: 0x0C)
952 // - Basic volume on GPT disk: "DMIO:ID:" + Gpt.PartitionGuid (length: 0x18)
953 // - Volume on Basic disk (NT <= 4): 8-byte FTDisk identifier (length: 0x08)
954 // - Volume on Dynamic disk (NT 5+): "DMIO:ID:" + dmio VolumeGuid (length: 0x18)
955 // - Super-floppy (single-partition with StartingOffset == 0),
956 // or Removable media: DiskInterfaceName.
957 // - As fallback, we use the VolumeInterfaceName.
958 //
959 if ((fdoExtension->DiskData.PartitionStyle == PARTITION_STYLE_MBR) &&
960 !fdoExtension->IsSuperFloppy)
961 {
962 basicVolId->Mbr.Signature = fdoExtension->DiskData.Mbr.Signature;
963 basicVolId->Mbr.StartingOffset = partExt->StartingOffset;
964 }
965 else if (fdoExtension->DiskData.PartitionStyle == PARTITION_STYLE_GPT)
966 {
967 basicVolId->Gpt.Signature = DMIO_ID_SIGNATURE;
968 basicVolId->Gpt.PartitionGuid = partExt->Gpt.PartitionId;
969 }
970 else
971 {
972 RtlCopyMemory(uniqueId->UniqueId,
973 InterfaceName->Buffer,
974 uniqueId->UniqueIdLength);
975 }
976
977 PartMgrReleaseLayoutLock(fdoExtension);
978
980 Irp->IoStatus.Information = headerSize + uniqueId->UniqueIdLength;
981 break;
982 }
986#if (NTDDI_VERSION >= NTDDI_WS03)
987 /* Deprecated Windows 2000/XP versions of IOCTL_MOUNTDEV_LINK_[CREATED|DELETED]
988 * without access protection, that were updated in Windows 2003 */
991#endif
994 {
995 WARN("Ignored MountMgr notification: 0x%lX\n",
996 ioStack->Parameters.DeviceIoControl.IoControlCode);
998 break;
999 }
1000 default:
1002 }
1003
1004 Irp->IoStatus.Status = status;
1006 return status;
1007}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define WARN(fmt,...)
Definition: precomp.h:61
NTSTATUS FASTCALL IoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN ULONG PartitionNumber, IN ULONG PartitionType)
Definition: ntoskrnl.c:46
#define IOCTL_DISK_VERIFY
Definition: cdrw_usr.h:170
_In_ PIRP Irp
Definition: csq.h:116
#define IOCTL_DISK_GET_PARTITION_INFO_EX
Definition: ntddk_ex.h:206
NTSTATUS NTAPI IoSetPartitionInformationEx(IN PDEVICE_OBJECT DeviceObject, IN ULONG PartitionNumber, IN PSET_PARTITION_INFORMATION_EX PartitionInfo)
Definition: fstubex.c:2347
DRIVER_DISPATCH ForwardIrpAndForget
Definition: i8042prt.h:341
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
#define IOCTL_MOUNTDEV_LINK_CREATED
Definition: imports.h:104
#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
Definition: imports.h:91
#define IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME
Definition: imports.h:97
#define IOCTL_MOUNTDEV_QUERY_STABLE_GUID
Definition: imports.h:255
struct _PARTITION_INFORMATION_EX PARTITION_INFORMATION_EX
#define IOCTL_DISK_GET_LENGTH_INFO
Definition: imports.h:192
#define MOUNTDEVCONTROLTYPE
Definition: imports.h:76
#define IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
Definition: imports.h:78
#define IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY
Definition: imports.h:84
struct _PARTITION_INFORMATION_MBR PARTITION_INFORMATION_MBR
@ PARTITION_STYLE_GPT
Definition: imports.h:202
#define IOCTL_MOUNTDEV_LINK_DELETED
Definition: imports.h:110
struct _PARTITION_INFORMATION_GPT PARTITION_INFORMATION_GPT
#define CTL_CODE(DeviceType, Function, Method, Access)
Definition: nt_native.h:586
#define FILE_ANY_ACCESS
Definition: nt_native.h:609
#define METHOD_BUFFERED
Definition: nt_native.h:594
#define IOCTL_DISK_SET_PARTITION_INFO
Definition: ntdddisk.h:214
#define IOCTL_DISK_SET_PARTITION_INFO_EX
Definition: ntdddisk.h:217
struct _PARTITION_INFORMATION PARTITION_INFORMATION
#define IOCTL_DISK_GET_PARTITION_INFO
Definition: ntdddisk.h:106
#define IOCTL_DISK_UPDATE_PROPERTIES
Definition: ntdddisk.h:242
#define IOCTL_STORAGE_MEDIA_REMOVAL
Definition: ntddstor.h:104
#define IOCTL_VOLUME_QUERY_VOLUME_NUMBER
Definition: ntddvol.h:85
#define IOCTL_VOLUME_GET_GPT_ATTRIBUTES
Definition: ntddvol.h:133
struct _VOLUME_DISK_EXTENTS VOLUME_DISK_EXTENTS
#define IOCTL_VOLUME_ONLINE
Definition: ntddvol.h:63
#define IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
Definition: ntddvol.h:44
#define IOCTL_VOLUME_IS_PARTITION
Definition: ntddvol.h:118
#define IoCompleteRequest
Definition: irp.c:1240
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define STATUS_DEVICE_DOES_NOT_EXIST
Definition: ntstatus.h:428
union _BASIC_VOLUME_UNIQUE_ID * PBASIC_VOLUME_UNIQUE_ID
FORCEINLINE VOID PartMgrReleaseLayoutLock(_In_ PFDO_EXTENSION FDOExtension)
Definition: partmgr.h:212
FORCEINLINE VOID PartMgrAcquireLayoutLock(_In_ PFDO_EXTENSION FDOExtension)
Definition: partmgr.h:202
FORCEINLINE BOOLEAN VerifyIrpInBufferSize(_In_ PIRP Irp, _In_ SIZE_T Size)
Definition: partmgr.h:187
#define DMIO_ID_SIGNATURE
Definition: partmgr.h:55
FORCEINLINE BOOLEAN VerifyIrpOutBufferSize(_In_ PIRP Irp, _In_ SIZE_T Size)
Definition: partmgr.h:172
unsigned short USHORT
Definition: pedump.c:61
VOID NTAPI IoInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject, IN DEVICE_RELATION_TYPE Type)
Definition: pnpmgr.c:1772
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
PDEVICE_OBJECT PhysicalDiskDO
Definition: partmgr.h:62
struct _FDO_EXTENSION::@1325 DiskData
PDEVICE_OBJECT LowerDevice
Definition: partmgr.h:61
BOOLEAN LayoutValid
Definition: partmgr.h:65
BOOLEAN IsSuperFloppy
Definition: partmgr.h:70
UNICODE_STRING DiskInterfaceName
Definition: partmgr.h:86
LARGE_INTEGER Length
Definition: imports.h:232
struct _IO_STACK_LOCATION::@1575::@1576 DeviceIoControl
union _IO_STACK_LOCATION::@1575 Parameters
USHORT UniqueIdLength
Definition: imports.h:136
UCHAR UniqueId[1]
Definition: imports.h:137
UNICODE_STRING VolumeInterfaceName
Definition: partmgr.h:124
BOOLEAN IsEnumerated
Definition: partmgr.h:103
LARGE_INTEGER StartingOffset
Definition: imports.h:221
PARTITION_INFORMATION_MBR Mbr
Definition: imports.h:226
PARTITION_INFORMATION_GPT Gpt
Definition: imports.h:227
LARGE_INTEGER StartingOffset
Definition: ntdddisk.h:651
ULONG NumberOfDiskExtents
Definition: ntddvol.h:54
WCHAR VolumeManagerName[8]
Definition: ntddvol.h:96
ULONG VolumeNumber
Definition: ntddvol.h:95
Definition: name.c:39
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
struct _BASIC_VOLUME_UNIQUE_ID::@1324 Gpt
struct _BASIC_VOLUME_UNIQUE_ID::@1323 Mbr
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
@ BusRelations
Definition: iotypes.h:2152
#define IO_NO_INCREMENT
Definition: iotypes.h:598

Referenced by PartMgrDeviceControl().

◆ PartitionHandleDeviceRelations()

static NTSTATUS PartitionHandleDeviceRelations ( _In_ PPARTITION_EXTENSION  PartExt,
_In_ PIRP  Irp 
)
static

Definition at line 361 of file partition.c.

364{
365 PAGED_CODE();
366
369
371 {
372 // Device relations have one entry built into their size.
373 PDEVICE_RELATIONS deviceRelations =
375
376 if (deviceRelations != NULL)
377 {
378 deviceRelations->Count = 1;
379 deviceRelations->Objects[0] = PartExt->DeviceObject;
380 ObReferenceObject(deviceRelations->Objects[0]);
381
382 Irp->IoStatus.Information = (ULONG_PTR)deviceRelations;
383 return STATUS_SUCCESS;
384 }
385 else
386 {
388 }
389 }
390 else
391 {
392 Irp->IoStatus.Information = 0;
393 return Irp->IoStatus.Status;
394 }
395}
#define NULL
Definition: types.h:112
#define ULONG_PTR
Definition: config.h:101
#define PagedPool
Definition: env_spec_w32.h:308
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
FORCEINLINE PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
Definition: precomp.h:45
#define TAG_PARTMGR
Definition: partmgr.h:23
PDEVICE_OBJECT Objects[1]
Definition: iotypes.h:2163
struct _IO_STACK_LOCATION::@3974::@3999 QueryDeviceRelations
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
@ TargetDeviceRelation
Definition: iotypes.h:2156
enum _DEVICE_RELATION_TYPE DEVICE_RELATION_TYPE
#define ObReferenceObject
Definition: obfuncs.h:204

Referenced by PartitionHandlePnp().

◆ PartitionHandlePnp()

NTSTATUS PartitionHandlePnp ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ PIRP  Irp 
)

Definition at line 499 of file partition.c.

502{
503 PPARTITION_EXTENSION partExt = DeviceObject->DeviceExtension;
506
507 PAGED_CODE();
508
509 switch (ioStack->MinorFunction)
510 {
512 {
514 break;
515 }
517 {
519 break;
520 }
526 {
528 break;
529 }
531 {
533 break;
534 }
536 {
538 break;
539 }
540 case IRP_MN_QUERY_ID:
541 {
543 break;
544 }
546 {
548 break;
549 }
550 default:
551 {
552 Irp->IoStatus.Information = 0;
554 }
555 }
556
557 Irp->IoStatus.Status = status;
559 return status;
560}
#define TRUE
Definition: types.h:120
NTSTATUS PartitionHandleRemove(_In_ PPARTITION_EXTENSION PartExt, _In_ BOOLEAN FinalRemove)
Definition: partition.c:276
static NTSTATUS PartitionHandleQueryId(_In_ PPARTITION_EXTENSION PartExt, _In_ PIRP Irp)
Definition: partition.c:400
static NTSTATUS PartitionHandleDeviceRelations(_In_ PPARTITION_EXTENSION PartExt, _In_ PIRP Irp)
Definition: partition.c:361
static NTSTATUS PartitionHandleStartDevice(_In_ PPARTITION_EXTENSION PartExt, _In_ PIRP Irp)
Definition: partition.c:94
static NTSTATUS PartitionHandleQueryCapabilities(_In_ PPARTITION_EXTENSION PartExt, _In_ PIRP Irp)
Definition: partition.c:478
#define IRP_MN_SURPRISE_REMOVAL
Definition: ntifs_ex.h:408
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
#define IRP_MN_CANCEL_STOP_DEVICE
#define IRP_MN_START_DEVICE
#define IRP_MN_QUERY_ID
#define IRP_MN_REMOVE_DEVICE
#define IRP_MN_QUERY_DEVICE_RELATIONS
#define IRP_MN_QUERY_STOP_DEVICE
#define IRP_MN_QUERY_CAPABILITIES
#define IRP_MN_CANCEL_REMOVE_DEVICE
#define IRP_MN_STOP_DEVICE
#define IRP_MN_QUERY_REMOVE_DEVICE

Referenced by PartMgrPnp().

◆ PartitionHandleQueryCapabilities()

static NTSTATUS PartitionHandleQueryCapabilities ( _In_ PPARTITION_EXTENSION  PartExt,
_In_ PIRP  Irp 
)
static

Definition at line 478 of file partition.c.

481{
483 PDEVICE_CAPABILITIES devCaps = ioStack->Parameters.DeviceCapabilities.Capabilities;
484
485 PAGED_CODE();
486 ASSERT(devCaps);
487
488 devCaps->SilentInstall = TRUE;
489 devCaps->RawDeviceOK = TRUE;
490 devCaps->NoDisplayInUI = TRUE;
491 devCaps->Address = PartExt->OnDiskNumber;
492 devCaps->UniqueID = FALSE;
493
494 return STATUS_SUCCESS;
495}
struct _IO_STACK_LOCATION::@3974::@4001 DeviceCapabilities
* PDEVICE_CAPABILITIES
Definition: iotypes.h:965

Referenced by PartitionHandlePnp().

◆ PartitionHandleQueryId()

static NTSTATUS PartitionHandleQueryId ( _In_ PPARTITION_EXTENSION  PartExt,
_In_ PIRP  Irp 
)
static

Definition at line 400 of file partition.c.

403{
405 BUS_QUERY_ID_TYPE idType = ioStack->Parameters.QueryId.IdType;
406 UNICODE_STRING idString;
408
409 PAGED_CODE();
410
411 switch (idType)
412 {
413 case BusQueryDeviceID:
414 status = RtlCreateUnicodeString(&idString, L"STORAGE\\Partition")
416 break;
418 {
419 static WCHAR volumeID[] = L"STORAGE\\Volume\0";
420
421 idString.Buffer = ExAllocatePoolWithTag(PagedPool, sizeof(volumeID), TAG_PARTMGR);
422 RtlCopyMemory(idString.Buffer, volumeID, sizeof(volumeID));
423
425 break;
426 }
428 {
429 WCHAR string[64];
430 PFDO_EXTENSION fdoExtension = PartExt->LowerDevice->DeviceExtension;
431
432 PartMgrAcquireLayoutLock(fdoExtension);
433
434 if (fdoExtension->DiskData.PartitionStyle == PARTITION_STYLE_MBR)
435 {
436 swprintf(string, L"S%08lx_O%I64x_L%I64x",
437 fdoExtension->DiskData.Mbr.Signature,
438 PartExt->StartingOffset,
439 PartExt->PartitionLength);
440 }
441 else
442 {
443 swprintf(string,
444 L"S%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02xS_O%I64x_L%I64x",
445 fdoExtension->DiskData.Gpt.DiskId.Data1,
446 fdoExtension->DiskData.Gpt.DiskId.Data2,
447 fdoExtension->DiskData.Gpt.DiskId.Data3,
448 fdoExtension->DiskData.Gpt.DiskId.Data4[0],
449 fdoExtension->DiskData.Gpt.DiskId.Data4[1],
450 fdoExtension->DiskData.Gpt.DiskId.Data4[2],
451 fdoExtension->DiskData.Gpt.DiskId.Data4[3],
452 fdoExtension->DiskData.Gpt.DiskId.Data4[4],
453 fdoExtension->DiskData.Gpt.DiskId.Data4[5],
454 fdoExtension->DiskData.Gpt.DiskId.Data4[6],
455 fdoExtension->DiskData.Gpt.DiskId.Data4[7],
456 PartExt->StartingOffset,
457 PartExt->PartitionLength);
458 }
459
460 PartMgrReleaseLayoutLock(fdoExtension);
461
462 status = RtlCreateUnicodeString(&idString, string)
464 break;
465 }
466 default:
468 break;
469 }
470
471 Irp->IoStatus.Information = NT_SUCCESS(status) ? (ULONG_PTR) idString.Buffer : 0;
472 return status;
473}
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
struct _IO_STACK_LOCATION::@3974::@4005 QueryId
enum _BUS_QUERY_ID_TYPE BUS_QUERY_ID_TYPE
@ BusQueryInstanceID
Definition: iotypes.h:2939
@ BusQueryDeviceID
Definition: iotypes.h:2936
@ BusQueryHardwareIDs
Definition: iotypes.h:2937

Referenced by PartitionHandlePnp().

◆ PartitionHandleRemove()

NTSTATUS PartitionHandleRemove ( _In_ PPARTITION_EXTENSION  PartExt,
_In_ BOOLEAN  FinalRemove 
)

Definition at line 276 of file partition.c.

279{
281
282 PAGED_CODE();
283
284 // remove the symbolic link
285 if (PartExt->SymlinkCreated)
286 {
287 WCHAR nameBuf[64];
288 UNICODE_STRING partitionSymlink;
289 PFDO_EXTENSION fdoExtension = PartExt->LowerDevice->DeviceExtension;
290
292 fdoExtension->DiskData.DeviceNumber, PartExt->DetectedNumber);
293
294 RtlInitUnicodeString(&partitionSymlink, nameBuf);
295
296 status = IoDeleteSymbolicLink(&partitionSymlink);
297
298 if (!NT_SUCCESS(status))
299 {
300 return status;
301 }
302 PartExt->SymlinkCreated = FALSE;
303
304 INFO("Symlink removed %wZ -> %wZ\n", &partitionSymlink, &PartExt->DeviceName);
305 }
306
307 // release device interfaces
308 if (PartExt->PartitionInterfaceName.Buffer)
309 {
310 status = IoSetDeviceInterfaceState(&PartExt->PartitionInterfaceName, FALSE);
311 if (!NT_SUCCESS(status))
312 {
313 return status;
314 }
315 RtlFreeUnicodeString(&PartExt->PartitionInterfaceName);
316 RtlInitUnicodeString(&PartExt->PartitionInterfaceName, NULL);
317 }
318
319 if (PartExt->VolumeInterfaceName.Buffer)
320 {
321 /* Notify MountMgr to delete all associated mount points.
322 * MountMgr does not automatically remove these in order to support
323 * drive letter persistence for online/offline volume transitions,
324 * or volumes arrival/removal on removable devices. */
326 if (!NT_SUCCESS(status))
327 {
328 ERR("VolumeDeleteMountPoints(%wZ) failed with status 0x%08lx\n",
329 &PartExt->DeviceName, status);
330 /* Failure isn't major, continue proceeding with volume removal */
331 }
332
333 /* Notify MountMgr of volume removal */
334 status = IoSetDeviceInterfaceState(&PartExt->VolumeInterfaceName, FALSE);
335 if (!NT_SUCCESS(status))
336 {
337 return status;
338 }
339 RtlFreeUnicodeString(&PartExt->VolumeInterfaceName);
340 RtlInitUnicodeString(&PartExt->VolumeInterfaceName, NULL);
341 }
342
343 if (FinalRemove)
344 {
345 ASSERT(PartExt->DeviceName.Buffer);
346 if (PartExt->DeviceName.Buffer)
347 {
348 INFO("Removed device %wZ\n", &PartExt->DeviceName);
349 RtlFreeUnicodeString(&PartExt->DeviceName);
350 }
351
352 IoDeleteDevice(PartExt->DeviceObject);
353 }
354
355 return STATUS_SUCCESS;
356}
static const WCHAR PartitionSymLinkFormat[]
Definition: partition.c:10
static NTSTATUS VolumeDeleteMountPoints(_In_ PPARTITION_EXTENSION PartExt)
Notifies MountMgr to delete all mount points associated with the given volume.
Definition: partition.c:185
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
NTSTATUS NTAPI IoSetDeviceInterfaceState(IN PUNICODE_STRING SymbolicLinkName, IN BOOLEAN Enable)
Definition: deviface.c:1311

Referenced by FdoHandleSurpriseRemoval(), PartitionHandlePnp(), and PartMgrUpdatePartitionDevices().

◆ PartitionHandleStartDevice()

static NTSTATUS PartitionHandleStartDevice ( _In_ PPARTITION_EXTENSION  PartExt,
_In_ PIRP  Irp 
)
static

Definition at line 94 of file partition.c.

97{
98 PAGED_CODE();
99
100 // first, create a symbolic link for our device
101 WCHAR nameBuf[64];
102 UNICODE_STRING partitionSymlink, interfaceName;
103 PFDO_EXTENSION fdoExtension = PartExt->LowerDevice->DeviceExtension;
104
105 // \\Device\\Harddisk%lu\\Partition%lu
107 fdoExtension->DiskData.DeviceNumber, PartExt->DetectedNumber);
108
109 if (!RtlCreateUnicodeString(&partitionSymlink, nameBuf))
110 {
112 }
113
114 NTSTATUS status = IoCreateSymbolicLink(&partitionSymlink, &PartExt->DeviceName);
115
116 if (!NT_SUCCESS(status))
117 {
118 return status;
119 }
120
121 PartExt->SymlinkCreated = TRUE;
122
123 INFO("Symlink created %wZ -> %wZ\n", &partitionSymlink, &PartExt->DeviceName);
124
125 // Our partition device will have two interfaces:
126 // GUID_DEVINTERFACE_PARTITION and GUID_DEVINTERFACE_VOLUME
127 // (aka. MOUNTDEV_MOUNTED_DEVICE_GUID).
128 // The latter one is used to notify MountMgr about the new volume.
129
130 status = IoRegisterDeviceInterface(PartExt->DeviceObject,
131 &GUID_DEVINTERFACE_PARTITION,
132 NULL,
133 &interfaceName);
134 if (!NT_SUCCESS(status))
135 {
136 return status;
137 }
138
139 PartExt->PartitionInterfaceName = interfaceName;
140 status = IoSetDeviceInterfaceState(&interfaceName, TRUE);
141
142 INFO("Partition interface %wZ\n", &interfaceName);
143
144 if (!NT_SUCCESS(status))
145 {
146 RtlFreeUnicodeString(&interfaceName);
147 RtlInitUnicodeString(&PartExt->PartitionInterfaceName, NULL);
148 return status;
149 }
150
151 status = IoRegisterDeviceInterface(PartExt->DeviceObject,
152 &GUID_DEVINTERFACE_VOLUME,
153 NULL,
154 &interfaceName);
155 if (!NT_SUCCESS(status))
156 {
157 return status;
158 }
159
160 PartExt->VolumeInterfaceName = interfaceName;
161 status = IoSetDeviceInterfaceState(&interfaceName, TRUE);
162
163 INFO("Volume interface %wZ\n", &interfaceName);
164
165 if (!NT_SUCCESS(status))
166 {
167 RtlFreeUnicodeString(&interfaceName);
168 RtlInitUnicodeString(&PartExt->VolumeInterfaceName, NULL);
169 return status;
170 }
171
172 return STATUS_SUCCESS;
173}
NTSTATUS NTAPI IoRegisterDeviceInterface(IN PDEVICE_OBJECT PhysicalDeviceObject, IN CONST GUID *InterfaceClassGuid, IN PUNICODE_STRING ReferenceString OPTIONAL, OUT PUNICODE_STRING SymbolicLinkName)
Definition: deviface.c:955

Referenced by PartitionHandlePnp().

◆ VolumeDeleteMountPoints()

static NTSTATUS VolumeDeleteMountPoints ( _In_ PPARTITION_EXTENSION  PartExt)
static

Notifies MountMgr to delete all mount points associated with the given volume.

Note
This should belong to volmgr.sys and act on a PVOLUME_EXTENSION.

Definition at line 185 of file partition.c.

187{
189 UNICODE_STRING MountMgr;
190 ULONG InputSize, OutputSize;
191 LOGICAL Retry;
197
198 PAGED_CODE();
199
200 /* Get the device pointer to the MountMgr */
204 &FileObject,
205 &DeviceObject);
206 if (!NT_SUCCESS(Status))
207 return Status;
208
209 /* Setup the volume device name for deleting its mount points */
210 DeviceName = &PartExt->DeviceName;
211
212 /* Allocate the input buffer */
213 InputSize = sizeof(*InputBuffer) + DeviceName->Length;
215 if (!InputBuffer)
216 {
218 goto Quit;
219 }
220
221 /* Fill it in */
223 InputBuffer->DeviceNameOffset = sizeof(*InputBuffer);
224 InputBuffer->DeviceNameLength = DeviceName->Length;
225 RtlCopyMemory(&InputBuffer[1], DeviceName->Buffer, DeviceName->Length);
226
227 /*
228 * IOCTL_MOUNTMGR_DELETE_POINTS needs a large-enough scratch output buffer
229 * to work with. (It uses it to query the mount points, before deleting
230 * them.) Start with a guessed size and call the IOCTL. If the buffer is
231 * not big enough, use the value retrieved in MOUNTMGR_MOUNT_POINTS::Size
232 * to re-allocate a larger buffer and call the IOCTL once more.
233 */
234 OutputSize = max(PAGE_SIZE, sizeof(*OutputBuffer));
235 for (Retry = 0; Retry < 2; ++Retry)
236 {
238 if (!OutputBuffer)
239 {
241 break;
242 }
243
244 /* Call the MountMgr to delete the drive letter */
248 InputSize,
250 OutputSize,
251 FALSE);
252
253 /* Adjust the allocation size if it was too small */
255 {
256 OutputSize = OutputBuffer->Size;
258 continue;
259 }
260 /* Success or failure: stop the loop */
261 break;
262 }
263
264Quit:
265 if (OutputBuffer)
267 if (InputBuffer)
269 if (FileObject)
271 return Status;
272}
_In_ PSCSI_REQUEST_BLOCK _Out_ NTSTATUS _Inout_ BOOLEAN * Retry
Definition: classpnp.h:312
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Status
Definition: gdiplustypes.h:25
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define IOCTL_MOUNTMGR_DELETE_POINTS
Definition: imports.h:122
#define MOUNTMGR_DEVICE_NAME
Definition: imports.h:74
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
NTSTATUS NTAPI IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, IN ACCESS_MASK DesiredAccess, OUT PFILE_OBJECT *FileObject, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1435
NTSTATUS IssueSyncIoControlRequest(_In_ UINT32 IoControlCode, _In_ PDEVICE_OBJECT DeviceObject, _In_ PVOID InputBuffer, _In_ ULONG InputBufferLength, _In_ PVOID OutputBuffer, _In_ ULONG OutputBufferLength, _In_ BOOLEAN InternalDeviceIoControl)
Definition: utils.c:19
#define max(a, b)
Definition: svc.c:63
uint32_t ULONG
Definition: typedefs.h:59
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3275
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR OutputBuffer
Definition: wdfiotarget.h:863
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR InputBuffer
Definition: wdfiotarget.h:953
* PFILE_OBJECT
Definition: iotypes.h:1998
#define ObDereferenceObject
Definition: obfuncs.h:203

Referenced by PartitionHandleRemove().

Variable Documentation

◆ PartitionSymLinkFormat

const WCHAR PartitionSymLinkFormat[] = L"\\Device\\Harddisk%lu\\Partition%lu"
static

Definition at line 10 of file partition.c.

Referenced by PartitionHandleRemove(), and PartitionHandleStartDevice().