1
1
Fork 0
mirror of https://github.com/pbatard/rufus.git synced 2026-10-22 22:34:26 +00:00

Compare commits

..

No commits in common. "714e3ad90126fa0d751d071222f3b29e11d8f435" and "875f221d5b4fa2c43cad1b85ae975d106964949f" have entirely different histories.

5 changed files with 27 additions and 212 deletions

View file

@ -35,7 +35,6 @@ jobs:
include: include:
- { sys: mingw64, env: x86_64, exe: rufus.exe } - { sys: mingw64, env: x86_64, exe: rufus.exe }
- { sys: mingw32, env: i686, exe: rufus_x86.exe } - { sys: mingw32, env: i686, exe: rufus_x86.exe }
- { sys: ucrt64, env: ucrt-x86_64, exe: rufus_ucrt.exe }
defaults: defaults:
run: run:
@ -81,7 +80,7 @@ jobs:
- name: Build - name: Build
run: | run: |
./configure --disable-debug ${{ steps.set_alpha.outputs.option }} ${{ steps.set_beta.outputs.option }} ./configure --disable-debug ${{ steps.set_alpha.outputs.option }} ${{ steps.set_beta.outputs.option }}
make -j4 ACLOCAL=: AUTOMAKE=: AUTOCONF=: AUTOHEADER=: make -j4
mv ./src/rufus.exe ./${{ matrix.exe }} mv ./src/rufus.exe ./${{ matrix.exe }}
strip ./${{ matrix.exe }} strip ./${{ matrix.exe }}
upx --lzma --best ./${{ matrix.exe }} upx --lzma --best ./${{ matrix.exe }}

161
src/dev.c
View file

