[core] add a cheat mode to reset the current USB device (cycle port)

* Will not work on Vista, Windows 7 or Server 2008
* Also update Windows version info
This commit is contained in:
Pete Batard 2017-09-15 12:40:33 +01:00
parent 13ba3e75b3
commit 8286a0f63a
6 changed files with 103 additions and 30 deletions

View File

@ -1,7 +1,7 @@
/*
* Rufus: The Reliable USB Formatting Utility
* Device detection and enumeration
* Copyright © 2014-2017 Pete Batard <pete@akeo.ie>
* Copyright © 2014-2017 Pete Batard <pete@akeo.ie>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -42,7 +42,8 @@
#include "drive.h"
#include "dev.h"
extern StrArray DriveID, DriveLabel;
extern StrArray DriveID, DriveLabel, DriveHub;
extern uint32_t DrivePort[MAX_DRIVES];
extern BOOL enable_HDDs, use_fake_units, enable_vmdk, usb_debug, list_non_usb_removable_drives;
/*
@ -123,6 +124,51 @@ out:
return r;
}
/*
* Cycle port (reset) the selected device
*/
BOOL ResetDevice(int index)
{
static uint64_t LastReset = 0;
BOOL r = FALSE;
HANDLE handle = INVALID_HANDLE_VALUE;
DWORD size;
USB_CYCLE_PORT_PARAMS cycle_port;
// Wait at least 10 secs between resets
if (_GetTickCount64() < LastReset + 10000ULL) {
uprintf("You must wait at least 10 seconds before trying to reset a device");
return FALSE;
}
if (DriveHub.String[index] == NULL)
return FALSE;
LastReset = _GetTickCount64();
handle = CreateFileA(DriveHub.String[index], GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (handle == INVALID_HANDLE_VALUE) {
uprintf("Could not open %s: %s", DriveHub.String[index], WindowsErrorString());
goto out;
}
memset(&cycle_port, 0, sizeof(cycle_port));
size = sizeof(cycle_port);
cycle_port.ConnectionIndex = DrivePort[index];
uprintf("Cycling port %d (reset) on %s", DrivePort[index], DriveHub.String[index]);
// As per https://msdn.microsoft.com/en-us/library/windows/hardware/ff537340.aspx
// IOCTL_USB_HUB_CYCLE_PORT is not supported on Windows 7, Windows Vista, and Windows Server 2008
if (!DeviceIoControl(handle, IOCTL_USB_HUB_CYCLE_PORT, &cycle_port, size, &cycle_port, size, &size, NULL)) {
uprintf(" Failed to cycle port: %s", WindowsErrorString());
goto out;
}
r = TRUE;
out:
safe_closehandle(handle);
return r;
}
static __inline BOOL IsVHD(const char* buffer)
{
int i;
@ -319,12 +365,13 @@ BOOL GetDevices(DWORD devnum)
LONG maxwidth = 0;
int s, score, drive_number, remove_drive;
char drive_letters[27], *device_id, *devid_list = NULL, entry_msg[128];
char *p, *label, *entry, buffer[MAX_PATH], str[MAX_PATH], *method_str;
char *p, *label, *entry, buffer[MAX_PATH], str[MAX_PATH], *method_str, *hub_path;
usb_device_props props;
IGNORE_RETVAL(ComboBox_ResetContent(hDeviceList));
StrArrayClear(&DriveID);
StrArrayClear(&DriveLabel);
StrArrayClear(&DriveHub);
StrArrayCreate(&dev_if_path, 128);
// Add a dummy for string index zero, as this is what non matching hashes will point to
StrArrayAdd(&dev_if_path, "", TRUE);
@ -452,6 +499,7 @@ BOOL GetDevices(DWORD devnum)
memset(buffer, 0, sizeof(buffer));
memset(&props, 0, sizeof(props));
method_str = "";
hub_path = NULL;
if (!SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_ENUMERATOR_NAME,
&datatype, (LPBYTE)buffer, sizeof(buffer), &size)) {
uprintf("SetupDiGetDeviceRegistryProperty (Enumerator Name) failed: %s\n", WindowsErrorString());
@ -584,8 +632,10 @@ BOOL GetDevices(DWORD devnum)
if ((uintptr_t)htab_devid.table[j].data > 0) {
uuprintf(" Matched with Hub[%d]: '%s'", (uintptr_t)htab_devid.table[j].data,
dev_if_path.String[(uintptr_t)htab_devid.table[j].data]);
if (GetUSBProperties(dev_if_path.String[(uintptr_t)htab_devid.table[j].data], device_id, &props))
if (GetUSBProperties(dev_if_path.String[(uintptr_t)htab_devid.table[j].data], device_id, &props)) {
method_str = "";
hub_path = dev_if_path.String[(uintptr_t)htab_devid.table[j].data];
}
#ifdef FORCED_DEVICE
props.vid = FORCED_VID;
props.pid = FORCED_PID;
@ -769,6 +819,8 @@ BOOL GetDevices(DWORD devnum)
// Must ensure that the combo box is UNSORTED for indexes to be the same
StrArrayAdd(&DriveID, buffer, TRUE);
StrArrayAdd(&DriveLabel, label, TRUE);
if ((hub_path != NULL) && (StrArrayAdd(&DriveHub, hub_path, TRUE) >= 0))
DrivePort[DriveHub.Index - 1] = props.port;
IGNORE_RETVAL(ComboBox_SetItemData(hDeviceList, ComboBox_AddStringU(hDeviceList, entry), drive_index));
maxwidth = max(maxwidth, GetEntryWidth(hDeviceList, entry));

View File

@ -1,7 +1,7 @@
/*
* Rufus: The Reliable USB Formatting Utility
* Device listing
* Copyright © 2014-2016 Pete Batard <pete@akeo.ie>
* Copyright © 2014-2016 Pete Batard <pete@akeo.ie>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -106,9 +106,12 @@ DECLSPEC_IMPORT CONFIGRET WINAPI CM_Get_Sibling(PDEVINST pdnDevInst, DEVINST dnD
// This last one is unknown from MinGW32 and needs to be fetched from the DLL
PF_TYPE_DECL(WINAPI, CONFIGRET, CM_Get_DevNode_Registry_PropertyA, (DEVINST, ULONG, PULONG, PVOID, PULONG, ULONG));
#define USB_HUB_CYCLE_PORT 273
#define USB_GET_NODE_CONNECTION_INFORMATION_EX 274
#define USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 279
#define IOCTL_USB_HUB_CYCLE_PORT \
CTL_CODE(FILE_DEVICE_USB, USB_HUB_CYCLE_PORT, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX \
CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_INFORMATION_EX, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 \
@ -172,6 +175,11 @@ typedef struct _USB_NODE_CONNECTION_INFORMATION_EX_V2 {
USB_NODE_CONNECTION_INFORMATION_EX_V2_FLAGS Flags;
} USB_NODE_CONNECTION_INFORMATION_EX_V2, *PUSB_NODE_CONNECTION_INFORMATION_EX_V2;
typedef struct {
ULONG ConnectionIndex;
ULONG StatusReturned;
} USB_CYCLE_PORT_PARAMS;
#pragma pack(pop)
const GUID _GUID_DEVINTERFACE_DISK =

View File

@ -114,7 +114,8 @@ uint16_t rufus_version[3], embedded_sl_version[2];
char embedded_sl_version_str[2][12] = { "?.??", "?.??" };
char embedded_sl_version_ext[2][32];
RUFUS_UPDATE update = { {0,0,0}, {0,0}, NULL, NULL};
StrArray DriveID, DriveLabel, BlockingProcess;
StrArray DriveID, DriveLabel, DriveHub, BlockingProcess;
uint32_t DrivePort[MAX_DRIVES];
extern char* szStatusMessage;
static HANDLE format_thid = NULL, dialog_handle = NULL;
@ -1828,9 +1829,10 @@ static void InitDialog(HWND hDlg)
}
IGNORE_RETVAL(ComboBox_SetCurSel(hDiskID, 0));
// Create the string array
// Create the string arrays
StrArrayCreate(&DriveID, MAX_DRIVES);
StrArrayCreate(&DriveLabel, MAX_DRIVES);
StrArrayCreate(&DriveHub, MAX_DRIVES);
StrArrayCreate(&BlockingProcess, 16);
// Set various checkboxes
CheckDlgButton(hDlg, IDC_QUICKFORMAT, BST_CHECKED);
@ -2351,6 +2353,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
PostQuitMessage(0);
StrArrayDestroy(&DriveID);
StrArrayDestroy(&DriveLabel);
StrArrayDestroy(&DriveHub);
StrArrayDestroy(&BlockingProcess);
DestroyAllTooltips();
DestroyWindow(hLogDlg);
@ -3351,7 +3354,7 @@ relaunch:
// Do our own event processing and process "magic" commands
while(GetMessage(&msg, NULL, 0, 0)) {
// ** ***** **** ** ******** *
// ** ***** **** ** **********
// .,ABCDEFGHIJKLMNOPQRSTUVWXYZ
// Ctrl-A => Select the log data
@ -3359,6 +3362,7 @@ relaunch:
(msg.message == WM_KEYDOWN) && (msg.wParam == 'A') ) {
// Might also need ES_NOHIDESEL property if you want to select when not active
Edit_SetSel(hLog, 0, -1);
continue;
}
// Alt-. => Enable USB enumeration debug
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == VK_OEM_PERIOD)) {
@ -3385,12 +3389,12 @@ relaunch:
PrintStatusTimeout(lmprintf(MSG_256), detect_fakes);
continue;
}
// Alt C => Force the update check to be successful
// This will set the reported current version of Rufus to 0.0.0.0 when performing an update
// check, so that it always succeeds. This is useful for translators.
// Alt-C => Cycle USB port for currently selected device
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'C')) {
force_update = !force_update;
PrintStatusTimeout(lmprintf(MSG_259), force_update);
int index = ComboBox_GetCurSel(hDeviceList);
if (index < 0)
break;
ResetDevice(index);
continue;
}
// Alt-D => Delete the NoDriveTypeAutorun key on exit (useful if the app crashed)
@ -3473,7 +3477,6 @@ relaunch:
PrintStatusTimeout(lmprintf(MSG_290), !disable_file_indexing);
continue;
}
// Alt-R => Remove all the registry keys that may have been created by Rufus
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'R')) {
PrintStatus(2000, DeleteRegistryKey(REGKEY_HKCU, COMPANY_NAME "\\" APPLICATION_NAME)?MSG_248:MSG_249);
@ -3525,11 +3528,20 @@ relaunch:
SHDeleteDirectoryExU(NULL, tmp_path, FOF_SILENT | FOF_NOERRORUI | FOF_NOCONFIRMATION);
continue;
}
// Alt Y => Force the update check to be successful
// This will set the reported current version of Rufus to 0.0.0.0 when performing an update
// check, so that it always succeeds. This is useful for translators.
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'Y')) {
force_update = !force_update;
PrintStatusTimeout(lmprintf(MSG_259), force_update);
continue;
}
// Alt-Z => Zero the drive
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'Z')) {
zero_drive = TRUE;
// Simulate a button click for Start
PostMessage(hDlg, WM_COMMAND, (WPARAM)IDC_START, 0);
continue;
}
// Hazardous cheat modes require Ctrl + Alt

View File

@ -369,11 +369,11 @@ enum WindowsVersion {
WINDOWS_UNDEFINED = -1,
WINDOWS_UNSUPPORTED = 0,
WINDOWS_XP = 0x51,
WINDOWS_2003 = 0x52, // Also XP x64
WINDOWS_VISTA = 0x60,
WINDOWS_7 = 0x61,
WINDOWS_8 = 0x62,
WINDOWS_8_1 = 0x63,
WINDOWS_2003 = 0x52, // Also XP_64
WINDOWS_VISTA = 0x60, // Also 2008
WINDOWS_7 = 0x61, // Also 2008_R2
WINDOWS_8 = 0x62, // Also 2012
WINDOWS_8_1 = 0x63, // Also 2012_R2
WINDOWS_10_PREVIEW1 = 0x64,
WINDOWS_10 = 0xA0,
WINDOWS_MAX
@ -460,6 +460,7 @@ extern DWORD GetResourceSize(HMODULE module, char* name, char* type, const char*
extern DWORD RunCommand(const char* cmdline, const char* dir, BOOL log);
extern BOOL CompareGUID(const GUID *guid1, const GUID *guid2);
extern BOOL GetDevices(DWORD devnum);
extern BOOL ResetDevice(int index);
extern BOOL GetOpticalMedia(IMG_SAVE* img_save);
extern BOOL SetLGP(BOOL bRestore, BOOL* bExistingKey, const char* szPath, const char* szPolicy, DWORD dwValue);
extern LONG GetEntryWidth(HWND hDropDown, const char* entry);

View File

@ -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.18.1200"
CAPTION "Rufus 2.18.1201"
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,18,1200,0
PRODUCTVERSION 2,18,1200,0
FILEVERSION 2,18,1201,0
PRODUCTVERSION 2,18,1201,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.18.1200"
VALUE "FileVersion", "2.18.1201"
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.18.1200"
VALUE "ProductVersion", "2.18.1201"
END
END
BLOCK "VarFileInfo"

View File

@ -284,20 +284,20 @@ void GetWindowsVersion(void)
switch (nWindowsVersion) {
case 0x51: w = "XP";
break;
case 0x52: w = (!GetSystemMetrics(89)?"2003":"2003_R2");
case 0x52: w = (!GetSystemMetrics(89)?"Server 2003":"Server 2003_R2");
break;
case 0x60: w = (ws?"Vista":"2008");
case 0x60: w = (ws?"Vista":"Server 2008");
break;
case 0x61: w = (ws?"7":"2008_R2");
case 0x61: w = (ws?"7":"Server 2008_R2");
break;
case 0x62: w = (ws?"8":"2012");
case 0x62: w = (ws?"8":"Server 2012");
break;
case 0x63: w = (ws?"8.1":"2012_R2");
case 0x63: w = (ws?"8.1":"Server 2012_R2");
break;
case 0x64: w = (ws?"10 (Preview 1)":"Server 10 (Preview 1)");
break;
// Starting with Windows 10 Preview 2, the major is the same as the public-facing version
case 0xA0: w = (ws?"10":"Server 10");
case 0xA0: w = (ws?"10":"Server 2016");
break;
default:
if (nWindowsVersion < 0x51)