From 09d2f2f0ab218d2ab5dd63dadd5cd7e1ec63d654 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Fri, 10 Jul 2020 11:55:29 +0100 Subject: [PATCH] [ui] add cheat mode (Alt +/-) to increase/decrease thread priority * This *may* help improve write speeds if your system is starved for I/O * Related to #968 --- res/loc/ChangeLog.txt | 7 +++-- res/loc/rufus.loc | 3 +- src/checksum.c | 2 ++ src/rufus.c | 69 ++++++++++++++++++++++++++++--------------- src/rufus.rc | 10 +++---- src/settings.h | 1 + src/vhd.c | 17 ++++++----- 7 files changed, 70 insertions(+), 39 deletions(-) diff --git a/res/loc/ChangeLog.txt b/res/loc/ChangeLog.txt index 407a5207..13881ac5 100644 --- a/res/loc/ChangeLog.txt +++ b/res/loc/ChangeLog.txt @@ -12,14 +12,17 @@ o v3.* - *NEW* MSG_309 "Compressed archive" // TODO: Add a test ISO for this. - *NEW* MSG_310 "The ISO you have selected uses UEFI and is small enough to be written as (...)" - - *NEW* MSG_311 "Use %s in the main application window to enable." + - *NEW* MSG_311 "Use %s (in the main application window) to enable." - *NEW* MSG_312 "Extra hashes (SHA512)" // The following are accessibility labels for some UI elements + // Can be tested with https://accessibilityinsights.io/docs/en/windows/overview - *NEW* MSG_313 "Save to VHD" - *NEW* MSG_314 "Compute image checksums" - *NEW* MSG_315 "Multiple buttons" - *NEW* MSG_316 "Number of passes" - - *NEW* MSG_317 "Disk ID" + - *NEW* MSG_317 "Disk ID" + // The following can be tested with -<+> and -<-> + - *NEW* MSG_318 "Default thread priority: %d" o v3.5 (2019.03.12) The following 3 messages can be tested by creating a UEFI:NTFS drive in Rufus ('Show advanced drive properties' must be enabled diff --git a/res/loc/rufus.loc b/res/loc/rufus.loc index a70a0d06..1f4374fb 100644 --- a/res/loc/rufus.loc +++ b/res/loc/rufus.loc @@ -570,13 +570,14 @@ t MSG_309 "Compressed archive" t MSG_310 "The ISO you have selected uses UEFI and is small enough to be written as an EFI System Partition (ESP). " "Writing to an ESP, instead of writing to a generic data partition occupying the whole disk, can be preferable " "for some types of installations.\n\nPlease select the mode that you want to use to write this image:" -t MSG_311 "Use %s in the main application window to enable." +t MSG_311 "Use %s (in the main application window) to enable." t MSG_312 "Extra hashes (SHA512)" t MSG_313 "Save to VHD" t MSG_314 "Compute image checksums" t MSG_315 "Multiple buttons" t MSG_316 "Number of passes" t MSG_317 "Disk ID" +t MSG_318 "Default thread priority: %d" ######################################################################### l "ar-SA" "Arabic (العربية)" 0x0401, 0x0801, 0x0c01, 0x1001, 0x1401, 0x1801, 0x1c01, 0x2001, 0x2401, 0x2801, 0x2c01, 0x3001, 0x3401, 0x3801, 0x3c01, 0x4001 diff --git a/src/checksum.c b/src/checksum.c index 579d031f..0b24640e 100644 --- a/src/checksum.c +++ b/src/checksum.c @@ -93,6 +93,7 @@ HANDLE data_ready[CHECKSUM_MAX] = { 0 }, thread_ready[CHECKSUM_MAX] = { 0 }; DWORD read_size[2]; BOOL enable_extra_hashes = FALSE; uint8_t ALIGNED(64) buffer[2][BUFFER_SIZE]; +extern int default_thread_priority; /* * Rotate 32 or 64 bit integers by n bytes. @@ -1152,6 +1153,7 @@ DWORD WINAPI SumThread(void* param) uprintf("Unable to start checksum thread #%d", i); goto out; } + SetThreadPriority(sum_thread[i], default_thread_priority); if (thread_affinity[i+1] != 0) SetThreadAffinityMask(sum_thread[i], thread_affinity[i+1]); } diff --git a/src/rufus.c b/src/rufus.c index d028d440..2fd4d06d 100755 --- a/src/rufus.c +++ b/src/rufus.c @@ -77,13 +77,13 @@ static int selected_pt = -1, selected_fs = FS_UNKNOWN, preselected_fs = FS_UNKNO static int image_index = 0, select_index = 0; static RECT relaunch_rc = { -65536, -65536, 0, 0}; static UINT uMBRChecked = BST_UNCHECKED; -static HANDLE format_thid = NULL; +static HANDLE format_thread = NULL; static HWND hSelectImage = NULL, hStart = NULL; static char szTimer[12] = "00:00:00"; static unsigned int timer; static char uppercase_select[2][64], uppercase_start[64], uppercase_close[64], uppercase_cancel[64]; -extern HANDLE update_check_thread; +extern HANDLE update_check_thread, apply_wim_thread; extern BOOL enable_iso, enable_joliet, enable_rockridge, enable_extra_hashes; extern BYTE* fido_script; extern HWND hFidoDlg; @@ -121,7 +121,7 @@ BOOL write_as_image = FALSE, write_as_esp = FALSE, installed_uefi_ntfs = FALSE, float fScale = 1.0f; int dialog_showing = 0, selection_default = BT_IMAGE, windows_to_go_selection = 0, persistence_unit_selection = -1; int default_fs, fs_type, boot_type, partition_type, target_type; // file system, boot type, partition type, target type -int force_update = 0; +int force_update = 0, default_thread_priority = THREAD_PRIORITY_ABOVE_NORMAL; char szFolderPath[MAX_PATH], app_dir[MAX_PATH], system_dir[MAX_PATH], temp_dir[MAX_PATH], sysnative_dir[MAX_PATH]; char embedded_sl_version_str[2][12] = { "?.??", "?.??" }; char embedded_sl_version_ext[2][32]; @@ -1770,7 +1770,7 @@ static void SaveVHD(void) EXT_DECL(img_ext, filename, __VA_GROUP__("*.vhd"), __VA_GROUP__(lmprintf(MSG_095))); ULARGE_INTEGER free_space; - if ((DriveIndex < 0) || (format_thid != NULL)) + if ((DriveIndex < 0) || (format_thread != NULL)) return; static_sprintf(filename, "%s.vhd", DriveLabel.String[DriveIndex]); @@ -1791,8 +1791,8 @@ static void SaveVHD(void) EnableControls(FALSE, FALSE); FormatStatus = 0; InitProgress(TRUE); - format_thid = CreateThread(NULL, 0, SaveImageThread, &img_save, 0, NULL); - if (format_thid != NULL) { + format_thread = CreateThread(NULL, 0, SaveImageThread, &img_save, 0, NULL); + if (format_thread != NULL) { uprintf("\r\nSave to VHD operation started"); PrintInfo(0, -1); SendMessage(hMainDialog, UM_TIMER_START, 0, 0); @@ -1822,7 +1822,7 @@ static void SaveISO(void) char filename[33] = "disc_image.iso"; EXT_DECL(img_ext, filename, __VA_GROUP__("*.iso"), __VA_GROUP__(lmprintf(MSG_036))); - if (op_in_progress || (format_thid != NULL)) + if (op_in_progress || (format_thread != NULL)) return; img_save.Type = IMG_SAVE_TYPE_ISO; @@ -1846,8 +1846,8 @@ static void SaveISO(void) // Disable all controls except cancel EnableControls(FALSE, FALSE); InitProgress(TRUE); - format_thid = CreateThread(NULL, 0, SaveImageThread, &img_save, 0, NULL); - if (format_thid != NULL) { + format_thread = CreateThread(NULL, 0, SaveImageThread, &img_save, 0, NULL); + if (format_thread != NULL) { uprintf("\r\nSave to ISO operation started"); PrintInfo(0, -1); SendMessage(hMainDialog, UM_TIMER_START, 0, 0); @@ -1998,11 +1998,11 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA case IDOK: // close application case IDCANCEL: EnableWindow(GetDlgItem(hDlg, IDCANCEL), FALSE); - if (format_thid != NULL) { + if (format_thread != NULL) { if ((no_confirmation_on_cancel) || (MessageBoxExU(hMainDialog, lmprintf(MSG_105), lmprintf(MSG_049), MB_YESNO|MB_ICONWARNING|MB_IS_RTL, selected_langid) == IDYES)) { // Operation may have completed in the meantime - if (format_thid != NULL) { + if (format_thread != NULL) { FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANCELLED; PrintInfo(0, MSG_201); uprintf("Cancelling"); @@ -2303,7 +2303,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA } break; case IDC_START: - if (format_thid != NULL) + if (format_thread != NULL) return (INT_PTR)TRUE; // Just in case boot_type = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType)); @@ -2340,7 +2340,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA MyDialogBox(hMainInstance, IDD_UPDATE_POLICY, hDlg, UpdateCallback); break; case IDC_HASH: - if ((format_thid == NULL) && (image_path != NULL)) { + if ((format_thread == NULL) && (image_path != NULL)) { FormatStatus = 0; no_confirmation_on_cancel = TRUE; SendMessage(hMainDialog, UM_PROGRESS_INIT, 0, 0); @@ -2348,8 +2348,9 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA EnableControls(FALSE, FALSE); InitProgress(FALSE); SetThreadAffinity(thread_affinity, CHECKSUM_MAX + 1); - format_thid = CreateThread(NULL, 0, SumThread, (LPVOID)thread_affinity, 0, NULL); - if (format_thid != NULL) { + format_thread = CreateThread(NULL, 0, SumThread, (LPVOID)thread_affinity, 0, NULL); + if (format_thread != NULL) { + SetThreadPriority(format_thread, default_thread_priority); PrintInfo(0, -1); SendMessage(hMainDialog, UM_TIMER_START, 0, 0); } else { @@ -2420,7 +2421,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA // DO *NOT* USE WM_DEVICECHANGE AS THE MESSAGE FROM THE TIMER PROC, as it may be filtered! // For instance filtering will occur when (un)plugging in a FreeBSD UFD on Windows 8. // Instead, use a custom user message, such as UM_MEDIA_CHANGE, to set DBT_CUSTOMEVENT. - if (format_thid == NULL) { + if (format_thread == NULL) { switch (wParam) { case DBT_DEVICEARRIVAL: case DBT_DEVICEREMOVECOMPLETE: @@ -2763,18 +2764,19 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA nDeviceIndex = ComboBox_GetCurSel(hDeviceList); DeviceNum = (DWORD)ComboBox_GetItemData(hDeviceList, nDeviceIndex); InitProgress(zero_drive || write_as_image); - format_thid = CreateThread(NULL, 0, FormatThread, (LPVOID)(uintptr_t)DeviceNum, 0, NULL); - if (format_thid == NULL) { + format_thread = CreateThread(NULL, 0, FormatThread, (LPVOID)(uintptr_t)DeviceNum, 0, NULL); + if (format_thread == NULL) { uprintf("Unable to start formatting thread"); FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_CANT_START_THREAD); PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)FALSE, 0); } else { + SetThreadPriority(format_thread, default_thread_priority); uprintf("\r\nFormat operation started"); SendMessage(hMainDialog, UM_TIMER_START, 0, 0); // Set focus to the Cancel button SendMessage(hMainDialog, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hMainDialog, IDCANCEL), TRUE); } - if (format_thid != NULL) + if (format_thread != NULL) break; aborted_start: zero_drive = FALSE; @@ -2790,7 +2792,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA case UM_FORMAT_COMPLETED: zero_drive = FALSE; - format_thid = NULL; + format_thread = NULL; // Stop the timer KillTimer(hMainDialog, TID_APP_TIMER); // Close the cancel MessageBox and Blocking notification if active @@ -3169,6 +3171,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine enable_file_indexing = ReadSettingBool(SETTING_ENABLE_FILE_INDEXING); enable_VHDs = !ReadSettingBool(SETTING_DISABLE_VHDS); enable_extra_hashes = ReadSettingBool(SETTING_ENABLE_EXTRA_HASHES); + // We want above normal priority by default, so we offset the value. + default_thread_priority = ReadSetting32(SETTING_DEFAULT_THREAD_PRIORITY) + THREAD_PRIORITY_ABOVE_NORMAL; // Initialize the global scaling, in case we need it before we initialize the dialog hDC = GetDC(NULL); @@ -3336,8 +3340,8 @@ relaunch: while(GetMessage(&msg, NULL, 0, 0)) { static BOOL ctrl_without_focus = FALSE; BOOL no_focus = (msg.message == WM_SYSKEYDOWN) && !(msg.lParam & 0x20000000); - // ** *********** ************* - // .,ABCDEFGHIJKLMNOPQRSTUVWXYZ + // ** *********** *************** + // .,ABCDEFGHIJKLMNOPQRSTUVWXYZ+- // Sigh... The things one need to do to detect standalone use of the 'Alt' key. if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam != VK_MENU)) @@ -3386,6 +3390,23 @@ relaunch: if (no_focus) continue; + // Alt +/- => Increase or decrease thread priority for format/file-copy/wim-apply operations + if ((msg.message == WM_SYSKEYDOWN) && ((msg.wParam == VK_OEM_PLUS) || (msg.wParam == VK_OEM_MINUS) || + (msg.wParam == VK_ADD) || (msg.wParam == VK_SUBTRACT))) { + int delta = ((msg.wParam == VK_OEM_PLUS) || (msg.wParam == VK_ADD)) ? +1 : -1; + if (((delta == +1) && (default_thread_priority < THREAD_PRIORITY_HIGHEST)) || + ((delta == -1) && (default_thread_priority > THREAD_PRIORITY_LOWEST))) { + default_thread_priority += delta; + WriteSetting32(SETTING_DEFAULT_THREAD_PRIORITY, default_thread_priority - THREAD_PRIORITY_ABOVE_NORMAL); + if (format_thread != NULL) + SetThreadPriority(format_thread, default_thread_priority); + if (apply_wim_thread != NULL) + SetThreadPriority(apply_wim_thread, default_thread_priority); + } + PrintStatus(STATUS_MSG_TIMEOUT, MSG_318, default_thread_priority); + continue; + } + // The following cheat modes should not be enacted when an operation is in progress if (!op_in_progress) { // Alt-. => Enable USB enumeration debug @@ -3424,7 +3445,7 @@ relaunch: // Alt-D => Delete the 'rufus_files' subdirectory if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'D')) { static_sprintf(tmp_path, "%s\\%s", app_dir, FILES_DIR); - PrintStatus(2000, MSG_264, tmp_path); + PrintStatus(STATUS_MSG_TIMEOUT, MSG_264, tmp_path); SHDeleteDirectoryExU(NULL, tmp_path, FOF_SILENT | FOF_NOERRORUI | FOF_NOCONFIRMATION); continue; } @@ -3528,7 +3549,7 @@ relaunch: } // Alt-R => Remove all the registry keys that may have been created by Rufus if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'R')) { - PrintStatus(2000, DeleteRegistryKey(REGKEY_HKCU, COMPANY_NAME "\\" APPLICATION_NAME) ? MSG_248 : MSG_249); + PrintStatus(STATUS_MSG_TIMEOUT, DeleteRegistryKey(REGKEY_HKCU, COMPANY_NAME "\\" APPLICATION_NAME) ? MSG_248 : MSG_249); // Also try to delete the upper key (company name) if it's empty (don't care about the result) DeleteRegistryKey(REGKEY_HKCU, COMPANY_NAME); continue; diff --git a/src/rufus.rc b/src/rufus.rc index 7817b975..ad1cddae 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -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 3.12.1688" +CAPTION "Rufus 3.12.1689" FONT 9, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP @@ -397,8 +397,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 3,12,1688,0 - PRODUCTVERSION 3,12,1688,0 + FILEVERSION 3,12,1689,0 + PRODUCTVERSION 3,12,1689,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -416,13 +416,13 @@ BEGIN VALUE "Comments", "https://rufus.ie" VALUE "CompanyName", "Akeo Consulting" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "3.12.1688" + VALUE "FileVersion", "3.12.1689" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2020 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" VALUE "OriginalFilename", "rufus-3.12.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "3.12.1688" + VALUE "ProductVersion", "3.12.1689" END END BLOCK "VarFileInfo" diff --git a/src/settings.h b/src/settings.h index 768e1a3f..ade24de8 100644 --- a/src/settings.h +++ b/src/settings.h @@ -31,6 +31,7 @@ extern char* ini_file; #define SETTING_ADVANCED_MODE_DEVICE "ShowAdvancedDriveProperties" #define SETTING_ADVANCED_MODE_FORMAT "ShowAdvancedFormatOptions" #define SETTING_COMM_CHECK "CommCheck64" +#define SETTING_DEFAULT_THREAD_PRIORITY "DefaultThreadPriority" #define SETTING_DISABLE_FAKE_DRIVES_CHECK "DisableFakeDrivesCheck" #define SETTING_DISABLE_LGP "DisableLGP" #define SETTING_DISABLE_SECURE_BOOT_NOTICE "DisableSecureBootNotice" diff --git a/src/vhd.c b/src/vhd.c index e0704c50..47e56eb3 100644 --- a/src/vhd.c +++ b/src/vhd.c @@ -101,6 +101,8 @@ PF_TYPE_DECL(WINAPI, DWORD, WIMUnregisterMessageCallback, (HANDLE, FARPROC)); PF_TYPE_DECL(RPC_ENTRY, RPC_STATUS, UuidCreate, (UUID __RPC_FAR*)); uint32_t wim_nb_files, wim_proc_files, wim_extra_files; +HANDLE apply_wim_thread = NULL; +extern int default_thread_priority; static uint8_t wim_flags = 0; static char sevenzip_path[MAX_PATH]; @@ -730,19 +732,20 @@ out: BOOL WimApplyImage(const char* image, int index, const char* dst) { - HANDLE handle; DWORD dw = 0; _image = image; _index = index; _dst = dst; - handle = CreateThread(NULL, 0, WimApplyImageThread, NULL, 0, NULL); - if (handle == NULL) { + apply_wim_thread = CreateThread(NULL, 0, WimApplyImageThread, NULL, 0, NULL); + if (apply_wim_thread == NULL) { uprintf("Unable to start apply-image thread"); return FALSE; } - WaitForSingleObject(handle, INFINITE); - if (!GetExitCodeThread(handle, &dw)) - return FALSE; - return (BOOL)dw; + SetThreadPriority(apply_wim_thread, default_thread_priority); + WaitForSingleObject(apply_wim_thread, INFINITE); + if (!GetExitCodeThread(apply_wim_thread, &dw)) + dw = 0; + apply_wim_thread = NULL; + return dw; }