diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml index ee7ae8d6..d59adfd5 100644 --- a/.github/workflows/mingw.yml +++ b/.github/workflows/mingw.yml @@ -35,7 +35,6 @@ jobs: include: - { sys: mingw64, env: x86_64, exe: rufus.exe } - { sys: mingw32, env: i686, exe: rufus_x86.exe } - - { sys: ucrt64, env: ucrt-x86_64, exe: rufus_ucrt.exe } defaults: run: @@ -81,7 +80,7 @@ jobs: - name: Build run: | ./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 }} strip ./${{ matrix.exe }} upx --lzma --best ./${{ matrix.exe }} diff --git a/src/dev.c b/src/dev.c index 7ee2116e..b1f1cdf7 100644 --- a/src/dev.c +++ b/src/dev.c @@ -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 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 */ static BOOL GetUSBProperties(char* parent_path, char* device_id, usb_device_props* props) { - int pass; BOOL r = FALSE; CONFIGRET cr; HANDLE handle = INVALID_HANDLE_VALUE; + DWORD size; DEVINST device_inst; USB_NODE_CONNECTION_INFORMATION_EX conn_info; 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)) 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)) { props->vid = conn_info.DeviceDescriptor.idVendor; 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 - // 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; + props->speed = conn_info.Speed + 1; r = TRUE; } // 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); memset(&conn_info_v2, 0, size); conn_info_v2.ConnectionIndex = (ULONG)props->port; conn_info_v2.Length = size; 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)) { uprintf("Could not get node connection information (V2) for device '%s': %s", device_id, WindowsErrorString()); } 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) { - props->current_speed = USB_SPEED_SUPER_5G; + props->speed = USB_SPEED_SUPER; } 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) { - props->max_speed = USB_SPEED_SUPER_5G; + props->lower_speed = 1; } out: @@ -602,12 +471,7 @@ BOOL GetDevices(DWORD devnum) const char* scsi_card_name[] = { "_SD_", "_SDHC_", "_SDXC_", "_MMC_", "_MS_", "_MSPro_", "_xDPicture_", "_O2Media_" }; - const char* usb_version[USB_SPEED_MAX] = { - "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* usb_speed_name[USB_SPEED_MAX] = { "USB", "USB 1.0", "USB 1.1", "USB 2.0", "USB 3.0", "USB 3.1" }; 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 htab_table htab_devid = HTAB_EMPTY; @@ -983,13 +847,12 @@ BOOL GetDevices(DWORD devnum) if (s < ARRAYSIZE(ignore_vid_pid)) continue; } - if (props.current_speed >= USB_SPEED_MAX) - props.current_speed = 0; + if (props.speed >= USB_SPEED_MAX) + props.speed = 0; 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); - if (props.max_speed > props.current_speed) - uprintf("NOTE: This a %s (%s) device operating at %s speed (%s)...", usb_version[props.max_speed], - usb_speed[props.max_speed], usb_version[props.current_speed], usb_speed[props.current_speed]); + usb_speed_name[props.speed], props.is_UASP ? ")" : "", buffer, str, method_str); + if (props.lower_speed) + uprintf("NOTE: This device is a USB 3.%c device operating at lower speed...", '0' + props.lower_speed - 1); } devint_data.cbSize = sizeof(devint_data); devint_detail_data = NULL; diff --git a/src/dev.h b/src/dev.h index 98710860..d0543d13 100644 --- a/src/dev.h +++ b/src/dev.h @@ -21,22 +21,19 @@ #include #define USB_SPEED_UNKNOWN 0 -#define USB_SPEED_LOW_1_5M 1 // USB 1.0 -#define USB_SPEED_FULL_12M 2 // USB 1.1 -#define USB_SPEED_HIGH_480M 3 // USB 2.0 -#define USB_SPEED_SUPER_5G 4 // USB 3.0 -#define USB_SPEED_SUPER_10G 5 // USB 3.1 -#define USB_SPEED_SUPER_20G 6 // USB 3.2 -#define USB_SPEED_SUPER_40G 7 // USB 4.0 -#define USB_SPEED_SUPER_80G 8 // USB 4.1 -#define USB_SPEED_MAX 9 +#define USB_SPEED_LOW 1 +#define USB_SPEED_FULL 2 +#define USB_SPEED_HIGH 3 +#define USB_SPEED_SUPER 4 +#define USB_SPEED_SUPER_PLUS 5 +#define USB_SPEED_MAX 6 /* List of the properties we are interested in */ typedef struct usb_device_props { int32_t vid; int32_t pid; - uint32_t current_speed; - uint32_t max_speed; + uint32_t speed; + uint32_t lower_speed; uint32_t port; BOOLEAN is_USB; BOOLEAN is_SCSI; @@ -148,47 +145,3 @@ const GUID GUID_DEVINTERFACE_USB_HUB = { 0xf18a0e88L, 0xc30c, 0x11d0, {0x88, 0x15, 0x00, 0xa0, 0xc9, 0x06, 0xbe, 0xd8} }; #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; - diff --git a/src/ext2fs/nt_io.c b/src/ext2fs/nt_io.c index 81165e6f..f36dc3b2 100644 --- a/src/ext2fs/nt_io.c +++ b/src/ext2fs/nt_io.c @@ -277,7 +277,7 @@ static PCSTR _NormalizeDeviceName(IN PCSTR Device, IN PSTR NormalizedDeviceNameB return Device; // Handle custom paths of the form " " used by Rufus to // 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; if ((NormalizedDeviceNameBuffer[1] == '\\') || (NormalizedDeviceNameBuffer[1] == '.')) NormalizedDeviceNameBuffer[1] = '?'; diff --git a/src/rufus.rc b/src/rufus.rc index e82dbf12..27ac0fb0 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 232, 326 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_ACCEPTFILES -CAPTION "Rufus 4.15.2411" +CAPTION "Rufus 4.15.2409" FONT 9, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP @@ -409,8 +409,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,15,2411,0 - PRODUCTVERSION 4,15,2411,0 + FILEVERSION 4,15,2409,0 + PRODUCTVERSION 4,15,2409,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -428,13 +428,13 @@ BEGIN VALUE "Comments", "https://rufus.ie" VALUE "CompanyName", "Akeo Consulting" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "4.15.2411" + VALUE "FileVersion", "4.15.2409" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2026 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" VALUE "OriginalFilename", "rufus-4.15.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "4.15.2411" + VALUE "ProductVersion", "4.15.2409" END END BLOCK "VarFileInfo"