From 7d52dda67c370de7d615678b61920c822eeb7142 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Sun, 3 May 2015 08:43:10 +0200 Subject: Windows Driver: Implement querying physical sector size of veraCrypt volume through IOCTL_STORAGE_QUERY_PROPERTY --- src/Common/Apidrvr.h | 1 + src/Common/Dlgcode.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/Driver/Ntdriver.c | 40 ++++++++++++++++++++++++-- src/Driver/Ntdriver.h | 4 ++- src/Driver/Ntvol.c | 35 +++++++++++++++++++++-- src/Driver/Ntvol.h | 1 + 6 files changed, 153 insertions(+), 6 deletions(-) diff --git a/src/Common/Apidrvr.h b/src/Common/Apidrvr.h index 76aafc20..83d30595 100644 --- a/src/Common/Apidrvr.h +++ b/src/Common/Apidrvr.h @@ -103,6 +103,7 @@ typedef struct int pkcs5_prf; int ProtectedHidVolPkcs5Prf; BOOL bTrueCryptMode; + uint32 BytesPerPhysicalSector; } MOUNT_STRUCT; typedef struct diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c index 30b76e82..cf85682d 100644 --- a/src/Common/Dlgcode.c +++ b/src/Common/Dlgcode.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "Resource.h" @@ -6230,6 +6231,48 @@ void BroadcastDeviceChange (WPARAM message, int nDosDriveNo, DWORD driveMap) IgnoreWmDeviceChange = FALSE; } +BOOL GetPhysicalDriveAlignment(UINT nDriveNumber, STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR* pDesc) +{ + DWORD dwRet = NO_ERROR; + + if (!pDesc) + return FALSE; + + // Format physical drive path (may be '\\.\PhysicalDrive0', '\\.\PhysicalDrive1' and so on). + TCHAR strDrivePath[512]; + StringCbPrintf(strDrivePath, sizeof(strDrivePath), _T("\\\\.\\PhysicalDrive%u"), nDriveNumber); + + // Get a handle to physical drive + HANDLE hDevice = ::CreateFile(strDrivePath, 0, FILE_SHARE_READ, + NULL, OPEN_EXISTING, 0, NULL); + + if(INVALID_HANDLE_VALUE == hDevice) + return FALSE; + + // Set the input data structure + STORAGE_PROPERTY_QUERY storagePropertyQuery; + ZeroMemory(&storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY)); + storagePropertyQuery.PropertyId = StorageAccessAlignmentProperty; + storagePropertyQuery.QueryType = PropertyStandardQuery; + + // Get the necessary output buffer size + DWORD dwBytesReturned = 0; + BOOL bRet = ::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, + &storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY), + pDesc, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR), + &dwBytesReturned, NULL); + dwRet = ::GetLastError(); + ::CloseHandle(hDevice); + + if (!bRet) + { + SetLastError (dwRet); + return FALSE; + } + else + return TRUE; +} + /************************************************************/ // implementation of the generic wait dialog mechanism @@ -6477,7 +6520,42 @@ retry: { DWORD bps, flags, d; if (GetDiskFreeSpace (root, &d, &bps, &d, &d)) + { mount.BytesPerSector = bps; + mount.BytesPerPhysicalSector = bps; + } + + if (IsOSAtLeast (WIN_VISTA)) + { + if ( (strlen(root) >= 2) + && (root[1] == ':') + && (toupper(root[0]) >= 'A' && toupper(root[0]) <= 'Z') + ) + { + string drivePath = "\\\\.\\X:"; + HANDLE dev = INVALID_HANDLE_VALUE; + VOLUME_DISK_EXTENTS extents = {0}; + DWORD dwResult = 0; + drivePath[4] = root[0]; + + if ((dev = CreateFile (drivePath.c_str(),0, 0, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) + { + if (DeviceIoControl (dev, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &extents, sizeof(extents), &dwResult, NULL)) + { + if (extents.NumberOfDiskExtents > 0) + { + STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR desc; + if (GetPhysicalDriveAlignment (extents.Extents[0].DiskNumber, &desc)) + { + mount.BytesPerSector = desc.BytesPerLogicalSector; + mount.BytesPerPhysicalSector = desc.BytesPerPhysicalSector; + } + } + } + CloseHandle (dev); + } + } + } // Read-only host filesystem if (!mount.bMountReadOnly && GetVolumeInformation (root, NULL, 0, NULL, &d, &flags, NULL, 0)) diff --git a/src/Driver/Ntdriver.c b/src/Driver/Ntdriver.c index 86f3d9eb..402301c3 100644 --- a/src/Driver/Ntdriver.c +++ b/src/Driver/Ntdriver.c @@ -120,8 +120,8 @@ NTSTATUS DriverAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo) if (VolumeClassFilterRegistered && BootArgsValid && BootArgs.HiddenSystemPartitionStart != 0) { - PWSTR interfaceLinks; - if (NT_SUCCESS (IoGetDeviceInterfaces (&GUID_DEVINTERFACE_VOLUME, pdo, DEVICE_INTERFACE_INCLUDE_NONACTIVE, &interfaceLinks))) + PWSTR interfaceLinks = NULL; + if (NT_SUCCESS (IoGetDeviceInterfaces (&GUID_DEVINTERFACE_VOLUME, pdo, DEVICE_INTERFACE_INCLUDE_NONACTIVE, &interfaceLinks)) && interfaceLinks) { if (interfaceLinks[0] != UNICODE_NULL) { @@ -628,6 +628,42 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION } break; + case IOCTL_STORAGE_QUERY_PROPERTY: + if (ValidateIOBufferSize (Irp, sizeof (STORAGE_PROPERTY_QUERY), ValidateInput)) + { + PSTORAGE_PROPERTY_QUERY pStoragePropQuery = (PSTORAGE_PROPERTY_QUERY) Irp->AssociatedIrp.SystemBuffer; + STORAGE_QUERY_TYPE type = pStoragePropQuery->QueryType; + + if (type == PropertyExistsQuery) + { + if (pStoragePropQuery->PropertyId == StorageAccessAlignmentProperty) + { + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + } + } + else if (type == PropertyStandardQuery) + { + if (pStoragePropQuery->PropertyId == StorageAccessAlignmentProperty) + { + if (ValidateIOBufferSize (Irp, sizeof (STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR), ValidateOutput)) + { + PSTORAGE_ACCESS_ALIGNMENT_DESCRIPTOR outputBuffer = (PSTORAGE_ACCESS_ALIGNMENT_DESCRIPTOR) Irp->AssociatedIrp.SystemBuffer; + + outputBuffer->Version = sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR); + outputBuffer->Size = sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR); + outputBuffer->BytesPerLogicalSector = Extension->BytesPerSector; + outputBuffer->BytesPerPhysicalSector = Extension->HostBytesPerPhysicalSector; + outputBuffer->BytesOffsetForSectorAlignment = Extension->BytesOffsetForSectorAlignment; + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof (STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR); + } + } + } + } + + break; + case IOCTL_DISK_GET_PARTITION_INFO: if (ValidateIOBufferSize (Irp, sizeof (PARTITION_INFORMATION), ValidateOutput)) { diff --git a/src/Driver/Ntdriver.h b/src/Driver/Ntdriver.h index 90ceb6b8..91cc6eed 100644 --- a/src/Driver/Ntdriver.h +++ b/src/Driver/Ntdriver.h @@ -58,8 +58,10 @@ typedef struct EXTENSION ULONG SectorsPerTrack; /* Partition info */ ULONG BytesPerSector; /* Partition info */ UCHAR PartitionType; /* Partition info */ - + uint32 HostBytesPerSector; + uint32 HostBytesPerPhysicalSector; + ULONG BytesOffsetForSectorAlignment; KEVENT keVolumeEvent; /* Event structure used when setting up a device */ diff --git a/src/Driver/Ntvol.c b/src/Driver/Ntvol.c index 7556b4cf..9acebaed 100644 --- a/src/Driver/Ntvol.c +++ b/src/Driver/Ntvol.c @@ -80,7 +80,9 @@ NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject, PARTITION_INFORMATION pi; PARTITION_INFORMATION_EX pix; LARGE_INTEGER diskLengthInfo; - DISK_GEOMETRY dg; + DISK_GEOMETRY dg; + STORAGE_PROPERTY_QUERY storagePropertyQuery = {0}; + STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR storageDescriptor = {0}; ntStatus = IoGetDeviceObjectPointer (&FullFileName, FILE_READ_DATA | FILE_READ_ATTRIBUTES, @@ -97,6 +99,21 @@ NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject, lDiskLength.QuadPart = dg.Cylinders.QuadPart * dg.SectorsPerTrack * dg.TracksPerCylinder * dg.BytesPerSector; Extension->HostBytesPerSector = dg.BytesPerSector; + storagePropertyQuery.PropertyId = StorageAccessAlignmentProperty; + storagePropertyQuery.QueryType = PropertyStandardQuery; + + /* IOCTL_STORAGE_QUERY_PROPERTY supported only on Vista and above */ + if (NT_SUCCESS (TCSendHostDeviceIoControlRequestEx (DeviceObject, Extension, IOCTL_STORAGE_QUERY_PROPERTY, + (char*) &storagePropertyQuery, sizeof(storagePropertyQuery), + (char *) &storageDescriptor, sizeof (storageDescriptor)))) + { + Extension->HostBytesPerPhysicalSector = storageDescriptor.BytesPerPhysicalSector; + } + else + { + Extension->HostBytesPerPhysicalSector = dg.BytesPerSector; + } + // Drive geometry is used only when IOCTL_DISK_GET_PARTITION_INFO fails if (NT_SUCCESS (TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_PARTITION_INFO_EX, (char *) &pix, sizeof (pix)))) { @@ -144,6 +161,7 @@ NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject, } Extension->HostBytesPerSector = mount->BytesPerSector; + Extension->HostBytesPerPhysicalSector = mount->BytesPerPhysicalSector; if (Extension->HostBytesPerSector != TC_SECTOR_SIZE_FILE_HOSTED_VOLUME) disableBuffering = FALSE; @@ -746,9 +764,11 @@ void TCCloseVolume (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension) } -NTSTATUS TCSendHostDeviceIoControlRequest (PDEVICE_OBJECT DeviceObject, +NTSTATUS TCSendHostDeviceIoControlRequestEx (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, ULONG IoControlCode, + void *InputBuffer, + ULONG InputBufferSize, void *OutputBuffer, ULONG OutputBufferSize) { @@ -762,7 +782,7 @@ NTSTATUS TCSendHostDeviceIoControlRequest (PDEVICE_OBJECT DeviceObject, Irp = IoBuildDeviceIoControlRequest (IoControlCode, Extension->pFsdDevice, - NULL, 0, + InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize, FALSE, &Extension->keVolumeEvent, @@ -787,6 +807,15 @@ NTSTATUS TCSendHostDeviceIoControlRequest (PDEVICE_OBJECT DeviceObject, return ntStatus; } +NTSTATUS TCSendHostDeviceIoControlRequest (PDEVICE_OBJECT DeviceObject, + PEXTENSION Extension, + ULONG IoControlCode, + void *OutputBuffer, + ULONG OutputBufferSize) +{ + return TCSendHostDeviceIoControlRequestEx (DeviceObject, Extension, IoControlCode, NULL, 0, OutputBuffer, OutputBufferSize); +} + NTSTATUS COMPLETE_IRP (PDEVICE_OBJECT DeviceObject, PIRP Irp, NTSTATUS IrpStatus, diff --git a/src/Driver/Ntvol.h b/src/Driver/Ntvol.h index a6e9ff9e..e67ca1ed 100644 --- a/src/Driver/Ntvol.h +++ b/src/Driver/Ntvol.h @@ -15,5 +15,6 @@ NTSTATUS TCOpenVolume ( PDEVICE_OBJECT DeviceObject , PEXTENSION Extension , MOU void TCCloseVolume ( PDEVICE_OBJECT DeviceObject , PEXTENSION Extension ); NTSTATUS TCCompletion ( PDEVICE_OBJECT DeviceObject , PIRP Irp , PVOID pUserBuffer ); static NTSTATUS TCSendHostDeviceIoControlRequest ( PDEVICE_OBJECT DeviceObject , PEXTENSION Extension , ULONG IoControlCode , void *OutputBuffer , ULONG OutputBufferSize ); +static NTSTATUS TCSendHostDeviceIoControlRequestEx ( PDEVICE_OBJECT DeviceObject , PEXTENSION Extension , ULONG IoControlCode , void *InputBuffer , ULONG InputBufferSize , void *OutputBuffer , ULONG OutputBufferSize ); NTSTATUS COMPLETE_IRP ( PDEVICE_OBJECT DeviceObject , PIRP Irp , NTSTATUS IrpStatus , ULONG_PTR IrpInformation ); static void RestoreTimeStamp ( PEXTENSION Extension ); -- cgit v1.2.3