mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[ui] improve Windows format prompt autoclose
* Closes #794 * Also reorder some messages (so that RUFUS_TEST comes first) * Also update issue template
This commit is contained in:
		
							parent
							
								
									cebfa4cc7a
								
							
						
					
					
						commit
						9dd06e93bc
					
				
					 8 changed files with 299 additions and 207 deletions
				
			
		
							
								
								
									
										4
									
								
								.github/ISSUE_TEMPLATE.md
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/ISSUE_TEMPLATE.md
									
										
									
									
										vendored
									
									
								
							|  | @ -1,7 +1,7 @@ | |||
| <PLEASE READ THIS CAREFULLY: You *MUST* read and complete the checklist below, by placing an x into each [ ], BEFORE clicking on 'Submit new issue'. Failure to perform these steps, WHICH ARE ONLY THERE TO HELP *YOU*, will result in the issue being dismissed without warning.> | ||||
| 
 | ||||
| Checklist | ||||
| --------- | ||||
| <Please complete the following and place an x into each [ ] to confirm that you have read and performed these preliminary steps> | ||||
| 
 | ||||
| - [ ] I looked at https://github.com/pbatard/rufus/wiki/FAQ to see if my question has already been answered. | ||||
| - [ ] I performed a search in the issue tracker for similar issues, using keywords relevant to my problem. | ||||
| - [ ] I clicked the `Log` button in Rufus and copy/pasted the log into the line that says `<FULL LOG>` below. | ||||
|  |  | |||
							
								
								
									
										47
									
								
								src/format.c
									
										
									
									
									
								
							
							
						
						
									
										47
									
								
								src/format.c
									
										
									
									
									
								
							|  | @ -825,7 +825,7 @@ static BOOL ClearMBRGPT(HANDLE hPhysicalDrive, LONGLONG DiskSize, DWORD SectorSi | |||
| 	// Also, for various reasons (one of which being that Windows seems to have issues
 | ||||
| 	// with GPT drives that contain a lot of small partitions) we try not not to clear
 | ||||
| 	// sectors further than the lowest partition already residing on the disk.
 | ||||
| 	num_sectors_to_clear = min(SelectedDrive.FirstDataSector, (add1MB ? 2048 : 0) + MAX_SECTORS_TO_CLEAR); | ||||
| 	num_sectors_to_clear = min(SelectedDrive.FirstDataSector, (DWORD)((add1MB ? 2048 : 0) + MAX_SECTORS_TO_CLEAR)); | ||||
| 	uprintf("Erasing %d sectors", num_sectors_to_clear); | ||||
| 	for (i=0; i<num_sectors_to_clear; i++) { | ||||
| 		if ((IS_ERROR(FormatStatus)) || (write_sectors(hPhysicalDrive, SectorSize, i, 1, pBuf) != SectorSize)) { | ||||
|  | @ -1406,50 +1406,6 @@ static BOOL SetupWinToGo(const char* drive_name, BOOL use_ms_efi) | |||
| 	return TRUE; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Detect if a Windows Format prompt is active, by enumerating the | ||||
|  * whole Windows tree and looking for the relevant popup | ||||
|  */ | ||||
| static BOOL CALLBACK FormatPromptCallback(HWND hWnd, LPARAM lParam) | ||||
| { | ||||
| 	char str_buf[MAX_PATH]; | ||||
| 	HWND *hFound = (HWND*)lParam; | ||||
| 	static const char* security_string = "Microsoft Windows"; | ||||
| 
 | ||||
| 	// The format prompt has the popup window style
 | ||||
| 	if (GetWindowLong(hWnd, GWL_STYLE) & WS_POPUPWINDOW) { | ||||
| 		str_buf[0] = 0; | ||||
| 		GetWindowTextA(hWnd, str_buf, MAX_PATH); | ||||
| 		str_buf[MAX_PATH-1] = 0; | ||||
| 		if (safe_strcmp(str_buf, security_string) == 0) { | ||||
| 			*hFound = hWnd; | ||||
| 			return TRUE; | ||||
| 		} | ||||
| 	} | ||||
| 	return TRUE; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * When we format a drive that doesn't have any existing partitions, we can't lock it | ||||
|  * prior to partitioning, which means that Windows will display a "You need to format the | ||||
|  * disk in drive X: before you can use it'. You will also get that popup if you start a | ||||
|  * bad blocks check and cancel it before it completes. We have to close that popup manually. | ||||
|  */ | ||||
| static DWORD WINAPI CloseFormatPromptThread(LPVOID param) { | ||||
| 	HWND hFormatPrompt; | ||||
| 
 | ||||
| 	while(format_op_in_progress) { | ||||
| 		hFormatPrompt = NULL; | ||||
| 		EnumChildWindows(GetDesktopWindow(), FormatPromptCallback, (LPARAM)&hFormatPrompt); | ||||
| 		if (hFormatPrompt != NULL) { | ||||
| 			SendMessage(hFormatPrompt, WM_COMMAND, (WPARAM)IDCANCEL, (LPARAM)0); | ||||
| 			uprintf("Closed Windows format prompt\n"); | ||||
| 		} | ||||
| 		Sleep(100); | ||||
| 	} | ||||
| 	ExitThread(0); | ||||
| } | ||||
| 
 | ||||
| static void update_progress(const uint64_t processed_bytes) | ||||
| { | ||||
| 	if (_GetTickCount64() > LastRefresh + MAX_REFRESH) { | ||||
|  | @ -1687,7 +1643,6 @@ DWORD WINAPI FormatThread(void* param) | |||
| 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_PARTITION_FAILURE; | ||||
| 		goto out; | ||||
| 	} | ||||
| 	CreateThread(NULL, 0, CloseFormatPromptThread, NULL, 0, NULL); | ||||
| 
 | ||||
| 	if (IsChecked(IDC_BADBLOCKS)) { | ||||
| 		do { | ||||
|  |  | |||
|  | @ -226,6 +226,21 @@ static __inline int MessageBoxExU(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UI | |||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static __inline int LoadStringU(HINSTANCE hInstance, UINT uID, LPSTR lpBuffer, int nBufferMax) | ||||
| { | ||||
| 	int ret; | ||||
| 	DWORD err = ERROR_INVALID_DATA; | ||||
| 	walloc(lpBuffer, nBufferMax); | ||||
| 	ret = LoadStringW(hInstance, uID, wlpBuffer, nBufferMax); | ||||
| 	err = GetLastError(); | ||||
| 	if ((ret > 0) && ((ret = wchar_to_utf8_no_alloc(wlpBuffer, lpBuffer, nBufferMax)) == 0)) { | ||||
| 		err = GetLastError(); | ||||
| 	} | ||||
| 	wfree(lpBuffer); | ||||
| 	SetLastError(err); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static __inline int DrawTextU(HDC hDC, LPCSTR lpText, int nCount, LPRECT lpRect, UINT uFormat) | ||||
| { | ||||
| 	int ret; | ||||
|  | @ -917,6 +932,14 @@ static __inline BOOL GetVolumeInformationU(LPCSTR lpRootPathName, LPSTR lpVolume | |||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static __inline HMODULE LoadLibraryU(LPCSTR lpFileName) | ||||
| { | ||||
| 	HMODULE h; | ||||
| 	wconvert(lpFileName); | ||||
| 	h = LoadLibraryW(wlpFileName); | ||||
| 	wfree(lpFileName); | ||||
| 	return h; | ||||
| } | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
|  |  | |||
							
								
								
									
										274
									
								
								src/rufus.c
									
										
									
									
									
								
							
							
						
						
									
										274
									
								
								src/rufus.c
									
										
									
									
									
								
							|  | @ -2076,115 +2076,13 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | |||
| 
 | ||||
| 	switch (message) { | ||||
| 
 | ||||
| 	case UM_MEDIA_CHANGE: | ||||
| 		wParam = DBT_CUSTOMEVENT; | ||||
| 		// Fall through
 | ||||
| 	case WM_DEVICECHANGE: | ||||
| 		// The Windows hotplug subsystem sucks. Among other things, if you insert a GPT partitioned
 | ||||
| 		// USB drive with zero partitions, the only device messages you will get are a stream of
 | ||||
| 		// DBT_DEVNODES_CHANGED and that's it. But those messages are also issued when you get a
 | ||||
| 		// DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE, and there's a whole slew of them so we
 | ||||
| 		// can't really issue a refresh for each one we receive
 | ||||
| 		// What we do then is arm a timer on DBT_DEVNODES_CHANGED, if it's been more than 1 second
 | ||||
| 		// since last refresh/arm timer, and have that timer send DBT_CUSTOMEVENT when it expires.
 | ||||
| 		// 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) { | ||||
| 			switch (wParam) { | ||||
| 			case DBT_DEVICEARRIVAL: | ||||
| 			case DBT_DEVICEREMOVECOMPLETE: | ||||
| 			case DBT_CUSTOMEVENT:	// Sent by our timer refresh function or for card reader media change
 | ||||
| 				LastRefresh = _GetTickCount64(); | ||||
| 				KillTimer(hMainDialog, TID_REFRESH_TIMER); | ||||
| 				if (!format_op_in_progress) { | ||||
| 					queued_hotplug_event = FALSE; | ||||
| 					GetDevices((DWORD)ComboBox_GetItemData(hDeviceList, ComboBox_GetCurSel(hDeviceList))); | ||||
| 					user_changed_label = FALSE; | ||||
| 				} else { | ||||
| 					queued_hotplug_event = TRUE; | ||||
| 				} | ||||
| 				return (INT_PTR)TRUE; | ||||
| 			case DBT_DEVNODES_CHANGED: | ||||
| 				// If it's been more than a second since last device refresh, arm a refresh timer
 | ||||
| 				if (_GetTickCount64() > LastRefresh + 1000) { | ||||
| 					LastRefresh = _GetTickCount64(); | ||||
| 					SetTimer(hMainDialog, TID_REFRESH_TIMER, 1000, RefreshTimer); | ||||
| 				} | ||||
| 				break; | ||||
| 			default: | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		break; | ||||
| 
 | ||||
| 	case WM_INITDIALOG: | ||||
| 		PF_INIT(SHChangeNotifyRegister, shell32); | ||||
| 		// Make sure fScale is set before the first call to apply localization, so that move/resize scale appropriately
 | ||||
| 		hDC = GetDC(hDlg); | ||||
| 		fScale = GetDeviceCaps(hDC, LOGPIXELSX) / 96.0f; | ||||
| 		if (hDC != NULL) | ||||
| 			ReleaseDC(hDlg, hDC); | ||||
| 		apply_localization(IDD_DIALOG, hDlg); | ||||
| 		SetUpdateCheck(); | ||||
| 		togo_mode = TRUE;	// We display the ToGo controls by default and need to hide them
 | ||||
| 		// Create the log window (hidden)
 | ||||
| 		first_log_display = TRUE; | ||||
| 		log_displayed = FALSE; | ||||
| 		hLogDlg = MyCreateDialog(hMainInstance, IDD_LOG, hDlg, (DLGPROC)LogProc); | ||||
| 		InitDialog(hDlg); | ||||
| 		GetDevices(0); | ||||
| 		CheckForUpdates(FALSE); | ||||
| 		// Register MEDIA_INSERTED/MEDIA_REMOVED notifications for card readers
 | ||||
| 		if ((pfSHChangeNotifyRegister != NULL) && (SUCCEEDED(SHGetSpecialFolderLocation(0, CSIDL_DESKTOP, &pidlDesktop)))) { | ||||
| 			NotifyEntry.pidl = pidlDesktop; | ||||
| 			NotifyEntry.fRecursive = TRUE; | ||||
| 			// NB: The following only works if the media is already formatted.
 | ||||
| 			// If you insert a blank card, notifications will not be sent... :(
 | ||||
| 			ulRegister = pfSHChangeNotifyRegister(hDlg, 0x0001|0x0002|0x8000, | ||||
| 				SHCNE_MEDIAINSERTED|SHCNE_MEDIAREMOVED, UM_MEDIA_CHANGE, 1, &NotifyEntry); | ||||
| 		} | ||||
| 		// Bring our Window on top. We have to go through all *THREE* of these, or Far Manager hides our window :(
 | ||||
| 		SetWindowPos(hMainDialog, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE); | ||||
| 		SetWindowPos(hMainDialog, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE); | ||||
| 		SetWindowPos(hMainDialog, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE); | ||||
| 
 | ||||
| 		// Set 'Start' as the selected button if it's enabled, otherwise use 'Select ISO', instead
 | ||||
| 		SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)(IsWindowEnabled(hStart) ? hStart : hSelectISO), TRUE); | ||||
| 
 | ||||
| #if defined(ALPHA) | ||||
| 		// Add a VERY ANNOYING popup for Alpha releases, so that people don't start redistributing them
 | ||||
| 		MessageBoxA(NULL, "This is an Alpha version of " APPLICATION_NAME " - It is meant to be used for " | ||||
| 			"testing ONLY and should NOT be distributed as a release.", "ALPHA VERSION", MSG_INFO); | ||||
| #elif defined(TEST) | ||||
| 		// Same thing for Test releases
 | ||||
| 		MessageBoxA(NULL, "This is a Test version of " APPLICATION_NAME " - It is meant to be used for " | ||||
| 			"testing ONLY and should NOT be distributed as a release.", "TEST VERSION", MSG_INFO); | ||||
| #endif | ||||
| 		return (INT_PTR)FALSE; | ||||
| 
 | ||||
| 	// The things one must do to get an ellipsis and text alignment on the status bar...
 | ||||
| 	case WM_DRAWITEM: | ||||
| 		if (wParam == IDC_STATUS) { | ||||
| 			pDI = (DRAWITEMSTRUCT*)lParam; | ||||
| 			pDI->rcItem.top -= (int)((4.0f * fScale) - 6.0f); | ||||
| 			pDI->rcItem.left += (int)(((pDI->itemID == SB_SECTION_MIDDLE)?-2.0f:4.0f) * fScale); | ||||
| 			SetBkMode(pDI->hDC, TRANSPARENT); | ||||
| 			switch(pDI->itemID) { | ||||
| 			case SB_SECTION_LEFT: | ||||
| 				SetTextColor(pDI->hDC, GetSysColor(COLOR_BTNTEXT)); | ||||
| 				DrawTextExU(pDI->hDC, szStatusMessage, -1, &pDI->rcItem, | ||||
| 					DT_LEFT|DT_END_ELLIPSIS|DT_PATH_ELLIPSIS, NULL); | ||||
| 				return (INT_PTR)TRUE; | ||||
| 			case SB_SECTION_RIGHT: | ||||
| 				SetTextColor(pDI->hDC, GetSysColor(COLOR_3DSHADOW)); | ||||
| 				DrawTextExA(pDI->hDC, szTimer, -1, &pDI->rcItem, DT_LEFT, NULL); | ||||
| 				return (INT_PTR)TRUE; | ||||
| 			} | ||||
| 		} | ||||
| 		break; | ||||
| 
 | ||||
| 	case WM_COMMAND: | ||||
| #ifdef RUFUS_TEST | ||||
| 		if (LOWORD(wParam) == IDC_TEST) { | ||||
| 			break; | ||||
| 		} | ||||
| #endif | ||||
| 
 | ||||
| 		if ((LOWORD(wParam) >= UM_LANGUAGE_MENU) && (LOWORD(wParam) < UM_LANGUAGE_MENU_MAX)) { | ||||
| 			selected_language = LOWORD(wParam) - UM_LANGUAGE_MENU; | ||||
| 			i = 0; | ||||
|  | @ -2277,12 +2175,6 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | |||
| 			// Must come last for the log window to get focus
 | ||||
| 			ShowWindow(hLogDlg, log_displayed?SW_SHOW:SW_HIDE); | ||||
| 			break; | ||||
| #ifdef RUFUS_TEST | ||||
| 		case IDC_TEST: | ||||
| 		{ | ||||
| 			break; | ||||
| 		} | ||||
| #endif | ||||
| 		case IDC_ADVANCED: | ||||
| 			advanced_mode = !advanced_mode; | ||||
| 			WriteSettingBool(SETTING_ADVANCED_MODE, advanced_mode); | ||||
|  | @ -2578,6 +2470,115 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | |||
| 		} | ||||
| 		return (INT_PTR)TRUE; | ||||
| 
 | ||||
| 	case UM_MEDIA_CHANGE: | ||||
| 		wParam = DBT_CUSTOMEVENT; | ||||
| 		// Fall through
 | ||||
| 	case WM_DEVICECHANGE: | ||||
| 		// The Windows hotplug subsystem sucks. Among other things, if you insert a GPT partitioned
 | ||||
| 		// USB drive with zero partitions, the only device messages you will get are a stream of
 | ||||
| 		// DBT_DEVNODES_CHANGED and that's it. But those messages are also issued when you get a
 | ||||
| 		// DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE, and there's a whole slew of them so we
 | ||||
| 		// can't really issue a refresh for each one we receive
 | ||||
| 		// What we do then is arm a timer on DBT_DEVNODES_CHANGED, if it's been more than 1 second
 | ||||
| 		// since last refresh/arm timer, and have that timer send DBT_CUSTOMEVENT when it expires.
 | ||||
| 		// 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) { | ||||
| 			switch (wParam) { | ||||
| 			case DBT_DEVICEARRIVAL: | ||||
| 			case DBT_DEVICEREMOVECOMPLETE: | ||||
| 			case DBT_CUSTOMEVENT:	// Sent by our timer refresh function or for card reader media change
 | ||||
| 				LastRefresh = _GetTickCount64(); | ||||
| 				KillTimer(hMainDialog, TID_REFRESH_TIMER); | ||||
| 				if (!format_op_in_progress) { | ||||
| 					queued_hotplug_event = FALSE; | ||||
| 					GetDevices((DWORD)ComboBox_GetItemData(hDeviceList, ComboBox_GetCurSel(hDeviceList))); | ||||
| 					user_changed_label = FALSE; | ||||
| 				} | ||||
| 				else { | ||||
| 					queued_hotplug_event = TRUE; | ||||
| 				} | ||||
| 				return (INT_PTR)TRUE; | ||||
| 			case DBT_DEVNODES_CHANGED: | ||||
| 				// If it's been more than a second since last device refresh, arm a refresh timer
 | ||||
| 				if (_GetTickCount64() > LastRefresh + 1000) { | ||||
| 					LastRefresh = _GetTickCount64(); | ||||
| 					SetTimer(hMainDialog, TID_REFRESH_TIMER, 1000, RefreshTimer); | ||||
| 				} | ||||
| 				break; | ||||
| 			default: | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		break; | ||||
| 
 | ||||
| 	case WM_INITDIALOG: | ||||
| 		PF_INIT(SHChangeNotifyRegister, shell32); | ||||
| 		// Make sure fScale is set before the first call to apply localization, so that move/resize scale appropriately
 | ||||
| 		hDC = GetDC(hDlg); | ||||
| 		fScale = GetDeviceCaps(hDC, LOGPIXELSX) / 96.0f; | ||||
| 		if (hDC != NULL) | ||||
| 			ReleaseDC(hDlg, hDC); | ||||
| 		apply_localization(IDD_DIALOG, hDlg); | ||||
| 		SetUpdateCheck(); | ||||
| 		togo_mode = TRUE;	// We display the ToGo controls by default and need to hide them
 | ||||
| 							// Create the log window (hidden)
 | ||||
| 		first_log_display = TRUE; | ||||
| 		log_displayed = FALSE; | ||||
| 		hLogDlg = MyCreateDialog(hMainInstance, IDD_LOG, hDlg, (DLGPROC)LogProc); | ||||
| 		InitDialog(hDlg); | ||||
| 		GetDevices(0); | ||||
| 		CheckForUpdates(FALSE); | ||||
| 		// Register MEDIA_INSERTED/MEDIA_REMOVED notifications for card readers
 | ||||
| 		if ((pfSHChangeNotifyRegister != NULL) && (SUCCEEDED(SHGetSpecialFolderLocation(0, CSIDL_DESKTOP, &pidlDesktop)))) { | ||||
| 			NotifyEntry.pidl = pidlDesktop; | ||||
| 			NotifyEntry.fRecursive = TRUE; | ||||
| 			// NB: The following only works if the media is already formatted.
 | ||||
| 			// If you insert a blank card, notifications will not be sent... :(
 | ||||
| 			ulRegister = pfSHChangeNotifyRegister(hDlg, 0x0001 | 0x0002 | 0x8000, | ||||
| 				SHCNE_MEDIAINSERTED | SHCNE_MEDIAREMOVED, UM_MEDIA_CHANGE, 1, &NotifyEntry); | ||||
| 		} | ||||
| 		// Bring our Window on top. We have to go through all *THREE* of these, or Far Manager hides our window :(
 | ||||
| 		SetWindowPos(hMainDialog, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); | ||||
| 		SetWindowPos(hMainDialog, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); | ||||
| 		SetWindowPos(hMainDialog, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); | ||||
| 
 | ||||
| 		// Set 'Start' as the selected button if it's enabled, otherwise use 'Select ISO', instead
 | ||||
| 		SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)(IsWindowEnabled(hStart) ? hStart : hSelectISO), TRUE); | ||||
| 
 | ||||
| #if defined(ALPHA) | ||||
| 		// Add a VERY ANNOYING popup for Alpha releases, so that people don't start redistributing them
 | ||||
| 		MessageBoxA(NULL, "This is an Alpha version of " APPLICATION_NAME " - It is meant to be used for " | ||||
| 			"testing ONLY and should NOT be distributed as a release.", "ALPHA VERSION", MSG_INFO); | ||||
| #elif defined(TEST) | ||||
| 		// Same thing for Test releases
 | ||||
| 		MessageBoxA(NULL, "This is a Test version of " APPLICATION_NAME " - It is meant to be used for " | ||||
| 			"testing ONLY and should NOT be distributed as a release.", "TEST VERSION", MSG_INFO); | ||||
| #endif | ||||
| 		return (INT_PTR)FALSE; | ||||
| 
 | ||||
| 		// The things one must do to get an ellipsis and text alignment on the status bar...
 | ||||
| 	case WM_DRAWITEM: | ||||
| 		if (wParam == IDC_STATUS) { | ||||
| 			pDI = (DRAWITEMSTRUCT*)lParam; | ||||
| 			pDI->rcItem.top -= (int)((4.0f * fScale) - 6.0f); | ||||
| 			pDI->rcItem.left += (int)(((pDI->itemID == SB_SECTION_MIDDLE) ? -2.0f : 4.0f) * fScale); | ||||
| 			SetBkMode(pDI->hDC, TRANSPARENT); | ||||
| 			switch (pDI->itemID) { | ||||
| 			case SB_SECTION_LEFT: | ||||
| 				SetTextColor(pDI->hDC, GetSysColor(COLOR_BTNTEXT)); | ||||
| 				DrawTextExU(pDI->hDC, szStatusMessage, -1, &pDI->rcItem, | ||||
| 					DT_LEFT | DT_END_ELLIPSIS | DT_PATH_ELLIPSIS, NULL); | ||||
| 				return (INT_PTR)TRUE; | ||||
| 			case SB_SECTION_RIGHT: | ||||
| 				SetTextColor(pDI->hDC, GetSysColor(COLOR_3DSHADOW)); | ||||
| 				DrawTextExA(pDI->hDC, szTimer, -1, &pDI->rcItem, DT_LEFT, NULL); | ||||
| 				return (INT_PTR)TRUE; | ||||
| 			} | ||||
| 		} | ||||
| 		break; | ||||
| 
 | ||||
| 	case WM_NOTIFY: | ||||
| 		switch (((LPNMHDR)lParam)->code) { | ||||
| 		case TBN_DROPDOWN: | ||||
|  | @ -2784,46 +2785,6 @@ static HANDLE SetHogger(BOOL attached_console, BOOL disable_hogger) | |||
| 	return hogmutex; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Returns true if: | ||||
|  * 1. The OS supports UAC, UAC is on, and the current process runs elevated, or | ||||
|  * 2. The OS doesn't support UAC or UAC is off, and the process is being run by a member of the admin group | ||||
|  */ | ||||
| static BOOL IsCurrentProcessElevated(void) | ||||
| { | ||||
| 	BOOL r = FALSE; | ||||
| 	DWORD size; | ||||
| 	HANDLE token = INVALID_HANDLE_VALUE; | ||||
| 	TOKEN_ELEVATION te; | ||||
| 	SID_IDENTIFIER_AUTHORITY auth = { SECURITY_NT_AUTHORITY }; | ||||
| 	PSID psid; | ||||
| 
 | ||||
| 	if (ReadRegistryKey32(REGKEY_HKLM, "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\EnableLUA") == 1) { | ||||
| 		uprintf("NOTE: UAC is on"); | ||||
| 		if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) { | ||||
| 			uprintf("Could not get current process token: %s", WindowsErrorString()); | ||||
| 			goto out; | ||||
| 		} | ||||
| 		if (!GetTokenInformation(token, TokenElevation, &te, sizeof(te), &size)) { | ||||
| 			uprintf("Could not get token information: %s", WindowsErrorString()); | ||||
| 			goto out; | ||||
| 		} | ||||
| 		r = (te.TokenIsElevated != 0); | ||||
| 	} else { | ||||
| 		uprintf("NOTE: UAC is either disabled or not available"); | ||||
| 		if (!AllocateAndInitializeSid(&auth, 2, SECURITY_BUILTIN_DOMAIN_RID, | ||||
| 			DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psid)) | ||||
| 			goto out; | ||||
| 		if (!CheckTokenMembership(NULL, psid, &r)) | ||||
| 			r = FALSE; | ||||
| 		FreeSid(psid); | ||||
| 	} | ||||
| 
 | ||||
| out: | ||||
| 	safe_closehandle(token); | ||||
| 	return r; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Application Entrypoint | ||||
|  | @ -3135,6 +3096,10 @@ relaunch: | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Set the hook to automatically close Windows' "You need to format the disk in drive..." prompt
 | ||||
| 	if (!SetFormatPromptHook()) | ||||
| 		uprintf("Warning:Could not set 'Format Disk' prompt auto-close"); | ||||
| 
 | ||||
| 	ShowWindow(hDlg, SW_SHOWNORMAL); | ||||
| 	UpdateWindow(hDlg); | ||||
| 
 | ||||
|  | @ -3348,6 +3313,7 @@ out: | |||
| 	if ((!external_loc_file) && (loc_file[0] != 0)) | ||||
| 		DeleteFileU(loc_file); | ||||
| 	DestroyAllTooltips(); | ||||
| 	ClrFormatPromptHook(); | ||||
| 	exit_localization(); | ||||
| 	safe_free(image_path); | ||||
| 	safe_free(locale_name); | ||||
|  |  | |||
|  | @ -465,6 +465,10 @@ extern BOOL IsBufferInDB(const unsigned char* buf, const size_t len); | |||
| #define printbits(x) _printbits(sizeof(x), &x, 0) | ||||
| #define printbitslz(x) _printbits(sizeof(x), &x, 1) | ||||
| extern char* _printbits(size_t const size, void const * const ptr, int leading_zeroes); | ||||
| extern BOOL IsCurrentProcessElevated(void); | ||||
| extern char* GetCurrentMUI(void); | ||||
| extern BOOL SetFormatPromptHook(void); | ||||
| extern void ClrFormatPromptHook(void); | ||||
| 
 | ||||
| DWORD WINAPI FormatThread(void* param); | ||||
| DWORD WINAPI SaveImageThread(void* param); | ||||
|  |  | |||
							
								
								
									
										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.10.968" | ||||
| CAPTION "Rufus 2.10.969" | ||||
| FONT 8, "Segoe UI Symbol", 400, 0, 0x0 | ||||
| BEGIN | ||||
|     LTEXT           "Device",IDS_DEVICE_TXT,9,6,200,8 | ||||
|  | @ -320,8 +320,8 @@ END | |||
| // | ||||
| 
 | ||||
| VS_VERSION_INFO VERSIONINFO | ||||
|  FILEVERSION 2,10,968,0 | ||||
|  PRODUCTVERSION 2,10,968,0 | ||||
|  FILEVERSION 2,10,969,0 | ||||
|  PRODUCTVERSION 2,10,969,0 | ||||
|  FILEFLAGSMASK 0x3fL | ||||
| #ifdef _DEBUG | ||||
|  FILEFLAGS 0x1L | ||||
|  | @ -338,13 +338,13 @@ BEGIN | |||
|         BEGIN | ||||
|             VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" | ||||
|             VALUE "FileDescription", "Rufus" | ||||
|             VALUE "FileVersion", "2.10.968" | ||||
|             VALUE "FileVersion", "2.10.969" | ||||
|             VALUE "InternalName", "Rufus" | ||||
|             VALUE "LegalCopyright", "© 2011-2016 Pete Batard (GPL v3)" | ||||
|             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" | ||||
|             VALUE "OriginalFilename", "rufus.exe" | ||||
|             VALUE "ProductName", "Rufus" | ||||
|             VALUE "ProductVersion", "2.10.968" | ||||
|             VALUE "ProductVersion", "2.10.969" | ||||
|         END | ||||
|     END | ||||
|     BLOCK "VarFileInfo" | ||||
|  |  | |||
							
								
								
									
										60
									
								
								src/stdfn.c
									
										
									
									
									
								
							
							
						
						
									
										60
									
								
								src/stdfn.c
									
										
									
									
									
								
							|  | @ -36,6 +36,8 @@ extern BOOL usb_debug;	// For uuprintf | |||
| int  nWindowsVersion = WINDOWS_UNDEFINED; | ||||
| char WindowsVersionStr[128] = "Windows "; | ||||
| 
 | ||||
| PF_TYPE_DECL(WINAPI, int, LCIDToLocaleName, (LCID, LPWSTR, int, DWORD)); | ||||
| 
 | ||||
| /*
 | ||||
|  * Hash table functions - modified From glibc 2.3.2: | ||||
|  * [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986 | ||||
|  | @ -847,3 +849,61 @@ BOOL SetThreadAffinity(DWORD_PTR* thread_affinity, size_t num_threads) | |||
| 	uuprintf("  thr_%d:\t%s", i, printbitslz(thread_affinity[i])); | ||||
| 	return TRUE; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Returns true if: | ||||
|  * 1. The OS supports UAC, UAC is on, and the current process runs elevated, or | ||||
|  * 2. The OS doesn't support UAC or UAC is off, and the process is being run by a member of the admin group | ||||
|  */ | ||||
| BOOL IsCurrentProcessElevated(void) | ||||
| { | ||||
| 	BOOL r = FALSE; | ||||
| 	DWORD size; | ||||
| 	HANDLE token = INVALID_HANDLE_VALUE; | ||||
| 	TOKEN_ELEVATION te; | ||||
| 	SID_IDENTIFIER_AUTHORITY auth = { SECURITY_NT_AUTHORITY }; | ||||
| 	PSID psid; | ||||
| 
 | ||||
| 	if (ReadRegistryKey32(REGKEY_HKLM, "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\EnableLUA") == 1) { | ||||
| 		uprintf("Note: UAC is active"); | ||||
| 		if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) { | ||||
| 			uprintf("Could not get current process token: %s", WindowsErrorString()); | ||||
| 			goto out; | ||||
| 		} | ||||
| 		if (!GetTokenInformation(token, TokenElevation, &te, sizeof(te), &size)) { | ||||
| 			uprintf("Could not get token information: %s", WindowsErrorString()); | ||||
| 			goto out; | ||||
| 		} | ||||
| 		r = (te.TokenIsElevated != 0); | ||||
| 	} | ||||
| 	else { | ||||
| 		uprintf("Note: UAC is either disabled or not available"); | ||||
| 		if (!AllocateAndInitializeSid(&auth, 2, SECURITY_BUILTIN_DOMAIN_RID, | ||||
| 			DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psid)) | ||||
| 			goto out; | ||||
| 		if (!CheckTokenMembership(NULL, psid, &r)) | ||||
| 			r = FALSE; | ||||
| 		FreeSid(psid); | ||||
| 	} | ||||
| 
 | ||||
| out: | ||||
| 	safe_closehandle(token); | ||||
| 	return r; | ||||
| } | ||||
| 
 | ||||
| char* GetCurrentMUI(void) | ||||
| { | ||||
| 	static char mui_str[LOCALE_NAME_MAX_LENGTH]; | ||||
| 	wchar_t wmui_str[LOCALE_NAME_MAX_LENGTH]; | ||||
| 
 | ||||
| 	// Of course LCIDToLocaleName() is not available on XP... grrrr!
 | ||||
| 	PF_INIT(LCIDToLocaleName, kernel32); | ||||
| 
 | ||||
| 	if ( (pfLCIDToLocaleName != NULL) && | ||||
| 		 (pfLCIDToLocaleName(GetUserDefaultUILanguage(), wmui_str, LOCALE_NAME_MAX_LENGTH, 0) > 0) ) { | ||||
| 		wchar_to_utf8_no_alloc(wmui_str, mui_str, LOCALE_NAME_MAX_LENGTH); | ||||
| 	} else { | ||||
| 		safe_strcpy(mui_str, LOCALE_NAME_MAX_LENGTH, "en-US"); | ||||
| 	} | ||||
| 	return mui_str; | ||||
| } | ||||
|  |  | |||
							
								
								
									
										84
									
								
								src/stdlg.c
									
										
									
									
									
								
							
							
						
						
									
										84
									
								
								src/stdlg.c
									
										
									
									
									
								
							|  | @ -63,6 +63,8 @@ static BOOL notification_is_question; | |||
| static const notification_info* notification_more_info; | ||||
| static BOOL settings_commcheck = FALSE; | ||||
| static WNDPROC update_original_proc = NULL; | ||||
| static HWINEVENTHOOK fp_weh = NULL; | ||||
| static char *fp_title_str = "Microsoft Windows", *fp_button_str = "Format disk"; | ||||
| 
 | ||||
| extern loc_cmd* selected_locale; | ||||
| 
 | ||||
|  | @ -1725,3 +1727,85 @@ INT_PTR MyDialogBox(HINSTANCE hInstance, int Dialog_ID, HWND hWndParent, DLGPROC | |||
| 	safe_free(rcTemplate); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * The following function calls are used to automatically detect and close the native | ||||
|  * Windows format prompt "You must format the disk in drive X:". To do that, we use an | ||||
|  * event hook that gets triggered whenever a window is placed in the foreground. | ||||
|  * In that hook, we look for a dialog that has style WS_POPUPWINDOW and has the relevant | ||||
|  * title. However, because the title in itself is too generic (the expectation is that | ||||
|  * it will be "Microsoft Windows") we also enumerate all the child controls from that | ||||
|  * prompt, using another callback, until we find one that contains the text we expect | ||||
|  * for the "Format disk" button. | ||||
|  * Oh, and since all of these strings are localized, we must first pick them up from | ||||
|  * the relevant mui (something like "C:\Windows\System32\en-GB\shell32.dll.mui") | ||||
|  */ | ||||
| static BOOL CALLBACK FormatPromptCallback(HWND hWnd, LPARAM lParam) | ||||
| { | ||||
| 	char str[128]; | ||||
| 	BOOL *found = (BOOL*)lParam; | ||||
| 
 | ||||
| 	if (GetWindowTextU(hWnd, str, sizeof(str)) == 0) | ||||
| 		return TRUE; | ||||
| 	if (safe_strcmp(str, fp_button_str) == 0) | ||||
| 		*found = TRUE; | ||||
| 	return TRUE; | ||||
| } | ||||
| 
 | ||||
| static void CALLBACK FormatPromptHook(HWINEVENTHOOK hWinEventHook, DWORD Event, HWND hWnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime) | ||||
| { | ||||
| 	char str[128]; | ||||
| 	BOOL found; | ||||
| 
 | ||||
| 	if (Event == EVENT_SYSTEM_FOREGROUND) { | ||||
| 		if (GetWindowLong(hWnd, GWL_STYLE) & WS_POPUPWINDOW) { | ||||
| 			str[0] = 0; | ||||
| 			GetWindowTextU(hWnd, str, sizeof(str)); | ||||
| 			if (safe_strcmp(str, fp_title_str) == 0) { | ||||
| 				found = FALSE; | ||||
| 				EnumChildWindows(hWnd, FormatPromptCallback, (LPARAM)&found); | ||||
| 				if (found) { | ||||
| 					SendMessage(hWnd, WM_COMMAND, (WPARAM)IDCANCEL, (LPARAM)0); | ||||
| 					uprintf("Closed Windows format prompt"); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| BOOL SetFormatPromptHook(void) | ||||
| { | ||||
| 	HMODULE mui_lib; | ||||
| 	char mui_path[MAX_PATH]; | ||||
| 	static char title_str[128], button_str[128]; | ||||
| 
 | ||||
| 	if (fp_weh != NULL) | ||||
| 		return TRUE;	// No need to set again if active
 | ||||
| 
 | ||||
| 						// Fetch the localized strings in the relevant
 | ||||
| 	static_sprintf(mui_path, "%s\\%s\\shell32.dll.mui", system_dir, GetCurrentMUI()); | ||||
| 	mui_lib = LoadLibraryU(mui_path); | ||||
| 	if (mui_lib != NULL) { | ||||
| 		// 4097 = "You need to format the disk in drive %c: before you can use it." (dialog text)
 | ||||
| 		// 4125 = "Microsoft Windows" (dialog title)
 | ||||
| 		// 4126 = "Format disk" (button)
 | ||||
| 		if (LoadStringU(mui_lib, 4125, title_str, sizeof(title_str)) > 0) | ||||
| 			fp_title_str = title_str; | ||||
| 		else | ||||
| 			uprintf("Warning: Could not locate localized format prompt title string in '%s': %s", mui_path, WindowsErrorString()); | ||||
| 		if (LoadStringU(mui_lib, 4126, button_str, sizeof(button_str)) > 0) | ||||
| 			fp_button_str = button_str; | ||||
| 		else | ||||
| 			uprintf("Warning: Could not locate localized format prompt button string in '%s': %s", mui_path, WindowsErrorString()); | ||||
| 		FreeLibrary(mui_lib); | ||||
| 	} | ||||
| 
 | ||||
| 	fp_weh = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, NULL, | ||||
| 		FormatPromptHook, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS); | ||||
| 	return (fp_weh != NULL); | ||||
| } | ||||
| 
 | ||||
| void ClrFormatPromptHook(void) { | ||||
| 	UnhookWinEvent(fp_weh); | ||||
| 	fp_weh = NULL; | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue