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…
	
	Add table
		Add a link
		
	
		Reference in a new issue