@ -49,83 +49,18 @@ extern RUFUS_DRIVE rufus_drive[MAX_DRIVES];
extern BOOL enable_HDDs, enable_VHDs, use_fake_units, enable_vmdk, usb_debug; extern BOOL enable_HDDs, enable_VHDs, use_fake_units, enable_vmdk, usb_debug;
extern BOOL list_non_usb_removable_drives, its_a_me_mario; extern BOOL list_non_usb_removable_drives, its_a_me_mario;
static inline uint64_t ssp_to_bps(uint32_t v)
{
static const uint64_t scale[4] = { 1ULL, 1000ULL, 1000000ULL, 1000000000ULL };
return (uint64_t)(v >> 16) * scale[(v >> 4) & 0x3];
}
static uint64_t get_max_bps(const uint8_t* bos, uint32_t len)
{
uint8_t l, min_rx_lanes, min_tx_lanes;
uint32_t i, n, ssp, offset, attr, avail;
uint64_t bps, max_bps = 0;
if (len < 5 || bos[0] < 5 || bos[1] != 0x0F)
return 0;
offset = bos[0]; // skip the BOS header
while (offset + 3 <= len) {
l = bos[offset];
if (l < 3 || offset + l > len)
break;
// Look for the SUPERSPEED_PLUS (0x0A) Device Capability descriptor (0x10)
if (bos[offset + 1] == 0x10 && bos[offset + 2] == 0x0A && l >= 12) {
// Get the bmAttributes field
memcpy(&attr, &bos[offset + 4], sizeof(attr));
// Get the min lanes from the wFunctionalitySupport field
min_rx_lanes = bos[offset + 9] & 0x0F;
min_tx_lanes = bos[offset + 9] >> 4;
n = (attr & 0x1F) + 1; // Number of Sublink Speed Attributes
avail = (l - 12) / 4;
if (n > avail)
n = avail;
for (i = 0; i < n; i++) {
memcpy(&ssp, &bos[offset + 12 + 4 * i], sizeof(ssp));
bps = ssp_to_bps(ssp) * ((ssp & 0x80) ? min_tx_lanes : min_rx_lanes);
if (bps > max_bps)
max_bps = bps;
}
}
// Next descriptor
offset += l;
}
return max_bps;
}
static uint32_t version_to_speed(uint16_t usb_version) {
switch (usb_version) {
case 0x0100: return USB_SPEED_LOW_1_5M;
case 0x0110: return USB_SPEED_FULL_12M;
case 0x0200:
case 0x0201:
case 0x0210: return USB_SPEED_HIGH_480M;
case 0x0300: return USB_SPEED_SUPER_5G;
case 0x0310: return USB_SPEED_SUPER_10G;
case 0x0320: return USB_SPEED_SUPER_20G;
case 0x0400: return USB_SPEED_SUPER_40G;
case 0x0410: return USB_SPEED_SUPER_80G;
default: return USB_SPEED_UNKNOWN;
}
}
/* /*
* Get the VID, PID and current device speed * Get the VID, PID and current device speed
*/ */
static BOOL GetUSBProperties(char* parent_path, char* device_id, usb_device_props* props) static BOOL GetUSBProperties(char* parent_path, char* device_id, usb_device_props* props)
{ {
int pass;
BOOL r = FALSE; BOOL r = FALSE;
CONFIGRET cr; CONFIGRET cr;
HANDLE handle = INVALID_HANDLE_VALUE; HANDLE handle = INVALID_HANDLE_VALUE;
DWORD size;
DEVINST device_inst; DEVINST device_inst;
USB_NODE_CONNECTION_INFORMATION_EX conn_info; USB_NODE_CONNECTION_INFORMATION_EX conn_info;
USB_NODE_CONNECTION_INFORMATION_EX_V2 conn_info_v2; USB_NODE_CONNECTION_INFORMATION_EX_V2 conn_info_v2;
MY_USB_NODE_CONNECTION_SUPERSPEEDPLUS_INFORMATION ssp;
uint8_t buf[sizeof(USB_DESCRIPTOR_REQUEST) + 512] = { 0 };
uint8_t* bos = &buf[sizeof(USB_DESCRIPTOR_REQUEST)];
USB_DESCRIPTOR_REQUEST* req = (USB_DESCRIPTOR_REQUEST*)buf;
DWORD size, header_size = offsetof(USB_DESCRIPTOR_REQUEST, Data);
if ((parent_path == NULL) || (device_id == NULL) || (props == NULL)) if ((parent_path == NULL) || (device_id == NULL) || (props == NULL))
goto out; goto out;
@ -164,92 +99,26 @@ static BOOL GetUSBProperties(char* parent_path, char* device_id, usb_device_prop
if ((conn_info.DeviceDescriptor.idVendor != 0) || (conn_info.DeviceDescriptor.idProduct != 0)) { if ((conn_info.DeviceDescriptor.idVendor != 0) || (conn_info.DeviceDescriptor.idProduct != 0)) {
props->vid = conn_info.DeviceDescriptor.idVendor; props->vid = conn_info.DeviceDescriptor.idVendor;
props->pid = conn_info.DeviceDescriptor.idProduct; props->pid = conn_info.DeviceDescriptor.idProduct;
// Not exactly accurate since a USB 3.x device connected to a USB 2.0 port will use the props->speed = conn_info.Speed + 1;
// 2.0 lanes and report a 2.0 device descriptor there, which means that, despite being
// able to operate at 3.0 speeds, we only see a max speed of 2.0. Our additional checks
// below should however be able to take care of detecting the max speed.
props->max_speed = version_to_speed(conn_info.DeviceDescriptor.bcdUSB);
props->current_speed = conn_info.Speed + 1;
r = TRUE; r = TRUE;
} }
// The USB speed report of modern Windows is a complete mess // The USB speed report of modern Windows is a complete mess
size = sizeof(ssp);
memset(&ssp, 0, size);
ssp.ConnectionIndex = (ULONG)props->port;
ssp.Length = size;
size = sizeof(conn_info_v2); size = sizeof(conn_info_v2);
memset(&conn_info_v2, 0, size); memset(&conn_info_v2, 0, size);
conn_info_v2.ConnectionIndex = (ULONG)props->port; conn_info_v2.ConnectionIndex = (ULONG)props->port;
conn_info_v2.Length = size; conn_info_v2.Length = size;
conn_info_v2.SupportedUsbProtocols.Usb300 = 1; conn_info_v2.SupportedUsbProtocols.Usb300 = 1;
// Requires Windows 11 24H2 or later
if (DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_SUPERSPEEDPLUS_INFORMATION, &ssp, sizeof(ssp), &ssp, sizeof(ssp), &size, NULL)) {
uint64_t cur_bps = max(ssp_to_bps(ssp.RxSuperSpeedPlus) * (ssp.RxLaneCount + 1), ssp_to_bps(ssp.TxSuperSpeedPlus) * (ssp.TxLaneCount + 1));
if (cur_bps >= 80000000000ULL)
props->current_speed = USB_SPEED_SUPER_80G;
else if (cur_bps >= 40000000000ULL)
props->current_speed = USB_SPEED_SUPER_40G;
else if (cur_bps >= 20000000000ULL)
props->current_speed = USB_SPEED_SUPER_20G;
else if (cur_bps >= 10000000000ULL)
props->current_speed = USB_SPEED_SUPER_10G;
else if (cur_bps >= 5000000000ULL)
props->current_speed = USB_SPEED_SUPER_5G;
else
goto next;
props->max_speed = props->current_speed;
// Read the BOS to compare with the advertised speed
size = 5;
for (pass = 0; pass < 2; pass++) {
req->ConnectionIndex = (ULONG)props->port;
req->SetupPacket.bmRequest = 0x80;
req->SetupPacket.bRequest = 0x06;
req->SetupPacket.wValue = (0x0F << 8);
req->SetupPacket.wIndex = 0;
req->SetupPacket.wLength = (USHORT)size;
if (!DeviceIoControl(handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, req, header_size + size, req, header_size + size, &size, NULL) ||
size < header_size + 5)
break;
if (pass == 0) {
size = req->Data[2] | (req->Data[3] << 8);
if (size < 5 || size > 512)
break;
}
}
if (pass == 2) {
// Now the problem is that the max bps from the BOS is for *single* lane only, and the
// USB Forum *STUPIDLY* defined a minimum amount of lanes in the BOS but NOT a maximum
// or a preferred, which means we can not actually get the max speed of a USB 3.2 (2 x
// 10G lanes) if it's operating at USB 3.1 speed (1 x 10G lane). Somebody *REALLY*
// doesn't want users to find out if they are being screwed on USB speeds...
uint64_t max_bps = get_max_bps(bos, size);
if (max_bps >= 80000000000ULL)
props->max_speed = USB_SPEED_SUPER_80G;
else if (max_bps >= 40000000000ULL)
props->max_speed = USB_SPEED_SUPER_40G;
else if (max_bps >= 20000000000ULL)
props->max_speed = USB_SPEED_SUPER_20G;
else if (max_bps >= 10000000000ULL)
props->max_speed = USB_SPEED_SUPER_10G;
else if (max_bps >= 5000000000ULL)
props->max_speed = USB_SPEED_SUPER_5G;
}
goto out;
}
next:
if (!DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2, &conn_info_v2, size, &conn_info_v2, size, &size, NULL)) { if (!DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2, &conn_info_v2, size, &conn_info_v2, size, &size, NULL)) {
uprintf("Could not get node connection information (V2) for device '%s': %s", device_id, WindowsErrorString()); uprintf("Could not get node connection information (V2) for device '%s': %s", device_id, WindowsErrorString());
} else if (conn_info_v2.Flags.DeviceIsOperatingAtSuperSpeedPlusOrHigher) { } else if (conn_info_v2.Flags.DeviceIsOperatingAtSuperSpeedPlusOrHigher) {
props->current_speed = USB_SPEED_SUPER_10G; props->speed = USB_SPEED_SUPER_PLUS;
} else if (conn_info_v2.Flags.DeviceIsOperatingAtSuperSpeedOrHigher) { } else if (conn_info_v2.Flags.DeviceIsOperatingAtSuperSpeedOrHigher) {
props->current_speed = USB_SPEED_SUPER_5G; props->speed = USB_SPEED_SUPER;
} else if (conn_info_v2.Flags.DeviceIsSuperSpeedPlusCapableOrHigher) { } else if (conn_info_v2.Flags.DeviceIsSuperSpeedPlusCapableOrHigher) {
props->max_speed = USB_SPEED_SUPER_10G; props->lower_speed = 2;
} else if (conn_info_v2.Flags.DeviceIsSuperSpeedCapableOrHigher) { } else if (conn_info_v2.Flags.DeviceIsSuperSpeedCapableOrHigher) {
props->max_speed = USB_SPEED_SUPER_5G; props->lower_speed = 1;
} }
out: out:
@ -602,12 +471,7 @@ BOOL GetDevices(DWORD devnum)
const char* scsi_card_name[] = { const char* scsi_card_name[] = {
"_SD_", "_SDHC_", "_SDXC_", "_MMC_", "_MS_", "_MSPro_", "_xDPicture_", "_O2Media_" "_SD_", "_SDHC_", "_SDXC_", "_MMC_", "_MS_", "_MSPro_", "_xDPicture_", "_O2Media_"
}; };
const char* usb_version[USB_SPEED_MAX] = { const char* usb_speed_name[USB_SPEED_MAX] = { "USB", "USB 1.0", "USB 1.1", "USB 2.0", "USB 3.0", "USB 3.1" };
"USB", "USB 1.0", "USB 1.1", "USB 2.1", "USB 3.0", "USB 3.1", "USB 3.2", "USB 4.0", "USB 4.1"
}; // See, USB Forum, it *REALLY* isn't that hard!!!
const char* usb_speed[USB_SPEED_MAX] = {
"???", "1.5 Mbps", "12 Mbps", "480 Mbps", "5 Gbps", "10 Gbps", "20 Gbps", "40 Gbps", "80 Gbps"
};
const char* windows_sandbox_vhd_label = "PortableBaseLayer"; const char* windows_sandbox_vhd_label = "PortableBaseLayer";
// Hash table and String Array used to match a Device ID with the parent hub's Device Interface Path // Hash table and String Array used to match a Device ID with the parent hub's Device Interface Path
htab_table htab_devid = HTAB_EMPTY; htab_table htab_devid = HTAB_EMPTY;
@ -983,13 +847,12 @@ BOOL GetDevices(DWORD devnum)
if (s < ARRAYSIZE(ignore_vid_pid)) if (s < ARRAYSIZE(ignore_vid_pid))
continue; continue;
} }
if (props.current_speed >= USB_SPEED_MAX) if (props.speed >= USB_SPEED_MAX)
props.current_speed = 0; props.speed = 0;
uprintf("Found %s%s%s device '%s' (%s) %s", props.is_UASP ? "UAS (" : "", uprintf("Found %s%s%s device '%s' (%s) %s", props.is_UASP ? "UAS (" : "",
usb_version[props.current_speed], props.is_UASP ? ")" : "", buffer, str, method_str); usb_speed_name[props.speed], props.is_UASP ? ")" : "", buffer, str, method_str);
if (props.max_speed > props.current_speed) if (props.lower_speed)
uprintf("NOTE: This a %s (%s) device operating at %s speed (%s)...", usb_version[props.max_speed], uprintf("NOTE: This device is a USB 3.%c device operating at lower speed...", '0' + props.lower_speed - 1);
usb_speed[props.max_speed], usb_version[props.current_speed], usb_speed[props.current_speed]);
} }
devint_data.cbSize = sizeof(devint_data); devint_data.cbSize = sizeof(devint_data);
devint_detail_data = NULL; devint_detail_data = NULL;

