diff options
author | Mounir IDRASSI <mounir.idrassi@idrix.fr> | 2015-05-03 08:43:10 +0200 |
---|---|---|
committer | Mounir IDRASSI <mounir.idrassi@idrix.fr> | 2015-05-03 15:47:29 +0200 |
commit | 7d52dda67c370de7d615678b61920c822eeb7142 (patch) | |
tree | 72157105bee4c38b6ae13ce9b6bd52474d1a3b4d | |
parent | 0f2d32f01145f82fa83806e08ddde6cdce8a496d (diff) | |
download | VeraCrypt-7d52dda67c370de7d615678b61920c822eeb7142.tar.gz VeraCrypt-7d52dda67c370de7d615678b61920c822eeb7142.zip |
Windows Driver: Implement querying physical sector size of veraCrypt volume through IOCTL_STORAGE_QUERY_PROPERTY
-rw-r--r-- | src/Common/Apidrvr.h | 1 | ||||
-rw-r--r-- | src/Common/Dlgcode.c | 78 | ||||
-rw-r--r-- | src/Driver/Ntdriver.c | 40 | ||||
-rw-r--r-- | src/Driver/Ntdriver.h | 4 | ||||
-rw-r--r-- | src/Driver/Ntvol.c | 35 | ||||
-rw-r--r-- | 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 @@ -102,8 +102,9 @@ typedef struct BOOL RecoveryMode;
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 @@ -20,8 +20,9 @@ #include <shlobj.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <time.h>
+#include <tchar.h>
#include "Resource.h"
#include "Platform/Finally.h"
@@ -6229,8 +6230,50 @@ 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
@@ -6476,9 +6519,44 @@ retry: if (GetVolumePathName (volumePath, root, sizeof (root) - 1))
{
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))
mount.bMountReadOnly = (flags & FILE_READ_ONLY_VOLUME) != 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 @@ -119,10 +119,10 @@ NTSTATUS DriverAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo) #endif
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)
{
Dump ("Volume pdo=%p interface=%ws\n", pdo, interfaceLinks);
@@ -627,8 +627,44 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Irp->IoStatus.Information = sizeof (DISK_GEOMETRY);
}
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))
{
PPARTITION_INFORMATION outputBuffer = (PPARTITION_INFORMATION)
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 @@ -57,10 +57,12 @@ typedef struct EXTENSION ULONG TracksPerCylinder; /* Partition info */
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 */
EncryptedIoQueue Queue;
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 @@ -79,9 +79,11 @@ 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,
&Extension->pfoDeviceFile,
@@ -96,8 +98,23 @@ 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))))
{
lDiskLength.QuadPart = pix.PartitionLength.QuadPart;
@@ -143,8 +160,9 @@ NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject, goto error;
}
Extension->HostBytesPerSector = mount->BytesPerSector;
+ Extension->HostBytesPerPhysicalSector = mount->BytesPerPhysicalSector;
if (Extension->HostBytesPerSector != TC_SECTOR_SIZE_FILE_HOSTED_VOLUME)
disableBuffering = FALSE;
}
@@ -745,11 +763,13 @@ 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)
{
IO_STATUS_BLOCK IoStatusBlock;
@@ -761,9 +781,9 @@ NTSTATUS TCSendHostDeviceIoControlRequest (PDEVICE_OBJECT DeviceObject, KeClearEvent (&Extension->keVolumeEvent);
Irp = IoBuildDeviceIoControlRequest (IoControlCode,
Extension->pFsdDevice,
- NULL, 0,
+ InputBuffer, InputBufferSize,
OutputBuffer, OutputBufferSize,
FALSE,
&Extension->keVolumeEvent,
&IoStatusBlock);
@@ -786,8 +806,17 @@ 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,
ULONG_PTR IrpInformation)
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 @@ -14,6 +14,7 @@ extern volatile BOOL ProbingHostDeviceForWrite; NTSTATUS TCOpenVolume ( PDEVICE_OBJECT DeviceObject , PEXTENSION Extension , MOUNT_STRUCT *mount , PWSTR pwszMountVolume , BOOL bRawDevice );
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 );
|