diff --git a/src/Driver/Ntdriver.c b/src/Driver/Ntdriver.c index 5b32992ec1..51b683a49f 100644 --- a/src/Driver/Ntdriver.c +++ b/src/Driver/Ntdriver.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "Crypto.h" #include "Fat.h" #include "Tests.h" @@ -150,6 +151,91 @@ int EncryptionItemCount = 0; int EncryptionFragmentSize = 0; int EncryptionMaxWorkItems = 0; +typedef struct +{ + __int64 VirtualDiskLength; + __int64 PartitionStartingOffset; + __int64 PartitionLength; + ULONG DeviceNumber; + ULONG PartitionNumber; + ULONG HiddenSectors; + BOOL HasPhysicalBacking; + BOOL ExtendedIoctlEnabled; + BOOL WindowsDefragEnabled; +} TC_VOLUME_IDENTITY; + +static void TCGetVolumeIdentity (PEXTENSION Extension, TC_VOLUME_IDENTITY *identity) +{ + ULONGLONG start; + ULONGLONG end; + ULONGLONG hostEnd; + ULONGLONG hiddenSectors; + ULONGLONG partitionSectors; + BOOL extendedIoctlEnabled = EnableExtendedIoctlSupport; + BOOL windowsDefragEnabled = AllowWindowsDefrag; + BOOL physicalIdentityEnabled = extendedIoctlEnabled || windowsDefragEnabled; + + identity->VirtualDiskLength = Extension->DiskLength + BYTES_PER_MB; + identity->PartitionStartingOffset = BYTES_PER_MB; + identity->PartitionLength = Extension->DiskLength; + identity->DeviceNumber = (ULONG) -1; + identity->PartitionNumber = 1; + identity->HiddenSectors = Extension->BytesPerSector != 0 + ? BYTES_PER_MB / Extension->BytesPerSector + : 0; + identity->HasPhysicalBacking = FALSE; + identity->ExtendedIoctlEnabled = extendedIoctlEnabled; + identity->WindowsDefragEnabled = windowsDefragEnabled; + + // Keep the synthetic MBR view unless one raw backing extent maps to the normal volume data area. + if (!physicalIdentityEnabled + || !Extension->bRawDevice + || Extension->DeviceNumber == (ULONG) -1 + || Extension->PartitionNumber == (ULONG) -1 + || Extension->HostPartitionStartingOffset < 0 + || Extension->HostLength <= 0 + || Extension->DiskLength <= 0 + || !Extension->cryptoInfo + || Extension->cryptoInfo->hiddenVolume + || Extension->cryptoInfo->bProtectHiddenVolume + || Extension->PartitionInInactiveSysEncScope) + { + return; + } + + if (S_OK != ULongLongAdd ( + (ULONGLONG) Extension->HostPartitionStartingOffset, + Extension->cryptoInfo->volDataAreaOffset, + &start) + || S_OK != ULongLongAdd (start, (ULONGLONG) Extension->DiskLength, &end) + || S_OK != ULongLongAdd ( + (ULONGLONG) Extension->HostPartitionStartingOffset, + (ULONGLONG) Extension->HostLength, + &hostEnd) + || end > hostEnd + || end > (ULONGLONG) 0x7fffffffffffffffULL + || Extension->BytesPerSector == 0 + || start % Extension->BytesPerSector != 0 + || end % Extension->BytesPerSector != 0) + { + return; + } + + hiddenSectors = start / Extension->BytesPerSector; + partitionSectors = (ULONGLONG) Extension->DiskLength / Extension->BytesPerSector; + if (hiddenSectors > 0xffffffffUL + || partitionSectors > 0xffffffffUL + || end / Extension->BytesPerSector > 0x100000000ULL) + return; + + identity->VirtualDiskLength = (__int64) end; + identity->PartitionStartingOffset = (__int64) start; + identity->DeviceNumber = Extension->DeviceNumber; + identity->PartitionNumber = Extension->PartitionNumber; + identity->HiddenSectors = (ULONG) hiddenSectors; + identity->HasPhysicalBacking = TRUE; +} + BOOL IsOrderedFlushBarriersEnabled () { return OrderedFlushBarriersEnabled; @@ -1099,6 +1185,7 @@ IOCTL_STORAGE_QUERY_PROPERTY 0x002D1400 NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, PIRP Irp) { PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); + TC_VOLUME_IDENTITY identity; UNREFERENCED_PARAMETER(DeviceObject); switch (irpSp->Parameters.DeviceIoControl.IoControlCode) @@ -1228,8 +1315,11 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION PDISK_GEOMETRY outputBuffer = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer; + TCGetVolumeIdentity (Extension, &identity); outputBuffer->MediaType = Extension->bRemovable ? RemovableMedia : FixedMedia; - outputBuffer->Cylinders.QuadPart = Extension->NumberOfCylinders; + outputBuffer->Cylinders.QuadPart = identity.HasPhysicalBacking + ? identity.VirtualDiskLength / Extension->BytesPerSector + : Extension->NumberOfCylinders; outputBuffer->TracksPerCylinder = Extension->TracksPerCylinder; outputBuffer->SectorsPerTrack = Extension->SectorsPerTrack; outputBuffer->BytesPerSector = Extension->BytesPerSector; @@ -1249,13 +1339,15 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION BOOL bFullBuffer = (irpSp->Parameters.DeviceIoControl.OutputBufferLength >= fullOutputSize)? TRUE : FALSE; PDISK_GEOMETRY_EX outputBuffer = (PDISK_GEOMETRY_EX) Irp->AssociatedIrp.SystemBuffer; + TCGetVolumeIdentity (Extension, &identity); outputBuffer->Geometry.MediaType = Extension->bRemovable ? RemovableMedia : FixedMedia; - outputBuffer->Geometry.Cylinders.QuadPart = Extension->NumberOfCylinders; + outputBuffer->Geometry.Cylinders.QuadPart = identity.HasPhysicalBacking + ? identity.VirtualDiskLength / Extension->BytesPerSector + : Extension->NumberOfCylinders; outputBuffer->Geometry.TracksPerCylinder = Extension->TracksPerCylinder; outputBuffer->Geometry.SectorsPerTrack = Extension->SectorsPerTrack; outputBuffer->Geometry.BytesPerSector = Extension->BytesPerSector; - // Add 1MB to the disk size to emulate the geometry of a real MBR disk - outputBuffer->DiskSize.QuadPart = Extension->DiskLength + BYTES_PER_MB; + outputBuffer->DiskSize.QuadPart = identity.VirtualDiskLength; if (bFullBuffer) { @@ -1291,6 +1383,7 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Irp->AssociatedIrp.SystemBuffer; PDEVICE_MEDIA_INFO mediaInfo = &outputBuffer->MediaInfo[0]; + TCGetVolumeIdentity (Extension, &identity); outputBuffer->DeviceType = FILE_DEVICE_DISK; outputBuffer->MediaInfoCount = 1; @@ -1302,7 +1395,9 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION else mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaCharacteristics = (MEDIA_CURRENTLY_MOUNTED | MEDIA_READ_WRITE); mediaInfo->DeviceSpecific.RemovableDiskInfo.MediaType = (STORAGE_MEDIA_TYPE) RemovableMedia; - mediaInfo->DeviceSpecific.RemovableDiskInfo.Cylinders.QuadPart = Extension->NumberOfCylinders; + mediaInfo->DeviceSpecific.RemovableDiskInfo.Cylinders.QuadPart = identity.HasPhysicalBacking + ? identity.VirtualDiskLength / Extension->BytesPerSector + : Extension->NumberOfCylinders; mediaInfo->DeviceSpecific.RemovableDiskInfo.TracksPerCylinder = Extension->TracksPerCylinder; mediaInfo->DeviceSpecific.RemovableDiskInfo.SectorsPerTrack = Extension->SectorsPerTrack; mediaInfo->DeviceSpecific.RemovableDiskInfo.BytesPerSector = Extension->BytesPerSector; @@ -1315,7 +1410,9 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION else mediaInfo->DeviceSpecific.DiskInfo.MediaCharacteristics = (MEDIA_CURRENTLY_MOUNTED | MEDIA_READ_WRITE); mediaInfo->DeviceSpecific.DiskInfo.MediaType = (STORAGE_MEDIA_TYPE) FixedMedia; - mediaInfo->DeviceSpecific.DiskInfo.Cylinders.QuadPart = Extension->NumberOfCylinders; + mediaInfo->DeviceSpecific.DiskInfo.Cylinders.QuadPart = identity.HasPhysicalBacking + ? identity.VirtualDiskLength / Extension->BytesPerSector + : Extension->NumberOfCylinders; mediaInfo->DeviceSpecific.DiskInfo.TracksPerCylinder = Extension->TracksPerCylinder; mediaInfo->DeviceSpecific.DiskInfo.SectorsPerTrack = Extension->SectorsPerTrack; mediaInfo->DeviceSpecific.DiskInfo.BytesPerSector = Extension->BytesPerSector; @@ -1390,7 +1487,7 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION outputBuffer->Version = sizeof(STORAGE_DEVICE_DESCRIPTOR); outputBuffer->Size = descriptorSize; - outputBuffer->DeviceType = FILE_DEVICE_DISK; + outputBuffer->DeviceType = DIRECT_ACCESS_DEVICE; outputBuffer->RemovableMedia = Extension->bRemovable? TRUE : FALSE; outputBuffer->ProductIdOffset = sizeof (STORAGE_DEVICE_DESCRIPTOR); outputBuffer->SerialNumberOffset = sizeof (STORAGE_DEVICE_DESCRIPTOR); @@ -1522,14 +1619,15 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION PPARTITION_INFORMATION outputBuffer = (PPARTITION_INFORMATION) Irp->AssociatedIrp.SystemBuffer; + TCGetVolumeIdentity (Extension, &identity); outputBuffer->PartitionType = Extension->PartitionType; outputBuffer->BootIndicator = FALSE; outputBuffer->RecognizedPartition = TRUE; outputBuffer->RewritePartition = FALSE; - outputBuffer->StartingOffset.QuadPart = BYTES_PER_MB; // Set offset to 1MB to emulate the partition offset on a real MBR disk - outputBuffer->PartitionLength.QuadPart= Extension->DiskLength; - outputBuffer->PartitionNumber = 1; - outputBuffer->HiddenSectors = BYTES_PER_MB / Extension->BytesPerSector; + outputBuffer->StartingOffset.QuadPart = identity.PartitionStartingOffset; + outputBuffer->PartitionLength.QuadPart = identity.PartitionLength; + outputBuffer->PartitionNumber = identity.PartitionNumber; + outputBuffer->HiddenSectors = identity.HiddenSectors; Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof (PARTITION_INFORMATION); } @@ -1541,15 +1639,16 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION { PPARTITION_INFORMATION_EX outputBuffer = (PPARTITION_INFORMATION_EX) Irp->AssociatedIrp.SystemBuffer; + TCGetVolumeIdentity (Extension, &identity); outputBuffer->PartitionStyle = PARTITION_STYLE_MBR; outputBuffer->RewritePartition = FALSE; - outputBuffer->StartingOffset.QuadPart = BYTES_PER_MB; // Set offset to 1MB to emulate the partition offset on a real MBR disk - outputBuffer->PartitionLength.QuadPart= Extension->DiskLength; - outputBuffer->PartitionNumber = 1; + outputBuffer->StartingOffset.QuadPart = identity.PartitionStartingOffset; + outputBuffer->PartitionLength.QuadPart = identity.PartitionLength; + outputBuffer->PartitionNumber = identity.PartitionNumber; outputBuffer->Mbr.PartitionType = Extension->PartitionType; outputBuffer->Mbr.BootIndicator = FALSE; outputBuffer->Mbr.RecognizedPartition = TRUE; - outputBuffer->Mbr.HiddenSectors = BYTES_PER_MB / Extension->BytesPerSector; + outputBuffer->Mbr.HiddenSectors = identity.HiddenSectors; Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof (PARTITION_INFORMATION_EX); } @@ -1563,6 +1662,7 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION PDRIVE_LAYOUT_INFORMATION outputBuffer = (PDRIVE_LAYOUT_INFORMATION) Irp->AssociatedIrp.SystemBuffer; + TCGetVolumeIdentity (Extension, &identity); outputBuffer->PartitionCount = bFullBuffer? 4 : 1; outputBuffer->Signature = GetCrc32((unsigned char*) &(Extension->UniqueVolumeId), 4); @@ -1570,10 +1670,10 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION outputBuffer->PartitionEntry->BootIndicator = FALSE; outputBuffer->PartitionEntry->RecognizedPartition = TRUE; outputBuffer->PartitionEntry->RewritePartition = FALSE; - outputBuffer->PartitionEntry->StartingOffset.QuadPart = BYTES_PER_MB; // Set offset to 1MB to emulate the partition offset on a real MBR disk - outputBuffer->PartitionEntry->PartitionLength.QuadPart = Extension->DiskLength; - outputBuffer->PartitionEntry->PartitionNumber = 1; - outputBuffer->PartitionEntry->HiddenSectors = BYTES_PER_MB / Extension->BytesPerSector; + outputBuffer->PartitionEntry->StartingOffset.QuadPart = identity.PartitionStartingOffset; + outputBuffer->PartitionEntry->PartitionLength.QuadPart = identity.PartitionLength; + outputBuffer->PartitionEntry->PartitionNumber = identity.PartitionNumber; + outputBuffer->PartitionEntry->HiddenSectors = identity.HiddenSectors; Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof (DRIVE_LAYOUT_INFORMATION); @@ -1589,9 +1689,10 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Dump ("ProcessVolumeDeviceControlIrp (IOCTL_DISK_GET_DRIVE_LAYOUT_EX)\n"); Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Information = 0; - if (EnableExtendedIoctlSupport) { - if (ValidateIOBufferSize (Irp, sizeof (DRIVE_LAYOUT_INFORMATION_EX), ValidateOutput)) + TCGetVolumeIdentity (Extension, &identity); + if (identity.ExtendedIoctlEnabled + && ValidateIOBufferSize (Irp, sizeof (DRIVE_LAYOUT_INFORMATION_EX), ValidateOutput)) { BOOL bFullBuffer = (irpSp->Parameters.DeviceIoControl.OutputBufferLength >= (sizeof (DRIVE_LAYOUT_INFORMATION_EX) + 3*sizeof(PARTITION_INFORMATION_EX)))? TRUE : FALSE; PDRIVE_LAYOUT_INFORMATION_EX outputBuffer = (PDRIVE_LAYOUT_INFORMATION_EX) @@ -1605,10 +1706,10 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION outputBuffer->PartitionEntry->Mbr.BootIndicator = FALSE; outputBuffer->PartitionEntry->Mbr.RecognizedPartition = TRUE; outputBuffer->PartitionEntry->RewritePartition = FALSE; - outputBuffer->PartitionEntry->StartingOffset.QuadPart = BYTES_PER_MB; // Set offset to 1MB to emulate the partition offset on a real MBR disk - outputBuffer->PartitionEntry->PartitionLength.QuadPart = Extension->DiskLength; - outputBuffer->PartitionEntry->PartitionNumber = 1; - outputBuffer->PartitionEntry->Mbr.HiddenSectors = BYTES_PER_MB / Extension->BytesPerSector; + outputBuffer->PartitionEntry->StartingOffset.QuadPart = identity.PartitionStartingOffset; + outputBuffer->PartitionEntry->PartitionLength.QuadPart = identity.PartitionLength; + outputBuffer->PartitionEntry->PartitionNumber = identity.PartitionNumber; + outputBuffer->PartitionEntry->Mbr.HiddenSectors = identity.HiddenSectors; outputBuffer->PartitionEntry->Mbr.PartitionType = Extension->PartitionType; Irp->IoStatus.Status = STATUS_SUCCESS; @@ -1750,69 +1851,73 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS: Dump ("ProcessVolumeDeviceControlIrp (IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS)\n"); // Vista's, Windows 8.1 and later filesystem defragmenter fails if IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS does not succeed. - if (!AllowWindowsDefrag || !Extension->bRawDevice) // We don't support defragmentation for file-hosted volumes { - Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; - Irp->IoStatus.Information = 0; - } - else if (ValidateIOBufferSize(Irp, sizeof(VOLUME_DISK_EXTENTS), ValidateOutput)) - { - VOLUME_DISK_EXTENTS* extents = (VOLUME_DISK_EXTENTS*)Irp->AssociatedIrp.SystemBuffer; + TCGetVolumeIdentity (Extension, &identity); + if (!identity.WindowsDefragEnabled + || !identity.HasPhysicalBacking) + { + Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; + Irp->IoStatus.Information = 0; + } + else if (ValidateIOBufferSize(Irp, sizeof(VOLUME_DISK_EXTENTS), ValidateOutput)) + { + VOLUME_DISK_EXTENTS* extents = (VOLUME_DISK_EXTENTS*)Irp->AssociatedIrp.SystemBuffer; - // Windows 10 filesystem defragmenter works only if we report an extent with a real disk number - // So in the case of a VeraCrypt disk based volume, we use the disk number - // of the underlaying physical disk and we report a single extent - extents->NumberOfDiskExtents = 1; - extents->Extents[0].DiskNumber = Extension->DeviceNumber; - extents->Extents[0].StartingOffset.QuadPart = BYTES_PER_MB; // Set offset to 1MB to emulate the partition offset on a real MBR disk - extents->Extents[0].ExtentLength.QuadPart = Extension->DiskLength; + extents->NumberOfDiskExtents = 1; + extents->Extents[0].DiskNumber = identity.DeviceNumber; + extents->Extents[0].StartingOffset.QuadPart = identity.PartitionStartingOffset; + extents->Extents[0].ExtentLength.QuadPart = identity.PartitionLength; - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = sizeof(*extents); + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof(*extents); + } } break; - case IOCTL_STORAGE_READ_CAPACITY: - Dump ("ProcessVolumeDeviceControlIrp (IOCTL_STORAGE_READ_CAPACITY)\n"); + case IOCTL_STORAGE_GET_DEVICE_NUMBER: + Dump ("ProcessVolumeDeviceControlIrp (IOCTL_STORAGE_GET_DEVICE_NUMBER)\n"); Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Information = 0; - if (EnableExtendedIoctlSupport) { - if (ValidateIOBufferSize (Irp, sizeof (STORAGE_READ_CAPACITY), ValidateOutput)) + TCGetVolumeIdentity (Extension, &identity); + if (identity.ExtendedIoctlEnabled + && identity.HasPhysicalBacking + && ValidateIOBufferSize (Irp, sizeof (STORAGE_DEVICE_NUMBER), ValidateOutput)) { - STORAGE_READ_CAPACITY *capacity = (STORAGE_READ_CAPACITY *) Irp->AssociatedIrp.SystemBuffer; + STORAGE_DEVICE_NUMBER *storage = (STORAGE_DEVICE_NUMBER *) Irp->AssociatedIrp.SystemBuffer; - capacity->Version = sizeof (STORAGE_READ_CAPACITY); - capacity->Size = sizeof (STORAGE_READ_CAPACITY); - capacity->BlockLength = Extension->BytesPerSector; - capacity->DiskLength.QuadPart = Extension->DiskLength + BYTES_PER_MB; // Add 1MB to the disk size to emulate the geometry of a real MBR disk - capacity->NumberOfBlocks.QuadPart = capacity->DiskLength.QuadPart / capacity->BlockLength; + storage->DeviceType = FILE_DEVICE_DISK; + storage->DeviceNumber = identity.DeviceNumber; + storage->PartitionNumber = identity.PartitionNumber; Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = sizeof (STORAGE_READ_CAPACITY); + Irp->IoStatus.Information = sizeof (STORAGE_DEVICE_NUMBER); } } break; - /*case IOCTL_STORAGE_GET_DEVICE_NUMBER: - Dump ("ProcessVolumeDeviceControlIrp (IOCTL_STORAGE_GET_DEVICE_NUMBER)\n"); + case IOCTL_STORAGE_READ_CAPACITY: + Dump ("ProcessVolumeDeviceControlIrp (IOCTL_STORAGE_READ_CAPACITY)\n"); Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Information = 0; - if (EnableExtendedIoctlSupport) { - if (ValidateIOBufferSize (Irp, sizeof (STORAGE_DEVICE_NUMBER), ValidateOutput)) + TCGetVolumeIdentity (Extension, &identity); + if (identity.ExtendedIoctlEnabled + && ValidateIOBufferSize (Irp, sizeof (STORAGE_READ_CAPACITY), ValidateOutput)) { - STORAGE_DEVICE_NUMBER *storage = (STORAGE_DEVICE_NUMBER *) Irp->AssociatedIrp.SystemBuffer; + STORAGE_READ_CAPACITY *capacity = (STORAGE_READ_CAPACITY *) Irp->AssociatedIrp.SystemBuffer; - storage->DeviceType = FILE_DEVICE_DISK; - storage->DeviceNumber = (ULONG) -1; - storage->PartitionNumber = 1; + capacity->Version = sizeof (STORAGE_READ_CAPACITY); + capacity->Size = sizeof (STORAGE_READ_CAPACITY); + capacity->BlockLength = Extension->BytesPerSector; + capacity->DiskLength.QuadPart = identity.VirtualDiskLength; + capacity->NumberOfBlocks.QuadPart = capacity->DiskLength.QuadPart / capacity->BlockLength; Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = sizeof (STORAGE_DEVICE_NUMBER); + Irp->IoStatus.Information = sizeof (STORAGE_READ_CAPACITY); } } - break;*/ + break; case IOCTL_STORAGE_GET_HOTPLUG_INFO: Dump ("ProcessVolumeDeviceControlIrp (IOCTL_STORAGE_GET_HOTPLUG_INFO)\n"); @@ -2158,7 +2263,6 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION case IOCTL_STORAGE_CHECK_PRIORITY_HINT_SUPPORT: case IOCTL_VOLUME_QUERY_ALLOCATION_HINT: case FT_BALANCED_READ_MODE: - case IOCTL_STORAGE_GET_DEVICE_NUMBER: case IOCTL_MOUNTDEV_LINK_CREATED: Dump ("ProcessVolumeDeviceControlIrp: returning STATUS_INVALID_DEVICE_REQUEST for %ls\n", TCTranslateCode (irpSp->Parameters.DeviceIoControl.IoControlCode)); Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; diff --git a/src/Driver/Ntdriver.h b/src/Driver/Ntdriver.h index b367c87ae9..e9c94f1cf2 100644 --- a/src/Driver/Ntdriver.h +++ b/src/Driver/Ntdriver.h @@ -71,6 +71,7 @@ typedef struct EXTENSION CRYPTO_INFO *cryptoInfo; /* Cryptographic and other information for this device */ __int64 HostLength; + __int64 HostPartitionStartingOffset; __int64 DiskLength; /* The length of the disk referred to by this device */ __int64 NumberOfCylinders; /* Partition info */ ULONG TracksPerCylinder; /* Partition info */ @@ -84,6 +85,7 @@ typedef struct EXTENSION ULONG HostMaximumPhysicalPages; ULONG HostAlignmentMask; ULONG DeviceNumber; + ULONG PartitionNumber; BOOL IncursSeekPenalty; BOOL TrimEnabled; diff --git a/src/Driver/Ntvol.c b/src/Driver/Ntvol.c index 17eef47c8f..70bb397cdc 100644 --- a/src/Driver/Ntvol.c +++ b/src/Driver/Ntvol.c @@ -88,6 +88,8 @@ NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject, Extension->TrimEnabled = FALSE; Extension->DeviceNumber = (ULONG) -1; + Extension->PartitionNumber = (ULONG) -1; + Extension->HostPartitionStartingOffset = -1; RtlInitUnicodeString (&FullFileName, pwszMountVolume); InitializeObjectAttributes (&oaFileAttributes, &FullFileName, OBJ_CASE_INSENSITIVE | (forceAccessCheck ? OBJ_FORCE_ACCESS_CHECK : 0) | OBJ_KERNEL_HANDLE, NULL, NULL); @@ -113,7 +115,9 @@ NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject, DISK_GEOMETRY_EX dg; STORAGE_PROPERTY_QUERY storagePropertyQuery = { 0 }; uint8* dgBuffer; - STORAGE_DEVICE_NUMBER storageDeviceNumber; + STORAGE_DEVICE_NUMBER storageDeviceNumber = { 0 }; + BOOL hostDeviceNumberValid = FALSE; + BOOL hostPartitionOffsetKnown = FALSE; ntStatus = IoGetDeviceObjectPointer(&FullFileName, FILE_READ_DATA | FILE_READ_ATTRIBUTES, @@ -168,7 +172,14 @@ NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject, IOCTL_STORAGE_GET_DEVICE_NUMBER, (char*)&storageDeviceNumber, sizeof(storageDeviceNumber)))) { - Extension->DeviceNumber = storageDeviceNumber.DeviceNumber; + if (storageDeviceNumber.DeviceType == FILE_DEVICE_DISK + && storageDeviceNumber.DeviceNumber != (ULONG) -1 + && storageDeviceNumber.PartitionNumber != (ULONG) -1) + { + Extension->DeviceNumber = storageDeviceNumber.DeviceNumber; + Extension->PartitionNumber = storageDeviceNumber.PartitionNumber; + hostDeviceNumberValid = TRUE; + } } lDiskLength.QuadPart = dg.DiskSize.QuadPart; @@ -233,18 +244,25 @@ NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject, { lDiskLength.QuadPart = pix.PartitionLength.QuadPart; partitionStartingOffset = pix.StartingOffset.QuadPart; + hostPartitionOffsetKnown = TRUE; } // If IOCTL_DISK_GET_PARTITION_INFO_EX fails, switch to IOCTL_DISK_GET_PARTITION_INFO else if (NT_SUCCESS(TCSendHostDeviceIoControlRequest(DeviceObject, Extension, IOCTL_DISK_GET_PARTITION_INFO, (char*)&pi, sizeof(pi)))) { lDiskLength.QuadPart = pi.PartitionLength.QuadPart; partitionStartingOffset = pi.StartingOffset.QuadPart; + hostPartitionOffsetKnown = TRUE; } else if (NT_SUCCESS(TCSendHostDeviceIoControlRequest(DeviceObject, Extension, IOCTL_DISK_GET_LENGTH_INFO, &diskLengthInfo, sizeof(diskLengthInfo)))) { lDiskLength = diskLengthInfo; + if (hostDeviceNumberValid && storageDeviceNumber.PartitionNumber == 0) + hostPartitionOffsetKnown = TRUE; } + if (hostPartitionOffsetKnown) + Extension->HostPartitionStartingOffset = partitionStartingOffset; + ProbingHostDeviceForWrite = TRUE; if (!mount->bMountReadOnly