mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[usb] enable listing of non USB card readers
* Also fix the VID:PID population of USB card readers * Also improve enumeration debugging * Also add an unofficial cheat mode to list non USB *REMOVABLE* drives * Closes #693
This commit is contained in:
parent
58755c1bc4
commit
f88faf1a4f
6 changed files with 248 additions and 100 deletions
|
@ -395,10 +395,10 @@ static BOOL _GetDriveLettersAndType(DWORD DriveIndex, char* drive_letters, UINT*
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* IOCTL_STORAGE_GET_DEVICE_NUMBER's STORAGE_DEVICE_NUMBER.DeviceNumber is
|
// IOCTL_STORAGE_GET_DEVICE_NUMBER's STORAGE_DEVICE_NUMBER.DeviceNumber is
|
||||||
not unique! An HDD, a DVD and probably other drives can have the same
|
// not unique! An HDD, a DVD and probably other drives can have the same
|
||||||
value there => Use GetDriveType() to filter out unwanted devices.
|
// value there => Use GetDriveType() to filter out unwanted devices.
|
||||||
See https://github.com/pbatard/rufus/issues/32 for details. */
|
// See https://github.com/pbatard/rufus/issues/32#issuecomment-3785956
|
||||||
_drive_type = GetDriveTypeA(drive);
|
_drive_type = GetDriveTypeA(drive);
|
||||||
|
|
||||||
if ((_drive_type != DRIVE_REMOVABLE) && (_drive_type != DRIVE_FIXED))
|
if ((_drive_type != DRIVE_REMOVABLE) && (_drive_type != DRIVE_FIXED))
|
||||||
|
|
|
@ -1883,7 +1883,7 @@ DWORD WINAPI FormatThread(void* param)
|
||||||
} else if (tt == TT_UEFI) {
|
} else if (tt == TT_UEFI) {
|
||||||
// For once, no need to do anything - just check our sanity
|
// For once, no need to do anything - just check our sanity
|
||||||
if ( (bt != BT_ISO) || (!img_report.has_efi) || (fs > FS_NTFS) ) {
|
if ( (bt != BT_ISO) || (!img_report.has_efi) || (fs > FS_NTFS) ) {
|
||||||
uprintf("Spock gone crazy error!\n");
|
uprintf("Spock gone crazy error in %s:%d", __FILE__, __LINE__);
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INSTALL_FAILURE;
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INSTALL_FAILURE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
25
src/rufus.c
25
src/rufus.c
|
@ -152,7 +152,7 @@ BOOL use_own_c32[NB_OLD_C32] = {FALSE, FALSE}, mbr_selected_by_user = FALSE, tog
|
||||||
BOOL iso_op_in_progress = FALSE, format_op_in_progress = FALSE, right_to_left_mode = FALSE;
|
BOOL iso_op_in_progress = FALSE, format_op_in_progress = FALSE, right_to_left_mode = FALSE;
|
||||||
BOOL enable_HDDs = FALSE, force_update = FALSE, enable_ntfs_compression = FALSE, no_confirmation_on_cancel = FALSE, lock_drive = TRUE;
|
BOOL enable_HDDs = FALSE, force_update = FALSE, enable_ntfs_compression = FALSE, no_confirmation_on_cancel = FALSE, lock_drive = TRUE;
|
||||||
BOOL advanced_mode, allow_dual_uefi_bios, detect_fakes, enable_vmdk, force_large_fat32, usb_debug, use_fake_units, preserve_timestamps;
|
BOOL advanced_mode, allow_dual_uefi_bios, detect_fakes, enable_vmdk, force_large_fat32, usb_debug, use_fake_units, preserve_timestamps;
|
||||||
BOOL zero_drive = FALSE;
|
BOOL zero_drive = FALSE, list_non_usb_removable_drives = FALSE;
|
||||||
int dialog_showing = 0, lang_button_id = 0;
|
int dialog_showing = 0, lang_button_id = 0;
|
||||||
uint16_t rufus_version[3], embedded_sl_version[2];
|
uint16_t rufus_version[3], embedded_sl_version[2];
|
||||||
char embedded_sl_version_str[2][12] = { "?.??", "?.??" };
|
char embedded_sl_version_str[2][12] = { "?.??", "?.??" };
|
||||||
|
@ -1762,7 +1762,7 @@ void InitDialog(HWND hDlg)
|
||||||
if (selected_locale->ctrl_id & LOC_NEEDS_UPDATE) {
|
if (selected_locale->ctrl_id & LOC_NEEDS_UPDATE) {
|
||||||
uprintf("NOTE: The %s translation requires an update, but the current translator hasn't submitted "
|
uprintf("NOTE: The %s translation requires an update, but the current translator hasn't submitted "
|
||||||
"one. Because of this, some messages will only be displayed in English.", selected_locale->txt[1]);
|
"one. Because of this, some messages will only be displayed in English.", selected_locale->txt[1]);
|
||||||
uprintf("If you think you can help update this translation, please e-mail <pete@akeo.ie>.");
|
uprintf("If you think you can help update this translation, please e-mail the author of this application");
|
||||||
}
|
}
|
||||||
|
|
||||||
SetClusterSizeLabels();
|
SetClusterSizeLabels();
|
||||||
|
@ -2826,6 +2826,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||||
int wait_for_mutex = 0;
|
int wait_for_mutex = 0;
|
||||||
FILE* fd;
|
FILE* fd;
|
||||||
BOOL attached_console = FALSE, external_loc_file = FALSE, lgp_set = FALSE, automount, disable_hogger = FALSE;
|
BOOL attached_console = FALSE, external_loc_file = FALSE, lgp_set = FALSE, automount, disable_hogger = FALSE;
|
||||||
|
BOOL previous_enable_HDDs = FALSE;
|
||||||
BYTE *loc_data;
|
BYTE *loc_data;
|
||||||
DWORD loc_size, size;
|
DWORD loc_size, size;
|
||||||
char tmp_path[MAX_PATH] = "", loc_file[MAX_PATH] = "", ini_path[MAX_PATH], ini_flags[] = "rb";
|
char tmp_path[MAX_PATH] = "", loc_file[MAX_PATH] = "", ini_path[MAX_PATH], ini_flags[] = "rb";
|
||||||
|
@ -3278,6 +3279,26 @@ relaunch:
|
||||||
PostMessage(hDlg, WM_COMMAND, (WPARAM)IDC_START, 0);
|
PostMessage(hDlg, WM_COMMAND, (WPARAM)IDC_START, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hazardous cheat modes require Ctrl + Alt
|
||||||
|
// Ctrl-Alt-F => List non USB removable drives such as eSATA, etc - CAUTION!!!
|
||||||
|
if ((msg.message == WM_KEYDOWN) && (msg.wParam == 'F') &&
|
||||||
|
(GetKeyState(VK_CONTROL) & 0x8000) && (GetKeyState(VK_MENU) & 0x8000)) {
|
||||||
|
list_non_usb_removable_drives = !list_non_usb_removable_drives;
|
||||||
|
if (list_non_usb_removable_drives) {
|
||||||
|
previous_enable_HDDs = enable_HDDs;
|
||||||
|
enable_HDDs = TRUE;
|
||||||
|
} else {
|
||||||
|
enable_HDDs = previous_enable_HDDs;
|
||||||
|
}
|
||||||
|
CheckDlgButton(hMainDialog, IDC_ENABLE_FIXED_DISKS, enable_HDDs ? BST_CHECKED : BST_UNCHECKED);
|
||||||
|
PrintStatus2000("Listing of non-USB removable drives", list_non_usb_removable_drives);
|
||||||
|
uprintf("NOTE: Listing of non-USB removable drives has been %s.", (list_non_usb_removable_drives)?"enabled (CAUTION!)":"disabled");
|
||||||
|
if (list_non_usb_removable_drives)
|
||||||
|
uprintf("By using this unofficial cheat mode you forfeit ANY RIGHT to complain if you lose valuable data!");
|
||||||
|
GetUSBDevices(0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Let the system handle dialog messages (e.g. those from the tab key)
|
// Let the system handle dialog messages (e.g. those from the tab key)
|
||||||
if (!IsDialogMessage(hDlg, &msg) && !IsDialogMessage(hLogDlg, &msg)) {
|
if (!IsDialogMessage(hDlg, &msg) && !IsDialogMessage(hLogDlg, &msg)) {
|
||||||
TranslateMessage(&msg);
|
TranslateMessage(&msg);
|
||||||
|
|
10
src/rufus.rc
10
src/rufus.rc
|
@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||||
IDD_DIALOG DIALOGEX 12, 12, 242, 376
|
IDD_DIALOG DIALOGEX 12, 12, 242, 376
|
||||||
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 2.7.857"
|
CAPTION "Rufus 2.7.858"
|
||||||
FONT 8, "Segoe UI Symbol", 400, 0, 0x0
|
FONT 8, "Segoe UI Symbol", 400, 0, 0x0
|
||||||
BEGIN
|
BEGIN
|
||||||
LTEXT "Device",IDS_DEVICE_TXT,9,6,200,8
|
LTEXT "Device",IDS_DEVICE_TXT,9,6,200,8
|
||||||
|
@ -320,8 +320,8 @@ END
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 2,7,857,0
|
FILEVERSION 2,7,858,0
|
||||||
PRODUCTVERSION 2,7,857,0
|
PRODUCTVERSION 2,7,858,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -338,13 +338,13 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
|
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
|
||||||
VALUE "FileDescription", "Rufus"
|
VALUE "FileDescription", "Rufus"
|
||||||
VALUE "FileVersion", "2.7.857"
|
VALUE "FileVersion", "2.7.858"
|
||||||
VALUE "InternalName", "Rufus"
|
VALUE "InternalName", "Rufus"
|
||||||
VALUE "LegalCopyright", "© 2011-2016 Pete Batard (GPL v3)"
|
VALUE "LegalCopyright", "© 2011-2016 Pete Batard (GPL v3)"
|
||||||
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
|
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
|
||||||
VALUE "OriginalFilename", "rufus.exe"
|
VALUE "OriginalFilename", "rufus.exe"
|
||||||
VALUE "ProductName", "Rufus"
|
VALUE "ProductName", "Rufus"
|
||||||
VALUE "ProductVersion", "2.7.857"
|
VALUE "ProductVersion", "2.7.858"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
284
src/usb.c
284
src/usb.c
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Rufus: The Reliable USB Formatting Utility
|
* Rufus: The Reliable USB Formatting Utility
|
||||||
* USB device listing
|
* USB device listing
|
||||||
* Copyright © 2014 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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
|
|
||||||
extern StrArray DriveID, DriveLabel;
|
extern StrArray DriveID, DriveLabel;
|
||||||
extern BOOL enable_HDDs, use_fake_units, enable_vmdk, usb_debug;
|
extern BOOL enable_HDDs, use_fake_units, enable_vmdk, usb_debug, list_non_usb_removable_drives;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the VID, PID and current device speed
|
* Get the VID, PID and current device speed
|
||||||
|
@ -133,6 +133,17 @@ static __inline BOOL IsVHD(const char* buffer)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __inline BOOL IsRemovable(const char* buffer)
|
||||||
|
{
|
||||||
|
switch (*((DWORD*)buffer)) {
|
||||||
|
case CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVAL:
|
||||||
|
case CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL:
|
||||||
|
return TRUE;
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* For debugging user reports of HDDs vs UFDs */
|
/* For debugging user reports of HDDs vs UFDs */
|
||||||
//#define FORCED_DEVICE
|
//#define FORCED_DEVICE
|
||||||
#ifdef FORCED_DEVICE
|
#ifdef FORCED_DEVICE
|
||||||
|
@ -146,29 +157,50 @@ static __inline BOOL IsVHD(const char* buffer)
|
||||||
*/
|
*/
|
||||||
BOOL GetUSBDevices(DWORD devnum)
|
BOOL GetUSBDevices(DWORD devnum)
|
||||||
{
|
{
|
||||||
// The first two are standard Microsoft drivers (including the Windows 8 UASP one).
|
// List of USB storage drivers we know - list may be incomplete!
|
||||||
// The rest are the vendor UASP drivers I know of so far - list may be incomplete!
|
const char* usbstor_name[] = {
|
||||||
const char* storage_name[] = { "USBSTOR", "UASPSTOR", "VUSBSTOR", "ETRONSTOR", "ASUSSTPT" };
|
// Standard MS USB storage driver
|
||||||
const char* scsi_name = "SCSI";
|
"USBSTOR",
|
||||||
|
// USB card readers, with proprietary drivers (Realtek,etc...)
|
||||||
|
// Mostly "guessed" from http://www.carrona.org/dvrref.php
|
||||||
|
"RTSUER", "CMIUCR", "EUCR",
|
||||||
|
// UASP Drivers *MUST* be listed after this, starting with "UASPSTOR"
|
||||||
|
// (which is Microsoft's native UASP driver for Windows 8 and later)
|
||||||
|
// as we use "UASPSTOR" as a delimiter
|
||||||
|
"UASPSTOR", "VUSBSTOR", "ETRONSTOR", "ASUSSTPT"
|
||||||
|
};
|
||||||
|
// These are the generic (non USB) storage enumerators we also test
|
||||||
|
const char* genstor_name[] = {
|
||||||
|
// Generic storage drivers (Careful now!)
|
||||||
|
"SCSI", // "STORAGE", // "STORAGE" is used by 'Storage Spaces" and stuff => DANGEROUS!
|
||||||
|
// Non-USB card reader drivers - *MUST* start with "SD" (delimiter)
|
||||||
|
// See http://itdoc.hitachi.co.jp/manuals/3021/30213B5200e/DMDS0094.HTM
|
||||||
|
// Also http://www.carrona.org/dvrref.php. NB: These should be reported
|
||||||
|
// as enumerators by Rufus when Enum Debug is enabled
|
||||||
|
"SD", "PCISTOR", "RTSOR", "JMCR", "JMCF", "RIMMPTSK", "RIMSPTSK", "RIXDPTSK",
|
||||||
|
"TI21SONY", "ESD7SK", "ESM7SK", "O2MD", "O2SD", "VIACR"
|
||||||
|
};
|
||||||
const char* usb_speed_name[USB_SPEED_MAX] = { "USB", "USB 1.0", "USB 1.1", "USB 2.0", "USB 3.0" };
|
const char* usb_speed_name[USB_SPEED_MAX] = { "USB", "USB 1.0", "USB 1.1", "USB 2.0", "USB 3.0" };
|
||||||
// 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;
|
||||||
StrArray dev_if_path;
|
StrArray dev_if_path;
|
||||||
char letter_name[] = " (?:)";
|
char letter_name[] = " (?:)";
|
||||||
|
char drive_name[] = "?:\\";
|
||||||
char uefi_togo_check[] = "?:\\EFI\\Rufus\\ntfs_x64.efi";
|
char uefi_togo_check[] = "?:\\EFI\\Rufus\\ntfs_x64.efi";
|
||||||
BOOL r = FALSE, found = FALSE, is_SCSI, post_backslash;
|
BOOL r = FALSE, found = FALSE, post_backslash;
|
||||||
HDEVINFO dev_info = NULL;
|
HDEVINFO dev_info = NULL;
|
||||||
SP_DEVINFO_DATA dev_info_data;
|
SP_DEVINFO_DATA dev_info_data;
|
||||||
SP_DEVICE_INTERFACE_DATA devint_data;
|
SP_DEVICE_INTERFACE_DATA devint_data;
|
||||||
PSP_DEVICE_INTERFACE_DETAIL_DATA_A devint_detail_data;
|
PSP_DEVICE_INTERFACE_DETAIL_DATA_A devint_detail_data;
|
||||||
DEVINST parent_inst, grandparent_inst, device_inst;
|
DEVINST parent_inst, grandparent_inst, sibling_inst, device_inst;
|
||||||
DWORD size, i, j, k, l, datatype, drive_index;
|
DWORD size, i, j, k, l, datatype, drive_index;
|
||||||
ULONG list_size[ARRAYSIZE(storage_name)] = { 0 }, list_start[ARRAYSIZE(storage_name)] = { 0 }, full_list_size, ulFlags;
|
DWORD uasp_start = ARRAYSIZE(usbstor_name), card_start = ARRAYSIZE(genstor_name);
|
||||||
|
ULONG list_size[ARRAYSIZE(usbstor_name)] = { 0 }, list_start[ARRAYSIZE(usbstor_name)] = { 0 }, full_list_size, ulFlags;
|
||||||
HANDLE hDrive;
|
HANDLE hDrive;
|
||||||
LONG maxwidth = 0;
|
LONG maxwidth = 0;
|
||||||
int s, score, drive_number, remove_drive;
|
int s, score, drive_number, remove_drive;
|
||||||
char drive_letters[27], *device_id, *devid_list = NULL, entry_msg[128];
|
char drive_letters[27], *device_id, *devid_list = NULL, entry_msg[128];
|
||||||
char *label, *entry, buffer[MAX_PATH], str[MAX_PATH], *method_str;
|
char *p, *label, *entry, buffer[MAX_PATH], str[MAX_PATH], *method_str;
|
||||||
usb_device_props props;
|
usb_device_props props;
|
||||||
|
|
||||||
IGNORE_RETVAL(ComboBox_ResetContent(hDeviceList));
|
IGNORE_RETVAL(ComboBox_ResetContent(hDeviceList));
|
||||||
|
@ -235,29 +267,47 @@ BOOL GetUSBDevices(DWORD devnum)
|
||||||
ulFlags = CM_GETIDLIST_FILTER_SERVICE;
|
ulFlags = CM_GETIDLIST_FILTER_SERVICE;
|
||||||
if (nWindowsVersion >= WINDOWS_7)
|
if (nWindowsVersion >= WINDOWS_7)
|
||||||
ulFlags |= CM_GETIDLIST_FILTER_PRESENT;
|
ulFlags |= CM_GETIDLIST_FILTER_PRESENT;
|
||||||
for (s=0; s<ARRAYSIZE(storage_name); s++) {
|
for (s=0; s<ARRAYSIZE(usbstor_name); s++) {
|
||||||
// Get a list of device IDs for all USB storage devices
|
// Get a list of device IDs for all USB storage devices
|
||||||
// This will be used to find if a device is UASP
|
// This will be used to find if a device is UASP
|
||||||
if (CM_Get_Device_ID_List_SizeA(&list_size[s], storage_name[s], ulFlags) != CR_SUCCESS)
|
// Also compute the uasp_start index
|
||||||
|
if (strcmp(usbstor_name[s], "UASPSTOR") == 0)
|
||||||
|
uasp_start = s;
|
||||||
|
if (CM_Get_Device_ID_List_SizeA(&list_size[s], usbstor_name[s], ulFlags) != CR_SUCCESS)
|
||||||
list_size[s] = 0;
|
list_size[s] = 0;
|
||||||
if (list_size[s] != 0)
|
if (list_size[s] != 0)
|
||||||
full_list_size += list_size[s]-1; // remove extra NUL terminator
|
full_list_size += list_size[s]-1; // remove extra NUL terminator
|
||||||
}
|
}
|
||||||
|
// Compute the card_start index
|
||||||
|
for (s=0; s<ARRAYSIZE(genstor_name); s++) {
|
||||||
|
if (strcmp(genstor_name[s], "SD") == 0)
|
||||||
|
card_start = s;
|
||||||
|
}
|
||||||
|
// Overkill, but better safe than sorry. And yeah, we could have used
|
||||||
|
// arrays of arrays to avoid this, but it's more readable this way.
|
||||||
|
if ((uasp_start <= 0) || (uasp_start >= ARRAYSIZE(usbstor_name))) {
|
||||||
|
uprintf("Spock gone crazy error in %s:%d", __FILE__, __LINE__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if ((card_start <= 0) || (card_start >= ARRAYSIZE(genstor_name))) {
|
||||||
|
uprintf("Spock gone crazy error in %s:%d", __FILE__, __LINE__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
devid_list = NULL;
|
devid_list = NULL;
|
||||||
if (full_list_size != 0) {
|
if (full_list_size != 0) {
|
||||||
full_list_size += 1; // add extra NUL terminator
|
full_list_size += 1; // add extra NUL terminator
|
||||||
devid_list = (char*)malloc(full_list_size);
|
devid_list = (char*)malloc(full_list_size);
|
||||||
if (devid_list == NULL) {
|
if (devid_list == NULL) {
|
||||||
uprintf("Could not allocate Device ID list\n");
|
uprintf("Could not allocate Device ID list\n");
|
||||||
return FALSE;
|
goto out;
|
||||||
}
|
}
|
||||||
for (s=0, i=0; s<ARRAYSIZE(storage_name); s++) {
|
for (s=0, i=0; s<ARRAYSIZE(usbstor_name); s++) {
|
||||||
list_start[s] = i;
|
list_start[s] = i;
|
||||||
if (list_size[s] > 1) {
|
if (list_size[s] > 1) {
|
||||||
if (CM_Get_Device_ID_ListA(storage_name[s], &devid_list[i], list_size[s], ulFlags) != CR_SUCCESS)
|
if (CM_Get_Device_ID_ListA(usbstor_name[s], &devid_list[i], list_size[s], ulFlags) != CR_SUCCESS)
|
||||||
continue;
|
continue;
|
||||||
if (usb_debug) {
|
if (usb_debug) {
|
||||||
uprintf("Processing IDs belonging to %s:", storage_name[s]);
|
uprintf("Processing IDs belonging to '%s':", usbstor_name[s]);
|
||||||
for (device_id = &devid_list[i]; *device_id != 0; device_id += strlen(device_id) + 1)
|
for (device_id = &devid_list[i]; *device_id != 0; device_id += strlen(device_id) + 1)
|
||||||
uprintf(" %s", device_id);
|
uprintf(" %s", device_id);
|
||||||
}
|
}
|
||||||
|
@ -270,7 +320,7 @@ BOOL GetUSBDevices(DWORD devnum)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now use SetupDi to enumerate all our storage devices
|
// Now use SetupDi to enumerate all our disk storage devices
|
||||||
dev_info = SetupDiGetClassDevsA(&_GUID_DEVINTERFACE_DISK, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
|
dev_info = SetupDiGetClassDevsA(&_GUID_DEVINTERFACE_DISK, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
|
||||||
if (dev_info == INVALID_HANDLE_VALUE) {
|
if (dev_info == INVALID_HANDLE_VALUE) {
|
||||||
uprintf("SetupDiGetClassDevs (Interface) failed: %s\n", WindowsErrorString());
|
uprintf("SetupDiGetClassDevs (Interface) failed: %s\n", WindowsErrorString());
|
||||||
|
@ -279,24 +329,49 @@ BOOL GetUSBDevices(DWORD devnum)
|
||||||
dev_info_data.cbSize = sizeof(dev_info_data);
|
dev_info_data.cbSize = sizeof(dev_info_data);
|
||||||
for (i=0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) {
|
for (i=0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) {
|
||||||
memset(buffer, 0, sizeof(buffer));
|
memset(buffer, 0, sizeof(buffer));
|
||||||
|
memset(&props, 0, sizeof(props));
|
||||||
method_str = "";
|
method_str = "";
|
||||||
if (!SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_ENUMERATOR_NAME,
|
if (!SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_ENUMERATOR_NAME,
|
||||||
&datatype, (LPBYTE)buffer, sizeof(buffer), &size)) {
|
&datatype, (LPBYTE)buffer, sizeof(buffer), &size)) {
|
||||||
uprintf("SetupDiGetDeviceRegistryProperty (Enumerator Name) failed: %s\n", WindowsErrorString());
|
uprintf("SetupDiGetDeviceRegistryProperty (Enumerator Name) failed: %s\n", WindowsErrorString());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// UASP drives are listed under SCSI (along with regular SYSTEM drives => "DANGER, WILL ROBINSON!!!")
|
|
||||||
is_SCSI = (safe_stricmp(buffer, scsi_name) == 0);
|
for (j = 0; j < ARRAYSIZE(usbstor_name); j++) {
|
||||||
if ((safe_stricmp(buffer, storage_name[0]) != 0) && (!is_SCSI))
|
if (safe_stricmp(buffer, usbstor_name[0]) == 0) {
|
||||||
|
props.is_USB = TRUE;
|
||||||
|
if ((j != 0) && (j < uasp_start))
|
||||||
|
props.is_CARD = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UASP drives are listed under SCSI, and we also have non USB card readers to populate
|
||||||
|
for (j = 0; j < ARRAYSIZE(genstor_name); j++) {
|
||||||
|
if (safe_stricmp(buffer, genstor_name[j]) == 0) {
|
||||||
|
props.is_SCSI = TRUE;
|
||||||
|
if (j >= card_start)
|
||||||
|
props.is_CARD = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uuprintf("Processing '%s' device:", buffer);
|
||||||
|
if ((!props.is_USB) && (!props.is_SCSI)) {
|
||||||
|
uuprintf(" Disabled by policy");
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// We can't use the friendly name to find if a drive is a VHD, as friendly name string gets translated
|
// We can't use the friendly name to find if a drive is a VHD, as friendly name string gets translated
|
||||||
// according to your locale, so we poke the Hardware ID
|
// according to your locale, so we poke the Hardware ID
|
||||||
memset(&props, 0, sizeof(props));
|
|
||||||
memset(buffer, 0, sizeof(buffer));
|
memset(buffer, 0, sizeof(buffer));
|
||||||
props.is_VHD = SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_HARDWAREID,
|
props.is_VHD = SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_HARDWAREID,
|
||||||
&datatype, (LPBYTE)buffer, sizeof(buffer), &size) && IsVHD(buffer);
|
&datatype, (LPBYTE)buffer, sizeof(buffer), &size) && IsVHD(buffer);
|
||||||
uuprintf("Processing Device: '%s'", buffer);
|
uuprintf(" Hardware ID: '%s'", buffer);
|
||||||
|
|
||||||
|
memset(buffer, 0, sizeof(buffer));
|
||||||
|
props.is_Removable = SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_REMOVAL_POLICY,
|
||||||
|
&datatype, (LPBYTE)buffer, sizeof(buffer), &size) && IsRemovable(buffer);
|
||||||
|
|
||||||
memset(buffer, 0, sizeof(buffer));
|
memset(buffer, 0, sizeof(buffer));
|
||||||
if (!SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_FRIENDLYNAME,
|
if (!SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_FRIENDLYNAME,
|
||||||
|
@ -307,72 +382,92 @@ BOOL GetUSBDevices(DWORD devnum)
|
||||||
} else if ((!props.is_VHD) && (devid_list != NULL)) {
|
} else if ((!props.is_VHD) && (devid_list != NULL)) {
|
||||||
// Get the properties of the device. We could avoid doing this lookup every time by keeping
|
// Get the properties of the device. We could avoid doing this lookup every time by keeping
|
||||||
// a lookup table, but there shouldn't be that many USB storage devices connected...
|
// a lookup table, but there shouldn't be that many USB storage devices connected...
|
||||||
// NB: Each of these Device IDs have an _only_ child, from which we get the Device Instance match.
|
// NB: Each of these Device IDs should have a child, from which we get the Device Instance match.
|
||||||
for (device_id = devid_list; *device_id != 0; device_id += strlen(device_id) + 1) {
|
for (device_id = devid_list; *device_id != 0; device_id += strlen(device_id) + 1) {
|
||||||
if ( (CM_Locate_DevNodeA(&parent_inst, device_id, 0) == CR_SUCCESS)
|
if (CM_Locate_DevNodeA(&parent_inst, device_id, 0) != CR_SUCCESS) {
|
||||||
&& (CM_Get_Child(&device_inst, parent_inst, 0) == CR_SUCCESS)
|
uuprintf("Could not locate device node for '%s'", device_id);
|
||||||
&& (device_inst == dev_info_data.DevInst) ) {
|
continue;
|
||||||
post_backslash = FALSE;
|
}
|
||||||
method_str = "";
|
if (CM_Get_Child(&device_inst, parent_inst, 0) != CR_SUCCESS) {
|
||||||
|
uuprintf("Could not get children of '%s'", device_id);
|
||||||
// If we're not dealing with the USBSTOR part of our list, then this is an UASP device
|
continue;
|
||||||
props.is_UASP = ((((uintptr_t)device_id)+2) >= ((uintptr_t)devid_list)+list_start[1]);
|
}
|
||||||
// Now get the properties of the device, and its Device ID, which we need to populate the properties
|
if (device_inst != dev_info_data.DevInst) {
|
||||||
j = htab_hash(device_id, &htab_devid);
|
// Try the siblings
|
||||||
uuprintf(" Matched with ID[%03d]: %s", j, device_id);
|
while (CM_Get_Sibling(&sibling_inst, device_inst, 0) == CR_SUCCESS) {
|
||||||
|
if (sibling_inst == dev_info_data.DevInst) {
|
||||||
// Try to parse the current device_id string for VID:PID
|
uuprintf("NOTE: Matched instance from sibling for '%s'", device_id);
|
||||||
// We'll use that if we can't get anything better
|
device_inst = sibling_inst;
|
||||||
for (k = 0, l = 0; (k<strlen(device_id)) && (l<2); k++) {
|
break;
|
||||||
// The ID is in the form USB_VENDOR_BUSID\VID_xxxx&PID_xxxx\...
|
|
||||||
if (device_id[k] == '\\')
|
|
||||||
post_backslash = TRUE;
|
|
||||||
if (!post_backslash)
|
|
||||||
continue;
|
|
||||||
if (device_id[k] == '_') {
|
|
||||||
props.pid = (uint16_t)strtoul(&device_id[k + 1], NULL, 16);
|
|
||||||
if (l++ == 0)
|
|
||||||
props.vid = props.pid;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (props.vid != 0)
|
if (device_inst != dev_info_data.DevInst)
|
||||||
method_str = "[ID]";
|
continue;
|
||||||
|
|
||||||
// If the hash didn't match a populated string in dev_if_path[] (htab_devid.table[j].data > 0),
|
|
||||||
// we might have an extra vendor driver in between (e.g. "ASUS USB 3.0 Boost Storage Driver"
|
|
||||||
// for UASP devices in ASUS "Turbo Mode" or "Apple Mobile Device USB Driver" for iPods)
|
|
||||||
// so try to see if we can match the grandparent.
|
|
||||||
if ( ((uintptr_t)htab_devid.table[j].data == 0)
|
|
||||||
&& (CM_Get_Parent(&grandparent_inst, parent_inst, 0) == CR_SUCCESS)
|
|
||||||
&& (CM_Get_Device_IDA(grandparent_inst, str, MAX_PATH, 0) == CR_SUCCESS) ) {
|
|
||||||
device_id = str;
|
|
||||||
method_str = "[GP]";
|
|
||||||
j = htab_hash(device_id, &htab_devid);
|
|
||||||
uuprintf(" Matched with (GP) ID[%03d]: %s", j, device_id);
|
|
||||||
}
|
|
||||||
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))
|
|
||||||
method_str = "";
|
|
||||||
#ifdef FORCED_DEVICE
|
|
||||||
props.vid = FORCED_VID;
|
|
||||||
props.pid = FORCED_PID;
|
|
||||||
safe_strcpy(buffer, sizeof(buffer), FORCED_NAME);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
post_backslash = FALSE;
|
||||||
|
method_str = "";
|
||||||
|
|
||||||
|
// If we're not dealing with the USBSTOR part of our list, then this is an UASP device
|
||||||
|
props.is_UASP = ((((uintptr_t)device_id)+2) >= ((uintptr_t)devid_list)+list_start[uasp_start]);
|
||||||
|
// Now get the properties of the device, and its Device ID, which we need to populate the properties
|
||||||
|
j = htab_hash(device_id, &htab_devid);
|
||||||
|
uuprintf(" Matched with ID[%03d]: %s", j, device_id);
|
||||||
|
|
||||||
|
// Try to parse the current device_id string for VID:PID
|
||||||
|
// We'll use that if we can't get anything better
|
||||||
|
for (k = 0, l = 0; (k<strlen(device_id)) && (l<2); k++) {
|
||||||
|
// The ID is in the form USB_VENDOR_BUSID\VID_xxxx&PID_xxxx\...
|
||||||
|
if (device_id[k] == '\\')
|
||||||
|
post_backslash = TRUE;
|
||||||
|
if (!post_backslash)
|
||||||
|
continue;
|
||||||
|
if (device_id[k] == '_') {
|
||||||
|
props.pid = (uint16_t)strtoul(&device_id[k + 1], NULL, 16);
|
||||||
|
if (l++ == 0)
|
||||||
|
props.vid = props.pid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (props.vid != 0)
|
||||||
|
method_str = "[ID]";
|
||||||
|
|
||||||
|
// If the hash didn't match a populated string in dev_if_path[] (htab_devid.table[j].data > 0),
|
||||||
|
// we might have an extra vendor driver in between (e.g. "ASUS USB 3.0 Boost Storage Driver"
|
||||||
|
// for UASP devices in ASUS "Turbo Mode" or "Apple Mobile Device USB Driver" for iPods)
|
||||||
|
// so try to see if we can match the grandparent.
|
||||||
|
if ( ((uintptr_t)htab_devid.table[j].data == 0)
|
||||||
|
&& (CM_Get_Parent(&grandparent_inst, parent_inst, 0) == CR_SUCCESS)
|
||||||
|
&& (CM_Get_Device_IDA(grandparent_inst, str, MAX_PATH, 0) == CR_SUCCESS) ) {
|
||||||
|
device_id = str;
|
||||||
|
method_str = "[GP]";
|
||||||
|
j = htab_hash(device_id, &htab_devid);
|
||||||
|
uuprintf(" Matched with (GP) ID[%03d]: %s", j, device_id);
|
||||||
|
}
|
||||||
|
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))
|
||||||
|
method_str = "";
|
||||||
|
#ifdef FORCED_DEVICE
|
||||||
|
props.vid = FORCED_VID;
|
||||||
|
props.pid = FORCED_PID;
|
||||||
|
safe_strcpy(buffer, sizeof(buffer), FORCED_NAME);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (props.is_VHD) {
|
if (props.is_VHD) {
|
||||||
uprintf("Found VHD device '%s'", buffer);
|
uprintf("Found VHD device '%s'", buffer);
|
||||||
|
} else if ((props.is_CARD) && ((!props.is_USB) || ((props.vid == 0) && (props.pid == 0)))) {
|
||||||
|
uprintf("Found card reader device '%s'", buffer);
|
||||||
|
} else if ((!props.is_USB) && (props.is_Removable) && (!props.is_UASP)) {
|
||||||
|
uprintf("Found non-USB removable device '%s'", buffer);
|
||||||
} else {
|
} else {
|
||||||
if ((props.vid == 0) && (props.pid == 0)) {
|
if ((props.vid == 0) && (props.pid == 0)) {
|
||||||
if (is_SCSI) {
|
if (!props.is_USB) {
|
||||||
// If we have an SCSI drive and couldn't get a VID:PID, we are most likely
|
// If we have a non removable SCSI drive and couldn't get a VID:PID,
|
||||||
// dealing with a system drive => eliminate it!
|
// we are most likely dealing with a system drive => eliminate it!
|
||||||
uuprintf(" Non USB => Eliminated");
|
uuprintf(" Non-USB or non-removable => Eliminated");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
safe_strcpy(str, sizeof(str), "????:????"); // Couldn't figure VID:PID
|
safe_strcpy(str, sizeof(str), "????:????"); // Couldn't figure VID:PID
|
||||||
|
@ -444,11 +539,36 @@ BOOL GetUSBDevices(DWORD devnum)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetDriveLabel(drive_index, drive_letters, &label)) {
|
if (GetDriveLabel(drive_index, drive_letters, &label)) {
|
||||||
if ((!enable_HDDs) && (!props.is_VHD) &&
|
if ((props.is_SCSI) && (!props.is_UASP) && (!props.is_VHD)) {
|
||||||
|
if (!props.is_Removable) {
|
||||||
|
// Non removables should have been eliminated above, but since we
|
||||||
|
// are potentially dealing with system drives, better safe than sorry
|
||||||
|
safe_closehandle(hDrive);
|
||||||
|
safe_free(devint_detail_data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!list_non_usb_removable_drives) {
|
||||||
|
// Go over the mounted partitions and find if GetDriveType() says they are
|
||||||
|
// removable. If they are not removable, don't allow the drive to be listed
|
||||||
|
for (p = drive_letters; *p; p++) {
|
||||||
|
drive_name[0] = *p;
|
||||||
|
if (GetDriveTypeA(drive_name) != DRIVE_REMOVABLE)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (*p) {
|
||||||
|
uprintf("Device eliminated because it contains a mounted partition that is set as non-removable");
|
||||||
|
safe_closehandle(hDrive);
|
||||||
|
safe_free(devint_detail_data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((!enable_HDDs) && (!props.is_VHD) && (!props.is_CARD) &&
|
||||||
((score = IsHDD(drive_index, (uint16_t)props.vid, (uint16_t)props.pid, buffer)) > 0)) {
|
((score = IsHDD(drive_index, (uint16_t)props.vid, (uint16_t)props.pid, buffer)) > 0)) {
|
||||||
uprintf("Device eliminated because it was detected as an USB Hard Drive (score %d > 0)\n", score);
|
uprintf("Device eliminated because it was detected as a Hard Drive (score %d > 0)", score);
|
||||||
uprintf("If this device is not an USB Hard Drive, please e-mail the author of this application\n");
|
if (!list_non_usb_removable_drives)
|
||||||
uprintf("NOTE: You can enable the listing of USB Hard Drives in 'Advanced Options' (after clicking the white triangle)");
|
uprintf("If this device is not a Hard Drive, please e-mail the author of this application");
|
||||||
|
uprintf("NOTE: You can enable the listing of Hard Drives in 'Advanced Options' (after clicking the white triangle)");
|
||||||
safe_closehandle(hDrive);
|
safe_closehandle(hDrive);
|
||||||
safe_free(devint_detail_data);
|
safe_free(devint_detail_data);
|
||||||
break;
|
break;
|
||||||
|
|
19
src/usb.h
19
src/usb.h
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Rufus: The Reliable USB Formatting Utility
|
* Rufus: The Reliable USB Formatting Utility
|
||||||
* USB device listing
|
* USB device listing
|
||||||
* Copyright © 2014 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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -32,8 +32,12 @@ typedef struct usb_device_props {
|
||||||
uint32_t pid;
|
uint32_t pid;
|
||||||
uint32_t speed;
|
uint32_t speed;
|
||||||
uint32_t port;
|
uint32_t port;
|
||||||
|
BOOLEAN is_USB;
|
||||||
|
BOOLEAN is_SCSI;
|
||||||
|
BOOLEAN is_CARD;
|
||||||
BOOLEAN is_UASP;
|
BOOLEAN is_UASP;
|
||||||
BOOLEAN is_VHD;
|
BOOLEAN is_VHD;
|
||||||
|
BOOLEAN is_Removable;
|
||||||
BOOLEAN is_LowerSpeed;
|
BOOLEAN is_LowerSpeed;
|
||||||
} usb_device_props;
|
} usb_device_props;
|
||||||
|
|
||||||
|
@ -46,12 +50,15 @@ typedef DWORD RETURN_TYPE;
|
||||||
typedef RETURN_TYPE CONFIGRET;
|
typedef RETURN_TYPE CONFIGRET;
|
||||||
typedef CHAR *DEVINSTID_A;
|
typedef CHAR *DEVINSTID_A;
|
||||||
|
|
||||||
#define CR_SUCCESS 0x00000000
|
#define CR_SUCCESS 0x00000000
|
||||||
#define CR_NO_SUCH_DEVNODE 0x0000000D
|
#define CR_NO_SUCH_DEVNODE 0x0000000D
|
||||||
#define CM_GETIDLIST_FILTER_SERVICE 0x00000002
|
#define CM_GETIDLIST_FILTER_SERVICE 0x00000002
|
||||||
|
#define CM_REMOVAL_POLICY_EXPECT_NO_REMOVAL 0x00000001
|
||||||
|
#define CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL 0x00000002
|
||||||
|
#define CM_REMOVAL_POLICY_EXPECT_SURPRISE_REMOVAL 0x00000003
|
||||||
// /!\ The following flag is only available on Windows 7 or later!
|
// /!\ The following flag is only available on Windows 7 or later!
|
||||||
#define CM_GETIDLIST_FILTER_PRESENT 0x00000100
|
#define CM_GETIDLIST_FILTER_PRESENT 0x00000100
|
||||||
#define CM_DRP_ADDRESS 0x0000001D
|
#define CM_DRP_ADDRESS 0x0000001D
|
||||||
|
|
||||||
#ifndef METHOD_BUFFERED
|
#ifndef METHOD_BUFFERED
|
||||||
#define METHOD_BUFFERED 0
|
#define METHOD_BUFFERED 0
|
||||||
|
|
Loading…
Reference in a new issue