[misc] apply a timeout when querying drives for letters/type

* Some Windows Store reports suggest that the existing call might freeze
  on CreateFile() leading some users to kill the app. So switch to using
  a CreateFile() call that times out instead of waiting forever...
This commit is contained in:
Pete Batard 2023-05-03 16:26:54 +01:00
parent 0df68b6af9
commit 23d89d9764
No known key found for this signature in database
GPG Key ID: 38E0CF5E69EDD671
4 changed files with 74 additions and 8 deletions

View File

@ -1149,10 +1149,13 @@ static BOOL _GetDriveLettersAndType(DWORD DriveIndex, char* drive_letters, UINT*
continue;
static_sprintf(logical_drive, "\\\\.\\%c:", toupper(drive[0]));
hDrive = CreateFileA(logical_drive, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
// This call appears to freeze on some systems and we don't want to spend more
// time than needed waiting for unresponsive drives, so use a 3 seconds timeout.
hDrive = CreateFileWithTimeout(logical_drive, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL, 3000);
if (hDrive == INVALID_HANDLE_VALUE) {
// uprintf("Warning: could not open drive %c: %s", toupper(drive[0]), WindowsErrorString());
if (GetLastError() == WAIT_TIMEOUT)
uprintf("Warning: Time-out while trying to query drive %c", toupper(drive[0]));
continue;
}

View File

@ -684,6 +684,9 @@ extern BOOL ValidateOpensslSignature(BYTE* pbBuffer, DWORD dwBufferLen, BYTE* pb
extern BOOL IsFontAvailable(const char* font_name);
extern BOOL WriteFileWithRetry(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten, DWORD nNumRetries);
extern HANDLE CreateFileWithTimeout(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile, DWORD dwTimeOut);
extern BOOL SetThreadAffinity(DWORD_PTR* thread_affinity, size_t num_threads);
extern BOOL HashFile(const unsigned type, const char* path, uint8_t* sum);
extern BOOL HashBuffer(const unsigned type, const uint8_t* buf, const size_t len, uint8_t* sum);

View File

@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 232, 326
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_ACCEPTFILES
CAPTION "Rufus 4.0.2037"
CAPTION "Rufus 4.0.2038"
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
BEGIN
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
@ -392,8 +392,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,0,2037,0
PRODUCTVERSION 4,0,2037,0
FILEVERSION 4,0,2038,0
PRODUCTVERSION 4,0,2038,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -411,13 +411,13 @@ BEGIN
VALUE "Comments", "https://rufus.ie"
VALUE "CompanyName", "Akeo Consulting"
VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "4.0.2037"
VALUE "FileVersion", "4.0.2038"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2023 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
VALUE "OriginalFilename", "rufus-4.0.exe"
VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "4.0.2037"
VALUE "ProductVersion", "4.0.2038"
END
END
BLOCK "VarFileInfo"

View File

@ -863,6 +863,66 @@ const char* StrError(DWORD error_code, BOOL use_default_locale)
return ret;
}
typedef struct
{
LPCWSTR lpFileName;
DWORD dwDesiredAccess;
DWORD dwShareMode;
DWORD dwCreationDisposition;
DWORD dwFlagsAndAttributes;
HANDLE hFile;
DWORD dwError;
} cfx_params_t;
// Thread used by CreateFileWithTimeout() below
DWORD WINAPI CreateFileWithTimeoutThread(void* params)
{
cfx_params_t* cfx_params = (cfx_params_t*)params;
HANDLE hFile = CreateFileW(cfx_params->lpFileName, cfx_params->dwDesiredAccess,
cfx_params->dwShareMode, NULL, cfx_params->dwCreationDisposition,
cfx_params->dwFlagsAndAttributes, NULL);
cfx_params->dwError = (hFile == INVALID_HANDLE_VALUE) ? GetLastError() : NOERROR;
cfx_params->hFile = hFile;
return cfx_params->dwError;
}
// A UTF-8 CreateFile() with timeout
HANDLE CreateFileWithTimeout(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile, DWORD dwTimeOut)
{
HANDLE hThread;
wconvert(lpFileName);
cfx_params_t params = {
wlpFileName,
dwDesiredAccess,
dwShareMode,
dwCreationDisposition,
dwFlagsAndAttributes,
INVALID_HANDLE_VALUE,
ERROR_IO_PENDING,
};
hThread = CreateThread(NULL, 0, CreateFileWithTimeoutThread, &params, 0, NULL);
if (hThread != NULL) {
if (WaitForSingleObject(hThread, dwTimeOut) == WAIT_TIMEOUT) {
CancelSynchronousIo(hThread);
WaitForSingleObject(hThread, INFINITE);
params.dwError = WAIT_TIMEOUT;
}
CloseHandle(hThread);
} else {
params.dwError = GetLastError();
}
wfree(lpFileName);
SetLastError(params.dwError);
return params.hFile;
}
// A WriteFile() equivalent, with up to nNumRetries write attempts on error.
BOOL WriteFileWithRetry(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten, DWORD nNumRetries)