View file

@ -21,22 +21,19 @@
#include <cfgmgr32.h> #include <cfgmgr32.h>
#define USB_SPEED_UNKNOWN 0 #define USB_SPEED_UNKNOWN 0
#define USB_SPEED_LOW_1_5M 1 // USB 1.0 #define USB_SPEED_LOW 1
#define USB_SPEED_FULL_12M 2 // USB 1.1 #define USB_SPEED_FULL 2
#define USB_SPEED_HIGH_480M 3 // USB 2.0 #define USB_SPEED_HIGH 3
#define USB_SPEED_SUPER_5G 4 // USB 3.0 #define USB_SPEED_SUPER 4
#define USB_SPEED_SUPER_10G 5 // USB 3.1 #define USB_SPEED_SUPER_PLUS 5
#define USB_SPEED_SUPER_20G 6 // USB 3.2 #define USB_SPEED_MAX 6
#define USB_SPEED_SUPER_40G 7 // USB 4.0
#define USB_SPEED_SUPER_80G 8 // USB 4.1
#define USB_SPEED_MAX 9
/* List of the properties we are interested in */ /* List of the properties we are interested in */
typedef struct usb_device_props { typedef struct usb_device_props {
int32_t vid; int32_t vid;
int32_t pid; int32_t pid;
uint32_t current_speed; uint32_t speed;
uint32_t max_speed; uint32_t lower_speed;
uint32_t port; uint32_t port;
BOOLEAN is_USB; BOOLEAN is_USB;
BOOLEAN is_SCSI; BOOLEAN is_SCSI;
@ -148,47 +145,3 @@ const GUID GUID_DEVINTERFACE_USB_HUB =
{ 0xf18a0e88L, 0xc30c, 0x11d0, {0x88, 0x15, 0x00, 0xa0, 0xc9, 0x06, 0xbe, 0xd8} }; { 0xf18a0e88L, 0xc30c, 0x11d0, {0x88, 0x15, 0x00, 0xa0, 0xc9, 0x06, 0xbe, 0xd8} };
#define DEVID_HTAB_SIZE 257 #define DEVID_HTAB_SIZE 257
#ifndef FILE_DEVICE_USB
#define FILE_DEVICE_USB FILE_DEVICE_UNKNOWN
#endif
typedef struct _USB_DESCRIPTOR_REQUEST {
ULONG ConnectionIndex;
struct {
UCHAR bmRequest;
UCHAR bRequest;
USHORT wValue;
USHORT wIndex;
USHORT wLength;
} SetupPacket;
UCHAR Data[0];
} USB_DESCRIPTOR_REQUEST, * PUSB_DESCRIPTOR_REQUEST;
#ifndef USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION
#define USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION 260
#endif
#ifndef IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION
#define IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION CTL_CODE \
(FILE_DEVICE_USB, USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, METHOD_BUFFERED, FILE_ANY_ACCESS)
#endif
#ifndef USB_GET_NODE_CONNECTION_SUPERSPEEDPLUS_INFORMATION
#define USB_GET_NODE_CONNECTION_SUPERSPEEDPLUS_INFORMATION 289
#endif
#ifndef IOCTL_USB_GET_NODE_CONNECTION_SUPERSPEEDPLUS_INFORMATION
#define IOCTL_USB_GET_NODE_CONNECTION_SUPERSPEEDPLUS_INFORMATION CTL_CODE\
(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_SUPERSPEEDPLUS_INFORMATION, METHOD_BUFFERED, FILE_ANY_ACCESS)
#endif
typedef struct {
ULONG ConnectionIndex;
ULONG Length;
ULONG RxSuperSpeedPlus;
ULONG RxLaneCount;
ULONG TxSuperSpeedPlus;
ULONG TxLaneCount;
} MY_USB_NODE_CONNECTION_SUPERSPEEDPLUS_INFORMATION;

View file

@ -277,7 +277,7 @@ static PCSTR _NormalizeDeviceName(IN PCSTR Device, IN PSTR NormalizedDeviceNameB
return Device; return Device;
// Handle custom paths of the form "<Physical> <Offset> <Size>" used by Rufus to // Handle custom paths of the form "<Physical> <Offset> <Size>" used by Rufus to
// enable multi-partition access on removable devices, for pre 1703 platforms. // enable multi-partition access on removable devices, for pre 1703 platforms.
if (sscanf(Device, "%s %llu %llu", NormalizedDeviceNameBuffer, Offset, Size) < 1) if (sscanf(Device, "%s %I64u %I64u", NormalizedDeviceNameBuffer, Offset, Size) < 1)
return NULL; return NULL;
if ((NormalizedDeviceNameBuffer[1] == '\\') || (NormalizedDeviceNameBuffer[1] == '.')) if ((NormalizedDeviceNameBuffer[1] == '\\') || (NormalizedDeviceNameBuffer[1] == '.'))
NormalizedDeviceNameBuffer[1] = '?'; NormalizedDeviceNameBuffer[1] = '?';

View file

@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 232, 326 IDD_DIALOG DIALOGEX 12, 12, 232, 326
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 4.15.2411" CAPTION "Rufus 4.15.2409"
FONT 9, "Segoe UI Symbol", 400, 0, 0x0 FONT 9, "Segoe UI Symbol", 400, 0, 0x0
BEGIN BEGIN
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
@ -409,8 +409,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,15,2411,0 FILEVERSION 4,15,2409,0
PRODUCTVERSION 4,15,2411,0 PRODUCTVERSION 4,15,2409,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -428,13 +428,13 @@ BEGIN
VALUE "Comments", "https://rufus.ie" VALUE "Comments", "https://rufus.ie"
VALUE "CompanyName", "Akeo Consulting" VALUE "CompanyName", "Akeo Consulting"
VALUE "FileDescription", "Rufus" VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "4.15.2411" VALUE "FileVersion", "4.15.2409"
VALUE "InternalName", "Rufus" VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2026 Pete Batard (GPL v3)" VALUE "LegalCopyright", "© 2011-2026 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
VALUE "OriginalFilename", "rufus-4.15.exe" VALUE "OriginalFilename", "rufus-4.15.exe"
VALUE "ProductName", "Rufus" VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "4.15.2411" VALUE "ProductVersion", "4.15.2409"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"