VeraCrypt
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Common/Apidrvr.h3
-rw-r--r--src/Common/Dlgcode.c114
-rw-r--r--src/Driver/Ntdriver.h3
-rw-r--r--src/Driver/Ntvol.c33
4 files changed, 136 insertions, 17 deletions
diff --git a/src/Common/Apidrvr.h b/src/Common/Apidrvr.h
index 28202e61..adffacc2 100644
--- a/src/Common/Apidrvr.h
+++ b/src/Common/Apidrvr.h
@@ -172,6 +172,9 @@ typedef struct
BOOL bIsNTFS; // output only
BOOL bDriverSetLabel;
BOOL bCachePim;
+ ULONG MaximumTransferLength;
+ ULONG MaximumPhysicalPages;
+ ULONG AlignmentMask;
} MOUNT_STRUCT;
typedef struct
diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c
index d09e0044..97c55da4 100644
--- a/src/Common/Dlgcode.c
+++ b/src/Common/Dlgcode.c
@@ -7228,36 +7228,97 @@ void BroadcastDeviceChange (WPARAM message, int nDosDriveNo, DWORD driveMap)
IgnoreWmDeviceChange = FALSE;
}
-BOOL GetPhysicalDriveAlignment(UINT nDriveNumber, STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR* pDesc)
+static BOOL GetDeviceStorageProperty (HANDLE hDevice, STORAGE_PROPERTY_ID propertyId, DWORD dwDescSize, void* 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;
+ ZeroMemory (pDesc, dwDescSize);
// Set the input data structure
STORAGE_PROPERTY_QUERY storagePropertyQuery;
ZeroMemory(&storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY));
- storagePropertyQuery.PropertyId = StorageAccessAlignmentProperty;
+ storagePropertyQuery.PropertyId = propertyId;
storagePropertyQuery.QueryType = PropertyStandardQuery;
// Get the necessary output buffer size
+ STORAGE_DESCRIPTOR_HEADER descHeader = {0};
DWORD dwBytesReturned = 0;
BOOL bRet = ::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
&storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY),
- pDesc, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR),
+ &descHeader, sizeof(STORAGE_DESCRIPTOR_HEADER),
&dwBytesReturned, NULL);
+ if (bRet)
+ {
+ if (dwBytesReturned == sizeof(STORAGE_DESCRIPTOR_HEADER))
+ {
+ unsigned char* outputBuffer = (unsigned char*) TCalloc (descHeader.Size);
+ bRet = ::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
+ &storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY),
+ outputBuffer, descHeader.Size,
+ &dwBytesReturned, NULL);
+ if (bRet)
+ {
+ if (dwBytesReturned >= dwDescSize)
+ {
+ memcpy (pDesc, outputBuffer, dwDescSize);
+ ((STORAGE_DESCRIPTOR_HEADER*)pDesc)->Version = dwDescSize;
+ ((STORAGE_DESCRIPTOR_HEADER*)pDesc)->Size = dwDescSize;
+ }
+ else
+ {
+ bRet = FALSE;
+ dwRet = ERROR_UNHANDLED_ERROR;
+ }
+ }
+ else
+ dwRet = ::GetLastError();
+ TCfree (outputBuffer);
+ }
+ else
+ {
+ bRet = FALSE;
+ dwRet = ERROR_UNHANDLED_ERROR;
+ }
+ }
+ else
+ dwRet = ::GetLastError();
+ ::CloseHandle(hDevice);
+
+ if (!bRet)
+ {
+ SetLastError (dwRet);
+ return FALSE;
+ }
+ else
+ return TRUE;
+}
+
+BOOL GetPhysicalDriveStorageInformation(UINT nDriveNumber, STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR* pAlignmentDesc, STORAGE_ADAPTER_DESCRIPTOR* pAdapterDesc)
+{
+ DWORD dwRet = NO_ERROR;
+
+ if (!pAlignmentDesc || pAdapterDesc)
+ {
+ SetLastError (ERROR_INVALID_PARAMETER);
+ 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;
+
+ BOOL bRet = (GetDeviceStorageProperty (hDevice, StorageAccessAlignmentProperty, sizeof (STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR), pAlignmentDesc)
+ || GetDeviceStorageProperty (hDevice, StorageAdapterProperty, sizeof (STORAGE_ADAPTER_DESCRIPTOR), pAdapterDesc))? TRUE : FALSE;
dwRet = ::GetLastError();
::CloseHandle(hDevice);
@@ -7621,6 +7682,13 @@ retry:
if (!bDevice)
{
+ // put default values
+ mount.BytesPerSector = 512;
+ mount.BytesPerPhysicalSector = 512;
+ mount.MaximumTransferLength = 65536;
+ mount.MaximumPhysicalPages = 17;
+ mount.AlignmentMask = 0;
+
// UNC path
if (path.find (L"\\\\") == 0)
{
@@ -7655,11 +7723,23 @@ retry:
{
if (extents.NumberOfDiskExtents > 0)
{
- STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR desc;
- if (GetPhysicalDriveAlignment (extents.Extents[0].DiskNumber, &desc))
+ STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR accessDesc;
+ STORAGE_ADAPTER_DESCRIPTOR adapterDesc;
+
+ if (GetPhysicalDriveStorageInformation (extents.Extents[0].DiskNumber, &accessDesc, &adapterDesc))
{
- mount.BytesPerSector = desc.BytesPerLogicalSector;
- mount.BytesPerPhysicalSector = desc.BytesPerPhysicalSector;
+ if (accessDesc.Size >= sizeof (STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR))
+ {
+ mount.BytesPerSector = accessDesc.BytesPerLogicalSector;
+ mount.BytesPerPhysicalSector = accessDesc.BytesPerPhysicalSector;
+ }
+
+ if (adapterDesc.Size >= sizeof (STORAGE_ADAPTER_DESCRIPTOR))
+ {
+ mount.MaximumTransferLength = adapterDesc.MaximumTransferLength;
+ mount.MaximumPhysicalPages = adapterDesc.MaximumPhysicalPages;
+ mount.AlignmentMask = adapterDesc.AlignmentMask;
+ }
}
}
}
diff --git a/src/Driver/Ntdriver.h b/src/Driver/Ntdriver.h
index 5b52ab04..09a29542 100644
--- a/src/Driver/Ntdriver.h
+++ b/src/Driver/Ntdriver.h
@@ -63,6 +63,9 @@ typedef struct EXTENSION
uint32 HostBytesPerSector;
uint32 HostBytesPerPhysicalSector;
+ ULONG HostMaximumTransferLength;
+ ULONG HostMaximumPhysicalPages;
+ ULONG HostAlignmentMask;
KEVENT keVolumeEvent; /* Event structure used when setting up a device */
diff --git a/src/Driver/Ntvol.c b/src/Driver/Ntvol.c
index 8fda0bd9..8be0393a 100644
--- a/src/Driver/Ntvol.c
+++ b/src/Driver/Ntvol.c
@@ -63,6 +63,11 @@ NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject,
Extension->hDeviceFile = NULL;
Extension->bTimeStampValid = FALSE;
+ /* default value for storage alignment */
+ Extension->HostMaximumTransferLength = 65536;
+ Extension->HostMaximumPhysicalPages = 17;
+ Extension->HostAlignmentMask = 0;
+
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);
@@ -129,6 +134,31 @@ NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject,
TCfree (outputBuffer);
}
+
+ storagePropertyQuery.PropertyId = StorageAdapterProperty;
+ if (NT_SUCCESS (TCSendHostDeviceIoControlRequestEx (DeviceObject, Extension, IOCTL_STORAGE_QUERY_PROPERTY,
+ (char*) &storagePropertyQuery, sizeof(storagePropertyQuery),
+ (char *) &storageHeader, sizeof (storageHeader))))
+ {
+ byte* outputBuffer = TCalloc (storageHeader.Size);
+ if (!outputBuffer)
+ {
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ goto error;
+ }
+
+ if (NT_SUCCESS (TCSendHostDeviceIoControlRequestEx (DeviceObject, Extension, IOCTL_STORAGE_QUERY_PROPERTY,
+ (char*) &storagePropertyQuery, sizeof(storagePropertyQuery),
+ outputBuffer, storageHeader.Size)))
+ {
+ PSTORAGE_ADAPTER_DESCRIPTOR pStorageDescriptor = (PSTORAGE_ADAPTER_DESCRIPTOR) outputBuffer;
+ Extension->HostMaximumTransferLength = pStorageDescriptor->MaximumTransferLength;
+ Extension->HostMaximumPhysicalPages = pStorageDescriptor->MaximumPhysicalPages;
+ Extension->HostAlignmentMask = pStorageDescriptor->AlignmentMask;
+ }
+
+ TCfree (outputBuffer);
+ }
}
// Drive geometry is used only when IOCTL_DISK_GET_PARTITION_INFO fails
@@ -179,6 +209,9 @@ NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject,
Extension->HostBytesPerSector = mount->BytesPerSector;
Extension->HostBytesPerPhysicalSector = mount->BytesPerPhysicalSector;
+ Extension->HostMaximumTransferLength = mount->MaximumTransferLength;
+ Extension->HostMaximumPhysicalPages = mount->MaximumPhysicalPages;
+ Extension->HostAlignmentMask = mount->AlignmentMask;
if (Extension->HostBytesPerSector != TC_SECTOR_SIZE_FILE_HOSTED_VOLUME)
disableBuffering = FALSE;