From f88faf1a4f74dca1c88e2324acb041b094b0f999 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Tue, 16 Feb 2016 17:47:07 +0000 Subject: [PATCH] [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 --- src/drive.c | 8 +- src/format.c | 2 +- src/rufus.c | 25 ++++- src/rufus.rc | 10 +- src/usb.c | 284 ++++++++++++++++++++++++++++++++++++--------------- src/usb.h | 19 ++-- 6 files changed, 248 insertions(+), 100 deletions(-) diff --git a/src/drive.c b/src/drive.c index 0e6c3711..65980555 100644 --- a/src/drive.c +++ b/src/drive.c @@ -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)) diff --git a/src/format.c b/src/format.c index b70d8e9c..0c2c8487 100644 --- a/src/format.c +++ b/src/format.c @@ -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; } diff --git a/src/rufus.c b/src/rufus.c index 28811b82..377449e9 100644 --- a/src/rufus.c +++ b/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 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 ."); + 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); diff --git a/src/rufus.rc b/src/rufus.rc index 58e94ab3..4e650db2 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -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" diff --git a/src/usb.c b/src/usb.c index 8954d23b..acf0246c 100644 --- a/src/usb.c +++ b/src/usb.c @@ -1,7 +1,7 @@ /* * Rufus: The Reliable USB Formatting Utility * USB device listing - * Copyright © 2014 Pete Batard + * Copyright © 2014-2016 Pete Batard * * 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(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 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 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 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; diff --git a/src/usb.h b/src/usb.h index ece838b7..d67e018c 100644 --- a/src/usb.h +++ b/src/usb.h @@ -1,7 +1,7 @@ /* * Rufus: The Reliable USB Formatting Utility * USB device listing - * Copyright © 2014 Pete Batard + * Copyright © 2014-2016 Pete Batard * * 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