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 ((iso_label != NULL) && (usb_label != NULL)) { | ||||||
| 			if (replace_in_token_data(src, (props->is_grub_cfg) ? "linuxefi" : "append", | 			if (replace_in_token_data(src, (props->is_grub_cfg) ? "linuxefi" : "append", | ||||||
| 				iso_label, usb_label, TRUE) != NULL) | 				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(iso_label); | ||||||
| 		safe_free(usb_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(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); | 			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) | 			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(iso_label); | ||||||
| 		safe_free(usb_label); | 		safe_free(usb_label); | ||||||
|  | @ -896,7 +896,7 @@ out: | ||||||
| 			fclose(fd); | 			fclose(fd); | ||||||
| 			fd = NULL; | 			fd = NULL; | ||||||
| 			safe_sprintf(path2, sizeof(path2), "%s\\syslinux.org", dest_dir); | 			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)); | 			IGNORE_RETVAL(rename(path, path2)); | ||||||
| 		} | 		} | ||||||
| 		if (fd == NULL) { | 		if (fd == NULL) { | ||||||
|  |  | ||||||
|  | @ -276,6 +276,11 @@ static __inline int LoadStringU(HINSTANCE hInstance, UINT uID, LPSTR lpBuffer, i | ||||||
| { | { | ||||||
| 	int ret; | 	int ret; | ||||||
| 	DWORD err = ERROR_INVALID_DATA; | 	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]
 | 	// coverity[returned_null]
 | ||||||
| 	walloc(lpBuffer, nBufferMax); | 	walloc(lpBuffer, nBufferMax); | ||||||
| 	ret = LoadStringW(hInstance, uID, wlpBuffer, nBufferMax); | 	ret = LoadStringW(hInstance, uID, wlpBuffer, nBufferMax); | ||||||
|  | @ -461,6 +466,15 @@ static __inline BOOL DeleteFileU(const char* lpFileName) | ||||||
| 	return ret; | 	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) | static __inline int PathGetDriveNumberU(char* lpPath) | ||||||
| { | { | ||||||
| 	int ret = 0; | 	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 we're switching process and found a match, print it
 | ||||||
| 			if (bFound) { | 			if (bFound) { | ||||||
| 				vuprintf("● '%s' (pid: %ld, access: %s)", exe_path, pid[cur_pid], access_rights_str[access_rights & 0x7]); | 				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); | 				StrArrayAdd(&BlockingProcess, tmp, TRUE); | ||||||
| 				bFound = FALSE; | 				bFound = FALSE; | ||||||
| 				access_rights = 0; | 				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 | #ifdef RUFUS_TEST | ||||||
| 	extern int SelectionDyn(char* title, char* message, char** szChoice, int nChoices); | 	extern int SelectionDyn(char* title, char* message, char** szChoice, int nChoices); | ||||||
| #endif | #endif | ||||||
|  | @ -2189,7 +2248,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | ||||||
| 	case WM_COMMAND: | 	case WM_COMMAND: | ||||||
| #ifdef RUFUS_TEST | #ifdef RUFUS_TEST | ||||||
| 		if (LOWORD(wParam) == IDC_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" };
 | //			char* choices[] = { "Choice 1", "Choice 2", "Choice 3" };
 | ||||||
| //			SelectionDyn("Test Choice", "Unused", choices, ARRAYSIZE(choices));
 | //			SelectionDyn("Test Choice", "Unused", choices, ARRAYSIZE(choices));
 | ||||||
| 			break; | 			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)); | 				GetWindowTextU(hDeviceList, tmp, ARRAYSIZE(tmp)); | ||||||
| 				if (MessageBoxExU(hMainDialog, lmprintf(MSG_003, tmp), | 				if (MessageBoxExU(hMainDialog, lmprintf(MSG_003, tmp), | ||||||
| 					APPLICATION_NAME, MB_OKCANCEL|MB_ICONWARNING|MB_IS_RTL, selected_langid) == IDCANCEL) { | 					APPLICATION_NAME, MB_OKCANCEL|MB_ICONWARNING|MB_IS_RTL, selected_langid) == IDCANCEL) { | ||||||
|  |  | ||||||
|  | @ -160,6 +160,7 @@ enum notification_type { | ||||||
| 	MSG_WARNING, | 	MSG_WARNING, | ||||||
| 	MSG_ERROR, | 	MSG_ERROR, | ||||||
| 	MSG_QUESTION, | 	MSG_QUESTION, | ||||||
|  | 	MSG_WARNING_QUESTION | ||||||
| }; | }; | ||||||
| typedef INT_PTR (CALLBACK *Callback_t)(HWND, UINT, WPARAM, LPARAM); | typedef INT_PTR (CALLBACK *Callback_t)(HWND, UINT, WPARAM, LPARAM); | ||||||
| typedef struct { | 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 char* _printbits(size_t const size, void const * const ptr, int leading_zeroes); | ||||||
| extern BOOL IsCurrentProcessElevated(void); | extern BOOL IsCurrentProcessElevated(void); | ||||||
| extern char* GetCurrentMUI(void); | extern char* GetCurrentMUI(void); | ||||||
|  | extern char* GetMuiString(char* szModuleName, UINT uID); | ||||||
| extern BOOL SetFormatPromptHook(void); | extern BOOL SetFormatPromptHook(void); | ||||||
| extern void ClrFormatPromptHook(void); | extern void ClrFormatPromptHook(void); | ||||||
| extern BYTE SearchProcess(char* HandleName, BOOL bPartialMatch, BOOL bIgnoreSelf, BOOL bQuiet); | 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 | IDD_DIALOG DIALOGEX 12, 12, 242, 376 | ||||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||||
| EXSTYLE WS_EX_ACCEPTFILES | EXSTYLE WS_EX_ACCEPTFILES | ||||||
| CAPTION "Rufus 2.16.1126" | CAPTION "Rufus 2.16.1127" | ||||||
| FONT 8, "Segoe UI Symbol", 400, 0, 0x0 | FONT 8, "Segoe UI Symbol", 400, 0, 0x0 | ||||||
| BEGIN | BEGIN | ||||||
|     LTEXT           "Device",IDS_DEVICE_TXT,9,6,200,8 |     LTEXT           "Device",IDS_DEVICE_TXT,9,6,200,8 | ||||||
|  | @ -366,8 +366,8 @@ END | ||||||
| // | // | ||||||
| 
 | 
 | ||||||
| VS_VERSION_INFO VERSIONINFO | VS_VERSION_INFO VERSIONINFO | ||||||
|  FILEVERSION 2,16,1126,0 |  FILEVERSION 2,16,1127,0 | ||||||
|  PRODUCTVERSION 2,16,1126,0 |  PRODUCTVERSION 2,16,1127,0 | ||||||
|  FILEFLAGSMASK 0x3fL |  FILEFLAGSMASK 0x3fL | ||||||
| #ifdef _DEBUG | #ifdef _DEBUG | ||||||
|  FILEFLAGS 0x1L |  FILEFLAGS 0x1L | ||||||
|  | @ -384,13 +384,13 @@ BEGIN | ||||||
|         BEGIN |         BEGIN | ||||||
|             VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" |             VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" | ||||||
|             VALUE "FileDescription", "Rufus" |             VALUE "FileDescription", "Rufus" | ||||||
|             VALUE "FileVersion", "2.16.1126" |             VALUE "FileVersion", "2.16.1127" | ||||||
|             VALUE "InternalName", "Rufus" |             VALUE "InternalName", "Rufus" | ||||||
|             VALUE "LegalCopyright", "© 2011-2017 Pete Batard (GPL v3)" |             VALUE "LegalCopyright", "© 2011-2017 Pete Batard (GPL v3)" | ||||||
|             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" |             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" | ||||||
|             VALUE "OriginalFilename", "rufus.exe" |             VALUE "OriginalFilename", "rufus.exe" | ||||||
|             VALUE "ProductName", "Rufus" |             VALUE "ProductName", "Rufus" | ||||||
|             VALUE "ProductVersion", "2.16.1126" |             VALUE "ProductVersion", "2.16.1127" | ||||||
|         END |         END | ||||||
|     END |     END | ||||||
|     BLOCK "VarFileInfo" |     BLOCK "VarFileInfo" | ||||||
|  |  | ||||||
							
								
								
									
										32
									
								
								src/stdfn.c
									
										
									
									
									
								
							
							
						
						
									
										32
									
								
								src/stdfn.c
									
										
									
									
									
								
							|  | @ -909,3 +909,35 @@ char* GetCurrentMUI(void) | ||||||
| 	} | 	} | ||||||
| 	return mui_str; | 	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; | 	notification_is_question = FALSE; | ||||||
| 
 | 
 | ||||||
| 	switch(type) { | 	switch(type) { | ||||||
|  | 	case MSG_WARNING_QUESTION: | ||||||
|  | 		notification_is_question = TRUE; | ||||||
|  | 		// Fall through
 | ||||||
| 	case MSG_WARNING: | 	case MSG_WARNING: | ||||||
| 		hMessageIcon = LoadIcon(NULL, IDI_WARNING); | 		hMessageIcon = LoadIcon(NULL, IDI_WARNING); | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue