mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[ui] ask user if they want proceed when conflicting processes are found
* Rufus now checks for processes with handles opened on the drives/volumes before starting the format operation and asks the user if they want to continue. * This mimics Windows' behaviour when formatting drives, and actually uses the same message as the one from shell32.dll.mui. * Closes #773
This commit is contained in:
parent
bed889718e
commit
b4a2c06a2e
8 changed files with 127 additions and 10 deletions
|
@ -277,7 +277,7 @@ static void fix_config(const char* psz_fullpath, const char* psz_path, const cha
|
|||
if ((iso_label != NULL) && (usb_label != NULL)) {
|
||||
if (replace_in_token_data(src, (props->is_grub_cfg) ? "linuxefi" : "append",
|
||||
iso_label, usb_label, TRUE) != NULL)
|
||||
uprintf(" Patched %s: '%s' ⇨ '%s'\n", src, iso_label, usb_label);
|
||||
uprintf(" Patched %s: '%s' ➔ '%s'\n", src, iso_label, usb_label);
|
||||
}
|
||||
safe_free(iso_label);
|
||||
safe_free(usb_label);
|
||||
|
@ -301,7 +301,7 @@ static void fix_config(const char* psz_fullpath, const char* psz_path, const cha
|
|||
safe_sprintf(iso_label, MAX_PATH, "cd9660:/dev/iso9660/%s", img_report.label);
|
||||
safe_sprintf(usb_label, MAX_PATH, "msdosfs:/dev/msdosfs/%s", img_report.usb_label);
|
||||
if (replace_in_token_data(src, "set", iso_label, usb_label, TRUE) != NULL)
|
||||
uprintf(" Patched %s: '%s' ⇨ '%s'\n", src, iso_label, usb_label);
|
||||
uprintf(" Patched %s: '%s' ➔ '%s'\n", src, iso_label, usb_label);
|
||||
}
|
||||
safe_free(iso_label);
|
||||
safe_free(usb_label);
|
||||
|
@ -896,7 +896,7 @@ out:
|
|||
fclose(fd);
|
||||
fd = NULL;
|
||||
safe_sprintf(path2, sizeof(path2), "%s\\syslinux.org", dest_dir);
|
||||
uprintf("Renaming: %s ⇨ %s", path, path2);
|
||||
uprintf("Renaming: %s ➔ %s", path, path2);
|
||||
IGNORE_RETVAL(rename(path, path2));
|
||||
}
|
||||
if (fd == NULL) {
|
||||
|
|
|
@ -276,6 +276,11 @@ static __inline int LoadStringU(HINSTANCE hInstance, UINT uID, LPSTR lpBuffer, i
|
|||
{
|
||||
int ret;
|
||||
DWORD err = ERROR_INVALID_DATA;
|
||||
if (nBufferMax == 0) {
|
||||
// read-only pointer to resource mode is not supported
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
// coverity[returned_null]
|
||||
walloc(lpBuffer, nBufferMax);
|
||||
ret = LoadStringW(hInstance, uID, wlpBuffer, nBufferMax);
|
||||
|
@ -461,6 +466,15 @@ static __inline BOOL DeleteFileU(const char* lpFileName)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static __inline BOOL PathFileExistsU(char* szPath)
|
||||
{
|
||||
BOOL ret;
|
||||
wconvert(szPath);
|
||||
ret = PathFileExistsW(wszPath);
|
||||
wfree(szPath);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __inline int PathGetDriveNumberU(char* lpPath)
|
||||
{
|
||||
int ret = 0;
|
||||
|
|
|
@ -384,7 +384,7 @@ BYTE SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf, BOOL
|
|||
// If we're switching process and found a match, print it
|
||||
if (bFound) {
|
||||
vuprintf("● '%s' (pid: %ld, access: %s)", exe_path, pid[cur_pid], access_rights_str[access_rights & 0x7]);
|
||||
static_sprintf(tmp, "● %s (pid %ld)", exe_path, pid[cur_pid]);
|
||||
static_sprintf(tmp, "● %s (%s)", exe_path, access_rights_str[access_rights & 0x7]);
|
||||
StrArrayAdd(&BlockingProcess, tmp, TRUE);
|
||||
bFound = FALSE;
|
||||
access_rights = 0;
|
||||
|
|
68
src/rufus.c
68
src/rufus.c
|
@ -2153,6 +2153,65 @@ static void SaveISO(void)
|
|||
}
|
||||
}
|
||||
|
||||
// Check for conflicting processes accessing the drive, and if any,
|
||||
// ask the user whether they want to proceed.
|
||||
static BOOL CheckDriveAccess(void)
|
||||
{
|
||||
uint32_t i, j;
|
||||
BOOL bProceed = TRUE;
|
||||
BYTE access_mask;
|
||||
char *PhysicalPath, DevPath[MAX_PATH];
|
||||
char drive_letter[27], drive_name[] = "?:";
|
||||
char *message, title[128];
|
||||
|
||||
// Get the current selected device
|
||||
DWORD DeviceNum = (DWORD)ComboBox_GetItemData(hDeviceList, ComboBox_GetCurSel(hDeviceList));
|
||||
if ((DeviceNum < 0x80) || (DeviceNum == (DWORD)-1))
|
||||
return FALSE;
|
||||
|
||||
// Search for any blocking processes against the physical drive
|
||||
PhysicalPath = GetPhysicalName(DeviceNum);
|
||||
QueryDosDeviceA(&PhysicalPath[4], DevPath, sizeof(DevPath));
|
||||
access_mask = SearchProcess(DevPath, TRUE, TRUE, TRUE);
|
||||
if (access_mask != 0) {
|
||||
bProceed = FALSE;
|
||||
uprintf("Found potentially blocking process(es) against %s:", &PhysicalPath[4]);
|
||||
for (j = 0; j < BlockingProcess.Index; j++)
|
||||
uprintf(BlockingProcess.String[j]);
|
||||
}
|
||||
free(PhysicalPath);
|
||||
|
||||
// Search for any blocking processes against the logical volume(s)
|
||||
GetDriveLetters(DeviceNum, drive_letter);
|
||||
for (i = 0; drive_letter[i]; i++) {
|
||||
drive_name[0] = drive_letter[i];
|
||||
if (QueryDosDeviceA(drive_name, DevPath, sizeof(DevPath)) != 0) {
|
||||
StrArrayClear(&BlockingProcess);
|
||||
access_mask = SearchProcess(DevPath, TRUE, TRUE, TRUE);
|
||||
// Ignore if all we have is read-only
|
||||
if ((access_mask & 0x06) || (access_mask == 0x80)) {
|
||||
bProceed = FALSE;
|
||||
uprintf("Found potentially blocking process(es) against %s", drive_name);
|
||||
for (j = 0; j < BlockingProcess.Index; j++)
|
||||
uprintf(BlockingProcess.String[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prompt the user if we detected blocking processes
|
||||
if (!bProceed) {
|
||||
// We'll use a system translated string instead of one from rufus.loc
|
||||
message = GetMuiString("shell32.dll", 28701); // "This drive is in use (...) Do you want to format it anyway?"
|
||||
if (message != NULL) {
|
||||
ComboBox_GetTextU(hDeviceList, title, sizeof(title));
|
||||
bProceed = Notification(MSG_WARNING_QUESTION, NULL, title, message);
|
||||
free(message);
|
||||
}
|
||||
}
|
||||
|
||||
return bProceed;
|
||||
}
|
||||
|
||||
#ifdef RUFUS_TEST
|
||||
extern int SelectionDyn(char* title, char* message, char** szChoice, int nChoices);
|
||||
#endif
|
||||
|
@ -2189,7 +2248,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
|||
case WM_COMMAND:
|
||||
#ifdef RUFUS_TEST
|
||||
if (LOWORD(wParam) == IDC_TEST) {
|
||||
SearchProcess("\\Device\\Harddisk5\\DR5", TRUE, TRUE);
|
||||
uprintf("Proceed = %s", CheckDriveAccess()?"True":"False");
|
||||
// char* choices[] = { "Choice 1", "Choice 2", "Choice 3" };
|
||||
// SelectionDyn("Test Choice", "Unused", choices, ARRAYSIZE(choices));
|
||||
break;
|
||||
|
@ -2509,6 +2568,13 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
|||
}
|
||||
}
|
||||
|
||||
if (!CheckDriveAccess()) {
|
||||
format_op_in_progress = FALSE;
|
||||
zero_drive = FALSE;
|
||||
PROCESS_QUEUED_EVENTS;
|
||||
break;
|
||||
}
|
||||
|
||||
GetWindowTextU(hDeviceList, tmp, ARRAYSIZE(tmp));
|
||||
if (MessageBoxExU(hMainDialog, lmprintf(MSG_003, tmp),
|
||||
APPLICATION_NAME, MB_OKCANCEL|MB_ICONWARNING|MB_IS_RTL, selected_langid) == IDCANCEL) {
|
||||
|
|
|
@ -160,6 +160,7 @@ enum notification_type {
|
|||
MSG_WARNING,
|
||||
MSG_ERROR,
|
||||
MSG_QUESTION,
|
||||
MSG_WARNING_QUESTION
|
||||
};
|
||||
typedef INT_PTR (CALLBACK *Callback_t)(HWND, UINT, WPARAM, LPARAM);
|
||||
typedef struct {
|
||||
|
@ -493,6 +494,7 @@ extern BOOL IsBufferInDB(const unsigned char* buf, const size_t len);
|
|||
extern char* _printbits(size_t const size, void const * const ptr, int leading_zeroes);
|
||||
extern BOOL IsCurrentProcessElevated(void);
|
||||
extern char* GetCurrentMUI(void);
|
||||
extern char* GetMuiString(char* szModuleName, UINT uID);
|
||||
extern BOOL SetFormatPromptHook(void);
|
||||
extern void ClrFormatPromptHook(void);
|
||||
extern BYTE SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf, BOOL bQuiet);
|
||||
|
|
10
src/rufus.rc
10
src/rufus.rc
|
@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
|||
IDD_DIALOG DIALOGEX 12, 12, 242, 376
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
EXSTYLE WS_EX_ACCEPTFILES
|
||||
CAPTION "Rufus 2.16.1126"
|
||||
CAPTION "Rufus 2.16.1127"
|
||||
FONT 8, "Segoe UI Symbol", 400, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "Device",IDS_DEVICE_TXT,9,6,200,8
|
||||
|
@ -366,8 +366,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 2,16,1126,0
|
||||
PRODUCTVERSION 2,16,1126,0
|
||||
FILEVERSION 2,16,1127,0
|
||||
PRODUCTVERSION 2,16,1127,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -384,13 +384,13 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
|
||||
VALUE "FileDescription", "Rufus"
|
||||
VALUE "FileVersion", "2.16.1126"
|
||||
VALUE "FileVersion", "2.16.1127"
|
||||
VALUE "InternalName", "Rufus"
|
||||
VALUE "LegalCopyright", "© 2011-2017 Pete Batard (GPL v3)"
|
||||
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
|
||||
VALUE "OriginalFilename", "rufus.exe"
|
||||
VALUE "ProductName", "Rufus"
|
||||
VALUE "ProductVersion", "2.16.1126"
|
||||
VALUE "ProductVersion", "2.16.1127"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
32
src/stdfn.c
32
src/stdfn.c
|
@ -909,3 +909,35 @@ char* GetCurrentMUI(void)
|
|||
}
|
||||
return mui_str;
|
||||
}
|
||||
|
||||
char* GetMuiString(char* szModuleName, UINT uID)
|
||||
{
|
||||
HMODULE hModule;
|
||||
char path[MAX_PATH], *str;
|
||||
wchar_t* wstr;
|
||||
void* ptr;
|
||||
int len;
|
||||
static_sprintf(path, "%s\\%s\\%s.mui", system_dir, GetCurrentMUI(), szModuleName);
|
||||
// If the file doesn't exist, fall back to en-US
|
||||
if (!PathFileExistsU(path))
|
||||
static_sprintf(path, "%s\\en-US\\%s.mui", system_dir, szModuleName);
|
||||
hModule = LoadLibraryExA(path, NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE | LOAD_LIBRARY_AS_DATAFILE);
|
||||
if (hModule == NULL) {
|
||||
uprintf("Could not load '%s': %s", path, WindowsErrorString());
|
||||
return NULL;
|
||||
}
|
||||
// Calling LoadStringW with last parameter 0 returns the length of the string (without NUL terminator)
|
||||
len = LoadStringW(hModule, uID, (LPWSTR)(&ptr), 0);
|
||||
if (len <= 0) {
|
||||
if (GetLastError() == ERROR_SUCCESS)
|
||||
SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND);
|
||||
uprintf("Could not find string ID %d in '%s': %s", uID, path, WindowsErrorString());
|
||||
return NULL;
|
||||
}
|
||||
len += 1;
|
||||
wstr = calloc(len, sizeof(wchar_t));
|
||||
len = LoadStringW(hModule, uID, wstr, len);
|
||||
str = wchar_to_utf8(wstr);
|
||||
free(wstr);
|
||||
return str;
|
||||
}
|
||||
|
|
|
@ -823,6 +823,9 @@ BOOL Notification(int type, const notification_info* more_info, char* title, cha
|
|||
notification_is_question = FALSE;
|
||||
|
||||
switch(type) {
|
||||
case MSG_WARNING_QUESTION:
|
||||
notification_is_question = TRUE;
|
||||
// Fall through
|
||||
case MSG_WARNING:
|
||||
hMessageIcon = LoadIcon(NULL, IDI_WARNING);
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue