[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:
Pete Batard 2016-02-16 17:47:07 +00:00
parent 58755c1bc4
commit f88faf1a4f
6 changed files with 248 additions and 100 deletions

View File

@ -395,10 +395,10 @@ static BOOL _GetDriveLettersAndType(DWORD DriveIndex, char* drive_letters, UINT*
continue;
}
/* 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
value there => Use GetDriveType() to filter out unwanted devices.
See https://github.com/pbatard/rufus/issues/32 for details. */
// 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
// value there => Use GetDriveType() to filter out unwanted devices.
// See https://github.com/pbatard/rufus/issues/32#issuecomment-3785956
_drive_type = GetDriveTypeA(drive);
if ((_drive_type != DRIVE_REMOVABLE) && (_drive_type != DRIVE_FIXED))

View File

@ -1883,7 +1883,7 @@ DWORD WINAPI FormatThread(void* param)
} else if (tt == TT_UEFI) {
// For once, no need to do anything - just check our sanity
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;
goto out;
}

View File

@ -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 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 zero_drive = FALSE;
BOOL zero_drive = FALSE, list_non_usb_removable_drives = FALSE;
int dialog_showing = 0, lang_button_id = 0;
uint16_t rufus_version[3], embedded_sl_version[2];
char embedded_sl_version_str[2][12] = { "?.??", "?.??" };
@ -1762,7 +1762,7 @@ void InitDialog(HWND hDlg)
if (selected_locale->ctrl_id & LOC_NEEDS_UPDATE) {
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]);
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();
@ -2826,6 +2826,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
int wait_for_mutex = 0;
FILE* fd;
BOOL attached_console = FALSE, external_loc_file = FALSE, lgp_set = FALSE, automount, disable_hogger = FALSE;
BOOL previous_enable_HDDs = FALSE;
BYTE *loc_data;
DWORD loc_size, size;
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);
}
// 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)
if (!IsDialogMessage(hDlg, &msg) && !IsDialogMessage(hLogDlg, &msg)) {
TranslateMessage(&msg);

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.7.857"
CAPTION "Rufus 2.7.858"
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,7,857,0
PRODUCTVERSION 2,7,857,0
FILEVERSION 2,7,858,0
PRODUCTVERSION 2,7,858,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.7.857"
VALUE "FileVersion", "2.7.858"
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.7.857"
VALUE "ProductVersion", "2.7.858"
END
END
BLOCK "VarFileInfo"

284
src/usb.c
View File

@ -1,7 +1,7 @@
/*
* Rufus: The Reliable USB Formatting Utility
* 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
* it under the terms of the GNU General Public License as published by
@ -41,7 +41,7 @@
#include "usb.h"
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
@ -133,6 +133,17 @@ static __inline BOOL IsVHD(const char* buffer)
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 */
//#define FORCED_DEVICE
#ifdef FORCED_DEVICE
@ -146,29 +157,50 @@ static __inline BOOL IsVHD(const char* buffer)
*/
BOOL GetUSBDevices(DWORD devnum)
{
// The first two are standard Microsoft drivers (including the Windows 8 UASP one).
// The rest are the vendor UASP drivers I know of so far - list may be incomplete!
const char* storage_name[] = { "USBSTOR", "UASPSTOR", "VUSBSTOR", "ETRONSTOR", "ASUSSTPT" };
const char* scsi_name = "SCSI";
// List of USB storage drivers we know - list may be incomplete!
const char* usbstor_name[] = {
// Standard MS USB storage driver
"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" };
// 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;
StrArray dev_if_path;
char letter_name[] = " (?:)";
char drive_name[] = "?:\\";
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;
SP_DEVINFO_DATA dev_info_data;
SP_DEVICE_INTERFACE_DATA devint_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;
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;
LONG maxwidth = 0;
int s, score, drive_number, remove_drive;
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;
IGNORE_RETVAL(ComboBox_ResetContent(hDeviceList));
@ -235,29 +267,47 @@ BOOL GetUSBDevices(DWORD devnum)
ulFlags = CM_GETIDLIST_FILTER_SERVICE;
if (nWindowsVersion >= WINDOWS_7)
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
// 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;
if (list_size[s] != 0)
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;
if (full_list_size != 0) {
full_list_size += 1; // add extra NUL terminator
devid_list = (char*)malloc(full_list_size);
if (devid_list == NULL) {
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;
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;
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)
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);
if (dev_info == INVALID_HANDLE_VALUE) {
uprintf("SetupDiGetClassDevs (Interface) failed: %s\n", WindowsErrorString());
@ -279,24 +329,49 @@ BOOL GetUSBDevices(DWORD devnum)
dev_info_data.cbSize = sizeof(dev_info_data);
for (i=0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) {
memset(buffer, 0, sizeof(buffer));
memset(&props, 0, sizeof(props));
method_str = "";
if (!SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_ENUMERATOR_NAME,
&datatype, (LPBYTE)buffer, sizeof(buffer), &size)) {
uprintf("SetupDiGetDeviceRegistryProperty (Enumerator Name) failed: %s\n", WindowsErrorString());
continue;
}
// UASP drives are listed under SCSI (along with regular SYSTEM drives => "DANGER, WILL ROBINSON!!!")
is_SCSI = (safe_stricmp(buffer, scsi_name) == 0);
if ((safe_stricmp(buffer, storage_name[0]) != 0) && (!is_SCSI))
for (j = 0; j < ARRAYSIZE(usbstor_name); j++) {
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;
}
// 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
memset(&props, 0, sizeof(props));
memset(buffer, 0, sizeof(buffer));
props.is_VHD = SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_HARDWAREID,
&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));
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)) {
// 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...
// 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) {
if ( (CM_Locate_DevNodeA(&parent_inst, device_id, 0) == CR_SUCCESS)
&& (CM_Get_Child(&device_inst, parent_inst, 0) == CR_SUCCESS)
&& (device_inst == dev_info_data.DevInst) ) {
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[1]);
// 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 (CM_Locate_DevNodeA(&parent_inst, device_id, 0) != CR_SUCCESS) {
uuprintf("Could not locate device node for '%s'", device_id);
continue;
}
if (CM_Get_Child(&device_inst, parent_inst, 0) != CR_SUCCESS) {
uuprintf("Could not get children of '%s'", device_id);
continue;
}
if (device_inst != dev_info_data.DevInst) {
// Try the siblings
while (CM_Get_Sibling(&sibling_inst, device_inst, 0) == CR_SUCCESS) {
if (sibling_inst == dev_info_data.DevInst) {
uuprintf("NOTE: Matched instance from sibling for '%s'", device_id);
device_inst = sibling_inst;
break;
}
}
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 (device_inst != dev_info_data.DevInst)
continue;
}
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) {
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 {
if ((props.vid == 0) && (props.pid == 0)) {
if (is_SCSI) {
// If we have an SCSI drive and couldn't get a VID:PID, we are most likely
// dealing with a system drive => eliminate it!
uuprintf(" Non USB => Eliminated");
if (!props.is_USB) {
// If we have a non removable SCSI drive and couldn't get a VID:PID,
// we are most likely dealing with a system drive => eliminate it!
uuprintf(" Non-USB or non-removable => Eliminated");
continue;
}
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 ((!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)) {
uprintf("Device eliminated because it was detected as an USB Hard Drive (score %d > 0)\n", score);
uprintf("If this device is not an USB Hard Drive, please e-mail the author of this application\n");
uprintf("NOTE: You can enable the listing of USB Hard Drives in 'Advanced Options' (after clicking the white triangle)");
uprintf("Device eliminated because it was detected as a Hard Drive (score %d > 0)", score);
if (!list_non_usb_removable_drives)
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_free(devint_detail_data);
break;

View File

@ -1,7 +1,7 @@
/*
* Rufus: The Reliable USB Formatting Utility
* 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
* 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 speed;
uint32_t port;
BOOLEAN is_USB;
BOOLEAN is_SCSI;
BOOLEAN is_CARD;
BOOLEAN is_UASP;
BOOLEAN is_VHD;
BOOLEAN is_Removable;
BOOLEAN is_LowerSpeed;
} usb_device_props;
@ -46,12 +50,15 @@ typedef DWORD RETURN_TYPE;
typedef RETURN_TYPE CONFIGRET;
typedef CHAR *DEVINSTID_A;
#define CR_SUCCESS 0x00000000
#define CR_NO_SUCH_DEVNODE 0x0000000D
#define CM_GETIDLIST_FILTER_SERVICE 0x00000002
#define CR_SUCCESS 0x00000000
#define CR_NO_SUCH_DEVNODE 0x0000000D
#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!
#define CM_GETIDLIST_FILTER_PRESENT 0x00000100
#define CM_DRP_ADDRESS 0x0000001D
#define CM_GETIDLIST_FILTER_PRESENT 0x00000100
#define CM_DRP_ADDRESS 0x0000001D
#ifndef METHOD_BUFFERED
#define METHOD_BUFFERED 0