From cda40547fe35b28321f7a00b53cc18eb9cf77cba Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Tue, 23 May 2017 12:23:07 +0200 Subject: Windows: query extra host drive information using IOCTL_STORAGE_QUERY_PROPERTY (StorageAdapterProperty) in both driver and user mode applications. --- src/Common/Apidrvr.h | 3 ++ src/Common/Dlgcode.c | 114 +++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 100 insertions(+), 17 deletions(-) (limited to 'src/Common') 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; + } } } } -- cgit v1.2.3