mirror of
https://github.com/veracrypt/VeraCrypt.git
synced 2025-11-11 11:08:02 -06:00
Windows: query extra host drive information using IOCTL_STORAGE_QUERY_PROPERTY (StorageAdapterProperty) in both driver and user mode applications.
This commit is contained in:
@@ -172,6 +172,9 @@ typedef struct
|
|||||||
BOOL bIsNTFS; // output only
|
BOOL bIsNTFS; // output only
|
||||||
BOOL bDriverSetLabel;
|
BOOL bDriverSetLabel;
|
||||||
BOOL bCachePim;
|
BOOL bCachePim;
|
||||||
|
ULONG MaximumTransferLength;
|
||||||
|
ULONG MaximumPhysicalPages;
|
||||||
|
ULONG AlignmentMask;
|
||||||
} MOUNT_STRUCT;
|
} MOUNT_STRUCT;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|||||||
@@ -7228,13 +7228,84 @@ void BroadcastDeviceChange (WPARAM message, int nDosDriveNo, DWORD driveMap)
|
|||||||
IgnoreWmDeviceChange = FALSE;
|
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;
|
DWORD dwRet = NO_ERROR;
|
||||||
|
|
||||||
if (!pDesc)
|
if (!pDesc)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
ZeroMemory (pDesc, dwDescSize);
|
||||||
|
|
||||||
|
// Set the input data structure
|
||||||
|
STORAGE_PROPERTY_QUERY storagePropertyQuery;
|
||||||
|
ZeroMemory(&storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY));
|
||||||
|
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),
|
||||||
|
&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).
|
// Format physical drive path (may be '\\.\PhysicalDrive0', '\\.\PhysicalDrive1' and so on).
|
||||||
TCHAR strDrivePath[512];
|
TCHAR strDrivePath[512];
|
||||||
StringCbPrintf(strDrivePath, sizeof(strDrivePath), _T("\\\\.\\PhysicalDrive%u"), nDriveNumber);
|
StringCbPrintf(strDrivePath, sizeof(strDrivePath), _T("\\\\.\\PhysicalDrive%u"), nDriveNumber);
|
||||||
@@ -7246,18 +7317,8 @@ BOOL GetPhysicalDriveAlignment(UINT nDriveNumber, STORAGE_ACCESS_ALIGNMENT_DESCR
|
|||||||
if(INVALID_HANDLE_VALUE == hDevice)
|
if(INVALID_HANDLE_VALUE == hDevice)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
// Set the input data structure
|
BOOL bRet = (GetDeviceStorageProperty (hDevice, StorageAccessAlignmentProperty, sizeof (STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR), pAlignmentDesc)
|
||||||
STORAGE_PROPERTY_QUERY storagePropertyQuery;
|
|| GetDeviceStorageProperty (hDevice, StorageAdapterProperty, sizeof (STORAGE_ADAPTER_DESCRIPTOR), pAdapterDesc))? TRUE : FALSE;
|
||||||
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();
|
dwRet = ::GetLastError();
|
||||||
::CloseHandle(hDevice);
|
::CloseHandle(hDevice);
|
||||||
|
|
||||||
@@ -7621,6 +7682,13 @@ retry:
|
|||||||
|
|
||||||
if (!bDevice)
|
if (!bDevice)
|
||||||
{
|
{
|
||||||
|
// put default values
|
||||||
|
mount.BytesPerSector = 512;
|
||||||
|
mount.BytesPerPhysicalSector = 512;
|
||||||
|
mount.MaximumTransferLength = 65536;
|
||||||
|
mount.MaximumPhysicalPages = 17;
|
||||||
|
mount.AlignmentMask = 0;
|
||||||
|
|
||||||
// UNC path
|
// UNC path
|
||||||
if (path.find (L"\\\\") == 0)
|
if (path.find (L"\\\\") == 0)
|
||||||
{
|
{
|
||||||
@@ -7655,11 +7723,23 @@ retry:
|
|||||||
{
|
{
|
||||||
if (extents.NumberOfDiskExtents > 0)
|
if (extents.NumberOfDiskExtents > 0)
|
||||||
{
|
{
|
||||||
STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR desc;
|
STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR accessDesc;
|
||||||
if (GetPhysicalDriveAlignment (extents.Extents[0].DiskNumber, &desc))
|
STORAGE_ADAPTER_DESCRIPTOR adapterDesc;
|
||||||
|
|
||||||
|
if (GetPhysicalDriveStorageInformation (extents.Extents[0].DiskNumber, &accessDesc, &adapterDesc))
|
||||||
{
|
{
|
||||||
mount.BytesPerSector = desc.BytesPerLogicalSector;
|
if (accessDesc.Size >= sizeof (STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR))
|
||||||
mount.BytesPerPhysicalSector = desc.BytesPerPhysicalSector;
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,9 @@ typedef struct EXTENSION
|
|||||||
|
|
||||||
uint32 HostBytesPerSector;
|
uint32 HostBytesPerSector;
|
||||||
uint32 HostBytesPerPhysicalSector;
|
uint32 HostBytesPerPhysicalSector;
|
||||||
|
ULONG HostMaximumTransferLength;
|
||||||
|
ULONG HostMaximumPhysicalPages;
|
||||||
|
ULONG HostAlignmentMask;
|
||||||
|
|
||||||
KEVENT keVolumeEvent; /* Event structure used when setting up a device */
|
KEVENT keVolumeEvent; /* Event structure used when setting up a device */
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,11 @@ NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject,
|
|||||||
Extension->hDeviceFile = NULL;
|
Extension->hDeviceFile = NULL;
|
||||||
Extension->bTimeStampValid = FALSE;
|
Extension->bTimeStampValid = FALSE;
|
||||||
|
|
||||||
|
/* default value for storage alignment */
|
||||||
|
Extension->HostMaximumTransferLength = 65536;
|
||||||
|
Extension->HostMaximumPhysicalPages = 17;
|
||||||
|
Extension->HostAlignmentMask = 0;
|
||||||
|
|
||||||
RtlInitUnicodeString (&FullFileName, pwszMountVolume);
|
RtlInitUnicodeString (&FullFileName, pwszMountVolume);
|
||||||
InitializeObjectAttributes (&oaFileAttributes, &FullFileName, OBJ_CASE_INSENSITIVE | (forceAccessCheck ? OBJ_FORCE_ACCESS_CHECK : 0) | OBJ_KERNEL_HANDLE, NULL, NULL);
|
InitializeObjectAttributes (&oaFileAttributes, &FullFileName, OBJ_CASE_INSENSITIVE | (forceAccessCheck ? OBJ_FORCE_ACCESS_CHECK : 0) | OBJ_KERNEL_HANDLE, NULL, NULL);
|
||||||
KeInitializeEvent (&Extension->keVolumeEvent, NotificationEvent, FALSE);
|
KeInitializeEvent (&Extension->keVolumeEvent, NotificationEvent, FALSE);
|
||||||
@@ -129,6 +134,31 @@ NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject,
|
|||||||
|
|
||||||
TCfree (outputBuffer);
|
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
|
// 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->HostBytesPerSector = mount->BytesPerSector;
|
||||||
Extension->HostBytesPerPhysicalSector = mount->BytesPerPhysicalSector;
|
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)
|
if (Extension->HostBytesPerSector != TC_SECTOR_SIZE_FILE_HOSTED_VOLUME)
|
||||||
disableBuffering = FALSE;
|
disableBuffering = FALSE;
|
||||||
|
|||||||
Reference in New Issue
Block a user