From cd59d5364f5b32ac136e4a91b8534f2410059cde Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Sun, 4 Mar 2018 18:48:16 +0100 Subject: Windows: Implement TRIM support for non-system SSD partitions/drives and add driver option to enable it (TRIM is disabled by default for non-system SSD partitions/drives) --- src/Common/Apidrvr.h | 1 + src/Common/Common.h | 2 + src/Driver/Ntdriver.c | 322 +++++++++++++++++++++++++++++++++++++++++++++----- src/Driver/Ntdriver.h | 3 + src/Driver/Ntvol.c | 28 +++++ src/Mount/Mount.c | 3 + src/Mount/Mount.rc | 22 ++-- src/Mount/Resource.h | 3 +- 8 files changed, 341 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/Common/Apidrvr.h b/src/Common/Apidrvr.h index 283e58d2..fda2d946 100644 --- a/src/Common/Apidrvr.h +++ b/src/Common/Apidrvr.h @@ -410,5 +410,6 @@ typedef struct #define TC_DRIVER_CONFIG_ENABLE_EXTENDED_IOCTL 0x10 #define TC_DRIVER_CONFIG_DISABLE_EVIL_MAID_ATTACK_DETECTION 0x20 #define TC_DRIVER_CONFIG_CACHE_BOOT_PIM 0x40 +#define VC_DRIVER_CONFIG_ALLOW_NONSYS_TRIM 0x80 #endif /* _WIN32 */ diff --git a/src/Common/Common.h b/src/Common/Common.h index 421d8239..0620b652 100644 --- a/src/Common/Common.h +++ b/src/Common/Common.h @@ -23,6 +23,8 @@ #define VOLUME_ID_SIZE SHA256_DIGESTSIZE +#define ALIGN_VALUE(value, alignment) (((alignment) == 0)? (value) : (((value) + ((alignment) - 1)) & ~((alignment) - 1))) + typedef enum { // IMPORTANT: If you add a new item here, update IsOSVersionAtLeast(). diff --git a/src/Driver/Ntdriver.c b/src/Driver/Ntdriver.c index 73930404..ce2f01ce 100644 --- a/src/Driver/Ntdriver.c +++ b/src/Driver/Ntdriver.c @@ -69,6 +69,42 @@ #define IOCTL_VOLUME_IS_DYNAMIC CTL_CODE(IOCTL_VOLUME_BASE, 18, METHOD_BUFFERED, FILE_ANY_ACCESS) #endif +#ifndef StorageDeviceLBProvisioningProperty +#define StorageDeviceLBProvisioningProperty 11 +#endif + +#ifndef DeviceDsmAction_OffloadRead +#define DeviceDsmAction_OffloadRead ( 3 | DeviceDsmActionFlag_NonDestructive) +#endif + +#ifndef DeviceDsmAction_OffloadWrite +#define DeviceDsmAction_OffloadWrite 4 +#endif + +#ifndef DeviceDsmAction_Allocation +#define DeviceDsmAction_Allocation ( 5 | DeviceDsmActionFlag_NonDestructive) +#endif + +#ifndef DeviceDsmAction_Repair +#define DeviceDsmAction_Repair ( 6 | DeviceDsmActionFlag_NonDestructive) +#endif + +#ifndef DeviceDsmAction_Scrub +#define DeviceDsmAction_Scrub ( 7 | DeviceDsmActionFlag_NonDestructive) +#endif + +#ifndef DeviceDsmAction_DrtQuery +#define DeviceDsmAction_DrtQuery ( 8 | DeviceDsmActionFlag_NonDestructive) +#endif + +#ifndef DeviceDsmAction_DrtClear +#define DeviceDsmAction_DrtClear ( 9 | DeviceDsmActionFlag_NonDestructive) +#endif + +#ifndef DeviceDsmAction_DrtDisable +#define DeviceDsmAction_DrtDisable (10 | DeviceDsmActionFlag_NonDestructive) +#endif + /* Init section, which is thrown away as soon as DriverEntry returns */ #pragma alloc_text(INIT,DriverEntry) #pragma alloc_text(INIT,TCCreateRootDeviceObject) @@ -96,6 +132,7 @@ static size_t EncryptionThreadPoolFreeCpuCountLimit = 0; static BOOL SystemFavoriteVolumeDirty = FALSE; static BOOL PagingFileCreationPrevented = FALSE; static BOOL EnableExtendedIoctlSupport = FALSE; +static BOOL AllowTrimCommand = FALSE; static KeSaveExtendedProcessorStateFn KeSaveExtendedProcessorStatePtr = NULL; static KeRestoreExtendedProcessorStateFn KeRestoreExtendedProcessorStatePtr = NULL; @@ -710,6 +747,8 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION case IOCTL_DISK_GET_MEDIA_TYPES: case IOCTL_DISK_GET_DRIVE_GEOMETRY: + case IOCTL_STORAGE_GET_MEDIA_TYPES: + case IOCTL_DISK_UPDATE_DRIVE_SIZE: Dump ("ProcessVolumeDeviceControlIrp (IOCTL_DISK_GET_DRIVE_GEOMETRY)\n"); /* Return the drive geometry for the disk. Note that we return values which were made up to suit the disk size. */ @@ -774,25 +813,6 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION } break; - case IOCTL_STORAGE_GET_MEDIA_TYPES: - Dump ("ProcessVolumeDeviceControlIrp (IOCTL_STORAGE_GET_MEDIA_TYPES)\n"); - /* Return the drive geometry for the disk. Note that we - return values which were made up to suit the disk size. */ - if (ValidateIOBufferSize (Irp, sizeof (DISK_GEOMETRY), ValidateOutput)) - { - PDISK_GEOMETRY outputBuffer = (PDISK_GEOMETRY) - Irp->AssociatedIrp.SystemBuffer; - - outputBuffer->MediaType = Extension->bRemovable ? RemovableMedia : FixedMedia; - outputBuffer->Cylinders.QuadPart = Extension->NumberOfCylinders; - outputBuffer->TracksPerCylinder = Extension->TracksPerCylinder; - outputBuffer->SectorsPerTrack = Extension->SectorsPerTrack; - outputBuffer->BytesPerSector = Extension->BytesPerSector; - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = sizeof (DISK_GEOMETRY); - } - break; - case IOCTL_STORAGE_GET_MEDIA_TYPES_EX: Dump ("ProcessVolumeDeviceControlIrp (IOCTL_STORAGE_GET_MEDIA_TYPES_EX)\n"); if (ValidateIOBufferSize (Irp, sizeof (GET_MEDIA_TYPES), ValidateOutput)) @@ -839,19 +859,40 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Dump ("ProcessVolumeDeviceControlIrp (IOCTL_STORAGE_QUERY_PROPERTY)\n"); Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Information = 0; - if (EnableExtendedIoctlSupport) + if (EnableExtendedIoctlSupport || Extension->TrimEnabled) { if (ValidateIOBufferSize (Irp, sizeof (STORAGE_PROPERTY_QUERY), ValidateInput)) { PSTORAGE_PROPERTY_QUERY pStoragePropQuery = (PSTORAGE_PROPERTY_QUERY) Irp->AssociatedIrp.SystemBuffer; STORAGE_QUERY_TYPE type = pStoragePropQuery->QueryType; - Dump ("IOCTL_STORAGE_QUERY_PROPERTY - PropertyId = %d, type = %d\n", pStoragePropQuery->PropertyId, type); + Dump ("IOCTL_STORAGE_QUERY_PROPERTY - PropertyId = %d, type = %d, InputBufferLength = %d, OutputBufferLength = %d\n", pStoragePropQuery->PropertyId, type, (int) irpSp->Parameters.DeviceIoControl.InputBufferLength, (int) irpSp->Parameters.DeviceIoControl.OutputBufferLength); - /* return error if an unsupported type is encountered */ - Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; - - if ( (pStoragePropQuery->PropertyId == StorageAccessAlignmentProperty) + if (Extension->bRawDevice && + (pStoragePropQuery->PropertyId == (STORAGE_PROPERTY_ID) StorageDeviceLBProvisioningProperty) + ) + { + IO_STATUS_BLOCK IoStatus; + Dump ("ProcessVolumeDeviceControlIrp: sending IOCTL_STORAGE_QUERY_PROPERTY (%d) to device\n", (int) pStoragePropQuery->PropertyId); + Irp->IoStatus.Status = ZwDeviceIoControlFile ( + Extension->hDeviceFile, + NULL, + NULL, + NULL, + &IoStatus, + IOCTL_STORAGE_QUERY_PROPERTY, + Irp->AssociatedIrp.SystemBuffer, + irpSp->Parameters.DeviceIoControl.InputBufferLength, + Irp->AssociatedIrp.SystemBuffer, + irpSp->Parameters.DeviceIoControl.OutputBufferLength); + Dump ("ProcessVolumeDeviceControlIrp: ZwDeviceIoControlFile returned 0x%.8X\n", (DWORD) Irp->IoStatus.Status); + if (Irp->IoStatus.Status == STATUS_SUCCESS) + { + Irp->IoStatus.Status = IoStatus.Status; + Irp->IoStatus.Information = IoStatus.Information; + } + } + else if ( (pStoragePropQuery->PropertyId == StorageAccessAlignmentProperty) || (pStoragePropQuery->PropertyId == StorageDeviceProperty) || (pStoragePropQuery->PropertyId == StorageAdapterProperty) || (pStoragePropQuery->PropertyId == StorageDeviceSeekPenaltyProperty) @@ -865,12 +906,14 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION } else if (type == PropertyStandardQuery) { + ULONG descriptorSize; switch (pStoragePropQuery->PropertyId) { case StorageDeviceProperty: { + Dump ("IOCTL_STORAGE_QUERY_PROPERTY - StorageDeviceProperty\n"); /* Add 0x00 for NULL terminating string used as ProductId, ProductRevision, SerialNumber, VendorId */ - ULONG descriptorSize = sizeof (STORAGE_DEVICE_DESCRIPTOR) + 1; + descriptorSize = sizeof (STORAGE_DEVICE_DESCRIPTOR) + 1; if (ValidateIOBufferSize (Irp, descriptorSize, ValidateOutput)) { PSTORAGE_DEVICE_DESCRIPTOR outputBuffer = (PSTORAGE_DEVICE_DESCRIPTOR) Irp->AssociatedIrp.SystemBuffer; @@ -899,7 +942,8 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION break; case StorageAdapterProperty: { - ULONG descriptorSize = sizeof (STORAGE_ADAPTER_DESCRIPTOR); + Dump ("IOCTL_STORAGE_QUERY_PROPERTY - StorageAdapterProperty\n"); + descriptorSize = sizeof (STORAGE_ADAPTER_DESCRIPTOR); if (ValidateIOBufferSize (Irp, descriptorSize, ValidateOutput)) { PSTORAGE_ADAPTER_DESCRIPTOR outputBuffer = (PSTORAGE_ADAPTER_DESCRIPTOR) Irp->AssociatedIrp.SystemBuffer; @@ -925,6 +969,7 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION break; case StorageAccessAlignmentProperty: { + Dump ("IOCTL_STORAGE_QUERY_PROPERTY - StorageAccessAlignmentProperty\n"); if (ValidateIOBufferSize (Irp, sizeof (STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR), ValidateOutput)) { PSTORAGE_ACCESS_ALIGNMENT_DESCRIPTOR outputBuffer = (PSTORAGE_ACCESS_ALIGNMENT_DESCRIPTOR) Irp->AssociatedIrp.SystemBuffer; @@ -948,13 +993,14 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION break; case StorageDeviceSeekPenaltyProperty: { + Dump ("IOCTL_STORAGE_QUERY_PROPERTY - StorageDeviceSeekPenaltyProperty\n"); if (ValidateIOBufferSize (Irp, sizeof (DEVICE_SEEK_PENALTY_DESCRIPTOR), ValidateOutput)) { PDEVICE_SEEK_PENALTY_DESCRIPTOR outputBuffer = (PDEVICE_SEEK_PENALTY_DESCRIPTOR) Irp->AssociatedIrp.SystemBuffer; - + Dump ("IOCTL_STORAGE_QUERY_PROPERTY - StorageDeviceSeekPenaltyProperty: set IncursSeekPenalty to %s\n", Extension->IncursSeekPenalty? "TRUE" : "FALSE"); outputBuffer->Version = sizeof(DEVICE_SEEK_PENALTY_DESCRIPTOR); outputBuffer->Size = sizeof(DEVICE_SEEK_PENALTY_DESCRIPTOR); - outputBuffer->IncursSeekPenalty = TRUE; //TODO: in case of SSD drive, we should probably return FALSE + outputBuffer->IncursSeekPenalty = (BOOLEAN) Extension->IncursSeekPenalty; Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof (DEVICE_SEEK_PENALTY_DESCRIPTOR); } @@ -970,13 +1016,14 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION break; case StorageDeviceTrimProperty: { + Dump ("IOCTL_STORAGE_QUERY_PROPERTY - StorageDeviceTrimProperty\n"); if (ValidateIOBufferSize (Irp, sizeof (DEVICE_TRIM_DESCRIPTOR), ValidateOutput)) { PDEVICE_TRIM_DESCRIPTOR outputBuffer = (PDEVICE_TRIM_DESCRIPTOR) Irp->AssociatedIrp.SystemBuffer; - + Dump ("IOCTL_STORAGE_QUERY_PROPERTY - StorageDeviceTrimProperty: set TrimEnabled to %s\n", Extension->TrimEnabled? "TRUE" : "FALSE"); outputBuffer->Version = sizeof(DEVICE_TRIM_DESCRIPTOR); outputBuffer->Size = sizeof(DEVICE_TRIM_DESCRIPTOR); - outputBuffer->TrimEnabled = FALSE; /* TODO: implement Trim support for SSD drives */ + outputBuffer->TrimEnabled = (BOOLEAN) Extension->TrimEnabled; Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof (DEVICE_TRIM_DESCRIPTOR); } @@ -1361,6 +1408,21 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION break; + case IOCTL_DISK_UPDATE_PROPERTIES: + Dump ("ProcessVolumeDeviceControlIrp: returning STATUS_SUCCESS for IOCTL_DISK_UPDATE_PROPERTIES\n"); + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + break; + + case IOCTL_DISK_MEDIA_REMOVAL: + case IOCTL_STORAGE_MEDIA_REMOVAL: + Dump ("ProcessVolumeDeviceControlIrp: returning STATUS_SUCCESS for %ls\n", TCTranslateCode (irpSp->Parameters.DeviceIoControl.IoControlCode)); + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + break; + case IOCTL_DISK_GET_CLUSTER_INFO: Dump ("ProcessVolumeDeviceControlIrp: returning STATUS_NOT_SUPPORTED for %ls\n", TCTranslateCode (irpSp->Parameters.DeviceIoControl.IoControlCode)); Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; @@ -1371,12 +1433,203 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Irp->IoStatus.Information = 0; } break; + + case IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES: + Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES\n"); + Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; + Irp->IoStatus.Information = 0; + if (Extension->bRawDevice && Extension->TrimEnabled) + { + if (ValidateIOBufferSize (Irp, sizeof (DEVICE_MANAGE_DATA_SET_ATTRIBUTES), ValidateInput)) + { + PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); + DWORD inputLength = irpSp->Parameters.DeviceIoControl.InputBufferLength; + PDEVICE_MANAGE_DATA_SET_ATTRIBUTES pInputAttrs = (PDEVICE_MANAGE_DATA_SET_ATTRIBUTES) Irp->AssociatedIrp.SystemBuffer; + DEVICE_DATA_MANAGEMENT_SET_ACTION action = pInputAttrs->Action; + BOOL bEntireSet = pInputAttrs->Flags & DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE? TRUE : FALSE; + ULONGLONG minSizedataSet = (ULONGLONG) pInputAttrs->DataSetRangesOffset + (ULONGLONG) pInputAttrs->DataSetRangesLength; + ULONGLONG minSizeParameter = (ULONGLONG) pInputAttrs->ParameterBlockOffset + (ULONGLONG) pInputAttrs->ParameterBlockLength; + ULONGLONG minSizeGeneric = sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES) + (ULONGLONG) pInputAttrs->ParameterBlockLength + (ULONGLONG) pInputAttrs->DataSetRangesLength; + PDEVICE_MANAGE_DATA_SET_ATTRIBUTES pNewSetAttrs = NULL; + ULONG ulNewInputLength = 0; + BOOL bForwardIoctl = FALSE; + + if (inputLength >= minSizeGeneric && inputLength >= minSizedataSet && inputLength >= minSizeParameter) + { + if (bEntireSet) + { + if (minSizedataSet) + { + Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE set but data set range specified=> Error.\n"); + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + Irp->IoStatus.Information = 0; + } + else + { + DWORD dwDataSetOffset = ALIGN_VALUE (inputLength, sizeof(DEVICE_DATA_SET_RANGE)); + DWORD dwDataSetLength = sizeof(DEVICE_DATA_SET_RANGE); + + Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE set. Setting data range to all volume.\n"); + + ulNewInputLength = dwDataSetOffset + dwDataSetLength; + pNewSetAttrs = (PDEVICE_MANAGE_DATA_SET_ATTRIBUTES) TCalloc (ulNewInputLength); + if (pNewSetAttrs) + { + PDEVICE_DATA_SET_RANGE pRange = (PDEVICE_DATA_SET_RANGE) (((unsigned char*) pNewSetAttrs) + dwDataSetOffset); + + memcpy (pNewSetAttrs, pInputAttrs, inputLength); + + pRange->StartingOffset = (ULONGLONG) Extension->cryptoInfo->hiddenVolume ? Extension->cryptoInfo->hiddenVolumeOffset : Extension->cryptoInfo->volDataAreaOffset; + pRange->LengthInBytes = Extension->DiskLength; + + pNewSetAttrs->Size = sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES); + pNewSetAttrs->Action = action; + pNewSetAttrs->Flags = pInputAttrs->Flags & (~DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE); + pNewSetAttrs->ParameterBlockOffset = pInputAttrs->ParameterBlockOffset; + pNewSetAttrs->ParameterBlockLength = pInputAttrs->ParameterBlockLength; + pNewSetAttrs->DataSetRangesOffset = dwDataSetOffset; + pNewSetAttrs->DataSetRangesLength = dwDataSetLength; + + bForwardIoctl = TRUE; + } + else + { + Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - Failed to allocate memory.\n"); + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + Irp->IoStatus.Information = 0; + } + } + } + else + { + Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - creating new data set range from input range.\n"); + ulNewInputLength = inputLength; + pNewSetAttrs = (PDEVICE_MANAGE_DATA_SET_ATTRIBUTES) TCalloc (inputLength); + if (pNewSetAttrs) + { + PDEVICE_DATA_SET_RANGE pNewRanges = (PDEVICE_DATA_SET_RANGE) (((unsigned char*) pNewSetAttrs) + pInputAttrs->DataSetRangesOffset); + PDEVICE_DATA_SET_RANGE pInputRanges = (PDEVICE_DATA_SET_RANGE) (((unsigned char*) pInputAttrs) + pInputAttrs->DataSetRangesOffset); + DWORD dwInputRangesCount = 0, dwNewRangesCount = 0, i; + ULONGLONG ullStartingOffset, ullNewOffset, ullEndOffset; + HRESULT hResult; + + memcpy (pNewSetAttrs, pInputAttrs, inputLength); + + dwInputRangesCount = pInputAttrs->DataSetRangesLength / sizeof(DEVICE_DATA_SET_RANGE); + + for (i = 0; i < dwInputRangesCount; i++) + { + ullStartingOffset = (ULONGLONG) pInputRanges[i].StartingOffset; + hResult = ULongLongAdd(ullStartingOffset, + (ULONGLONG) Extension->cryptoInfo->hiddenVolume ? Extension->cryptoInfo->hiddenVolumeOffset : Extension->cryptoInfo->volDataAreaOffset, + &ullNewOffset); + if (hResult != S_OK) + continue; + else if (S_OK != ULongLongAdd(ullStartingOffset, (ULONGLONG) pInputRanges[i].LengthInBytes, &ullEndOffset)) + continue; + else if (ullEndOffset > (ULONGLONG) Extension->DiskLength) + continue; + else if (ullNewOffset > 0) + { + pNewRanges[dwNewRangesCount].StartingOffset = (LONGLONG) ullNewOffset; + pNewRanges[dwNewRangesCount].LengthInBytes = pInputRanges[i].LengthInBytes; + + dwNewRangesCount++; + } + } + + Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - %d valid range processed from %d range in input.\n", (int) dwNewRangesCount, (int) dwInputRangesCount); + + pNewSetAttrs->DataSetRangesLength = dwNewRangesCount * sizeof (DEVICE_DATA_SET_RANGE); + + bForwardIoctl = TRUE; + } + else + { + Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - Failed to allocate memory.\n"); + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + Irp->IoStatus.Information = 0; + } + } + } + else + { + Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - buffer containing DEVICE_MANAGE_DATA_SET_ATTRIBUTES has invalid length.\n"); + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + Irp->IoStatus.Information = 0; + } + + + if (bForwardIoctl) + { + if (action == DeviceDsmAction_Trim) + { + Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - DeviceDsmAction_Trim.\n"); + + if (Extension->cryptoInfo->hiddenVolume || !AllowTrimCommand) + { + Dump ("ProcessVolumeDeviceControlIrp: TRIM command filtered\n"); + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + } + else + { + IO_STATUS_BLOCK IoStatus; + Dump ("ProcessVolumeDeviceControlIrp: sending TRIM to device\n"); + Irp->IoStatus.Status = ZwDeviceIoControlFile ( + Extension->hDeviceFile, + NULL, + NULL, + NULL, + &IoStatus, + IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES, + (PVOID) pNewSetAttrs, + ulNewInputLength, + NULL, + 0); + Dump ("ProcessVolumeDeviceControlIrp: ZwDeviceIoControlFile returned 0x%.8X\n", (DWORD) Irp->IoStatus.Status); + if (Irp->IoStatus.Status == STATUS_SUCCESS) + { + Irp->IoStatus.Status = IoStatus.Status; + Irp->IoStatus.Information = IoStatus.Information; + } + else + Irp->IoStatus.Information = 0; + } + } + else + { + switch (action) + { + case DeviceDsmAction_Notification: Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - DeviceDsmAction_Notification\n"); break; + case DeviceDsmAction_OffloadRead: Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - DeviceDsmAction_OffloadRead\n"); break; + case DeviceDsmAction_OffloadWrite: Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - DeviceDsmAction_OffloadWrite\n"); break; + case DeviceDsmAction_Allocation: Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - DeviceDsmAction_Allocation\n"); break; + case DeviceDsmAction_Scrub: Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - DeviceDsmAction_Scrub\n"); break; + case DeviceDsmAction_DrtQuery: Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - DeviceDsmAction_DrtQuery\n"); break; + case DeviceDsmAction_DrtClear: Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - DeviceDsmAction_DrtClear\n"); break; + case DeviceDsmAction_DrtDisable: Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - DeviceDsmAction_DrtDisable\n"); break; + default: Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - unknown action %d\n", (int) action); break; + } + + } + } + + if (pNewSetAttrs) + TCfree (pNewSetAttrs); + } + } +#if defined (DEBUG) || defined (DEBUG_TRACE) + else + Dump ("ProcessVolumeDeviceControlIrp: returning STATUS_INVALID_DEVICE_REQUEST for IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES\n"); +#endif + break; case IOCTL_STORAGE_CHECK_PRIORITY_HINT_SUPPORT: - case IOCTL_DISK_MEDIA_REMOVAL: 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; Irp->IoStatus.Information = 0; @@ -2772,6 +3025,8 @@ LPWSTR TCTranslateCode (ULONG ulCode) return (LPWSTR) _T ("IOCTL_DISK_GET_MEDIA_TYPES"); else if (ulCode == IOCTL_DISK_IS_CLUSTERED) return (LPWSTR) _T ("IOCTL_DISK_IS_CLUSTERED"); + else if (ulCode == IOCTL_DISK_UPDATE_DRIVE_SIZE) + return (LPWSTR) _T ("IOCTL_DISK_UPDATE_DRIVE_SIZE"); else if (ulCode == IOCTL_STORAGE_GET_MEDIA_TYPES) return (LPWSTR) _T ("IOCTL_STORAGE_GET_MEDIA_TYPES"); else if (ulCode == IOCTL_STORAGE_GET_HOTPLUG_INFO) @@ -2798,6 +3053,8 @@ LPWSTR TCTranslateCode (ULONG ulCode) return (LPWSTR) _T ("IOCTL_VOLUME_POST_ONLINE"); else if (ulCode == IOCTL_STORAGE_CHECK_PRIORITY_HINT_SUPPORT) return (LPWSTR) _T ("IOCTL_STORAGE_CHECK_PRIORITY_HINT_SUPPORT"); + else if (ulCode == IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES) + return (LPWSTR) _T ("IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES"); else if (ulCode == IRP_MJ_READ) return (LPWSTR) _T ("IRP_MJ_READ"); else if (ulCode == IRP_MJ_WRITE) @@ -3968,6 +4225,7 @@ NTSTATUS ReadRegistryConfigFlags (BOOL driverEntry) EnableHwEncryption ((flags & TC_DRIVER_CONFIG_DISABLE_HARDWARE_ENCRYPTION) ? FALSE : TRUE); EnableExtendedIoctlSupport = (flags & TC_DRIVER_CONFIG_ENABLE_EXTENDED_IOCTL)? TRUE : FALSE; + AllowTrimCommand = (flags & VC_DRIVER_CONFIG_ALLOW_NONSYS_TRIM)? TRUE : FALSE; } else status = STATUS_INVALID_PARAMETER; diff --git a/src/Driver/Ntdriver.h b/src/Driver/Ntdriver.h index fd4d3559..50a98d03 100644 --- a/src/Driver/Ntdriver.h +++ b/src/Driver/Ntdriver.h @@ -67,6 +67,9 @@ typedef struct EXTENSION ULONG HostMaximumPhysicalPages; ULONG HostAlignmentMask; + BOOL IncursSeekPenalty; + BOOL TrimEnabled; + KEVENT keVolumeEvent; /* Event structure used when setting up a device */ EncryptedIoQueue Queue; diff --git a/src/Driver/Ntvol.c b/src/Driver/Ntvol.c index 81549ba1..c8552ab3 100644 --- a/src/Driver/Ntvol.c +++ b/src/Driver/Ntvol.c @@ -68,6 +68,10 @@ NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject, Extension->HostMaximumPhysicalPages = 17; Extension->HostAlignmentMask = 0; + /* default values for non-SSD drives */ + Extension->IncursSeekPenalty = TRUE; + Extension->TrimEnabled = FALSE; + RtlInitUnicodeString (&FullFileName, pwszMountVolume); InitializeObjectAttributes (&oaFileAttributes, &FullFileName, OBJ_CASE_INSENSITIVE | (forceAccessCheck ? OBJ_FORCE_ACCESS_CHECK : 0) | OBJ_KERNEL_HANDLE, NULL, NULL); KeInitializeEvent (&Extension->keVolumeEvent, NotificationEvent, FALSE); @@ -152,6 +156,8 @@ NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject, { STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR alignmentDesc = {0}; STORAGE_ADAPTER_DESCRIPTOR adapterDesc = {0}; + DEVICE_SEEK_PENALTY_DESCRIPTOR penaltyDesc = {0}; + DEVICE_TRIM_DESCRIPTOR trimDesc = {0}; storagePropertyQuery.PropertyId = StorageAccessAlignmentProperty; storagePropertyQuery.QueryType = PropertyStandardQuery; @@ -178,6 +184,28 @@ NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject, Extension->HostMaximumPhysicalPages = adapterDesc.MaximumPhysicalPages; Extension->HostAlignmentMask = adapterDesc.AlignmentMask; } + + storagePropertyQuery.PropertyId = StorageDeviceSeekPenaltyProperty; + penaltyDesc.Version = sizeof (DEVICE_SEEK_PENALTY_DESCRIPTOR); + penaltyDesc.Size = sizeof (DEVICE_SEEK_PENALTY_DESCRIPTOR); + + if (NT_SUCCESS (TCSendHostDeviceIoControlRequestEx (DeviceObject, Extension, IOCTL_STORAGE_QUERY_PROPERTY, + (char*) &storagePropertyQuery, sizeof(storagePropertyQuery), + (char *) &penaltyDesc, sizeof (penaltyDesc)))) + { + Extension->IncursSeekPenalty = penaltyDesc.IncursSeekPenalty; + } + + storagePropertyQuery.PropertyId = StorageDeviceTrimProperty; + trimDesc.Version = sizeof (DEVICE_TRIM_DESCRIPTOR); + trimDesc.Size = sizeof (DEVICE_TRIM_DESCRIPTOR); + + if (NT_SUCCESS (TCSendHostDeviceIoControlRequestEx (DeviceObject, Extension, IOCTL_STORAGE_QUERY_PROPERTY, + (char*) &storagePropertyQuery, sizeof(storagePropertyQuery), + (char *) &trimDesc, sizeof (trimDesc)))) + { + Extension->TrimEnabled = trimDesc.TrimEnabled; + } } // Drive geometry is used only when IOCTL_DISK_GET_PARTITION_INFO fails diff --git a/src/Mount/Mount.c b/src/Mount/Mount.c index 6eb49a1b..61ce4f77 100644 --- a/src/Mount/Mount.c +++ b/src/Mount/Mount.c @@ -10687,6 +10687,7 @@ static BOOL CALLBACK PerformanceSettingsDlgProc (HWND hwndDlg, UINT msg, WPARAM uint32 driverConfig = ReadDriverConfigurationFlags(); CheckDlgButton (hwndDlg, IDC_ENABLE_HARDWARE_ENCRYPTION, (driverConfig & TC_DRIVER_CONFIG_DISABLE_HARDWARE_ENCRYPTION) ? BST_UNCHECKED : BST_CHECKED); CheckDlgButton (hwndDlg, IDC_ENABLE_EXTENDED_IOCTL_SUPPORT, (driverConfig & TC_DRIVER_CONFIG_ENABLE_EXTENDED_IOCTL) ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton (hwndDlg, IDC_ALLOW_TRIM_NONSYS_SSD, (driverConfig & VC_DRIVER_CONFIG_ALLOW_NONSYS_TRIM) ? BST_CHECKED : BST_UNCHECKED); SYSTEM_INFO sysInfo; GetSystemInfo (&sysInfo); @@ -10744,6 +10745,7 @@ static BOOL CALLBACK PerformanceSettingsDlgProc (HWND hwndDlg, UINT msg, WPARAM BOOL disableHW = !IsDlgButtonChecked (hwndDlg, IDC_ENABLE_HARDWARE_ENCRYPTION); BOOL enableExtendedIOCTL = IsDlgButtonChecked (hwndDlg, IDC_ENABLE_EXTENDED_IOCTL_SUPPORT); + BOOL allowTrimCommand = IsDlgButtonChecked (hwndDlg, IDC_ALLOW_TRIM_NONSYS_SSD); try { @@ -10780,6 +10782,7 @@ static BOOL CALLBACK PerformanceSettingsDlgProc (HWND hwndDlg, UINT msg, WPARAM SetDriverConfigurationFlag (TC_DRIVER_CONFIG_DISABLE_HARDWARE_ENCRYPTION, disableHW); SetDriverConfigurationFlag (TC_DRIVER_CONFIG_ENABLE_EXTENDED_IOCTL, enableExtendedIOCTL); + SetDriverConfigurationFlag (VC_DRIVER_CONFIG_ALLOW_NONSYS_TRIM, allowTrimCommand); DWORD bytesReturned; if (!DeviceIoControl (hDriver, TC_IOCTL_REREAD_DRIVER_CONFIG, NULL, 0, NULL, 0, &bytesReturned, NULL)) diff --git a/src/Mount/Mount.rc b/src/Mount/Mount.rc index 972fe5a0..9024b0d6 100644 --- a/src/Mount/Mount.rc +++ b/src/Mount/Mount.rc @@ -307,7 +307,7 @@ BEGIN GROUPBOX "Advanced Options",IDT_ADVANCED_OPTIONS,7,99,355,36 END -IDD_PERFORMANCE_SETTINGS DIALOGEX 0, 0, 370, 248 +IDD_PERFORMANCE_SETTINGS DIALOGEX 0, 0, 371, 253 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "VeraCrypt - Performance Options" FONT 8, "MS Shell Dlg", 400, 0, 0x1 @@ -319,17 +319,19 @@ BEGIN CONTROL "Do not use the following number of processors for encryption/decryption:",IDC_LIMIT_ENC_THREAD_POOL, "Button",BS_AUTOCHECKBOX | BS_TOP | WS_TABSTOP,18,103,283,11 COMBOBOX IDC_ENCRYPTION_FREE_CPU_COUNT,304,101,48,51,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "",IDT_LIMIT_ENC_THREAD_POOL_NOTE,18,126,334,33 LTEXT "More information",IDC_MORE_INFO_ON_THREAD_BASED_PARALLELIZATION,18,159,165,10,SS_NOTIFY - PUSHBUTTON "&Benchmark",IDC_BENCHMARK,7,227,59,14 - DEFPUSHBUTTON "OK",IDOK,257,227,50,14 - PUSHBUTTON "Cancel",IDCANCEL,313,227,50,14 + CONTROL "Enable extended disk control codes support",IDC_ENABLE_EXTENDED_IOCTL_SUPPORT, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,198,337,10 + CONTROL "Allow TRIM operation for non-system SSD partition/drive",IDC_ALLOW_TRIM_NONSYS_SSD, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,212,337,10 + PUSHBUTTON "&Benchmark",IDC_BENCHMARK,7,232,59,14 + DEFPUSHBUTTON "OK",IDOK,257,232,50,14 + PUSHBUTTON "Cancel",IDCANCEL,314,232,50,14 LTEXT "Processor (CPU) in this computer supports hardware acceleration for AES:",IDT_HW_AES_SUPPORTED_BY_CPU,18,23,273,9 GROUPBOX "Hardware Acceleration",IDT_ACCELERATION_OPTIONS,7,6,355,74 GROUPBOX "Thread-Based Parallelization",IDT_PARALLELIZATION_OPTIONS,7,84,355,93 - LTEXT "",IDT_LIMIT_ENC_THREAD_POOL_NOTE,18,126,334,33 - GROUPBOX "Driver Configuration",IDT_DRIVER_OPTIONS,7,183,356,36 - CONTROL "Enable extended disk control codes support",IDC_ENABLE_EXTENDED_IOCTL_SUPPORT, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,198,337,10 + GROUPBOX "Driver Configuration",IDT_DRIVER_OPTIONS,7,183,357,44 END IDD_FAVORITE_VOLUMES DIALOGEX 0, 0, 380, 368 @@ -492,9 +494,9 @@ BEGIN IDD_PERFORMANCE_SETTINGS, DIALOG BEGIN LEFTMARGIN, 7 - RIGHTMARGIN, 363 + RIGHTMARGIN, 364 TOPMARGIN, 7 - BOTTOMMARGIN, 241 + BOTTOMMARGIN, 246 END IDD_FAVORITE_VOLUMES, DIALOG diff --git a/src/Mount/Resource.h b/src/Mount/Resource.h index 907e5ad3..2cefbdad 100644 --- a/src/Mount/Resource.h +++ b/src/Mount/Resource.h @@ -187,6 +187,7 @@ #define IDC_SHOW_PLATFORMINFO 1164 #define IDC_EDIT_DCSPROP 1165 #define IDT_ADVANCED_OPTIONS 1166 +#define IDC_ALLOW_TRIM_NONSYS_SSD 1167 #define IDM_HELP 40001 #define IDM_ABOUT 40002 #define IDM_UNMOUNT_VOLUME 40003 @@ -263,7 +264,7 @@ #define _APS_NO_MFC 1 #define _APS_NEXT_RESOURCE_VALUE 120 #define _APS_NEXT_COMMAND_VALUE 40069 -#define _APS_NEXT_CONTROL_VALUE 1167 +#define _APS_NEXT_CONTROL_VALUE 1168 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif -- cgit v1.2.3