mirror of
https://github.com/pbatard/rufus.git
synced 2025-05-19 01:15:12 -04: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