mirror of
https://github.com/pbatard/rufus.git
synced 2025-05-28 13:44:15 -04:00
[core] report detected USB device speed
* Yes, it takes about all of the changes below, to basically add 3 extra characters in the log... That's Microsoft Windows for you, baby! * Closes #314
This commit is contained in:
parent
4026083da8
commit
c85670f7b7
13 changed files with 847 additions and 471 deletions
265
src/rufus.c
265
src/rufus.c
|
@ -28,8 +28,6 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <commctrl.h>
|
||||
#include <setupapi.h>
|
||||
#include <winioctl.h>
|
||||
#include <shlobj.h>
|
||||
#include <process.h>
|
||||
|
@ -128,12 +126,12 @@ int dialog_showing = 0;
|
|||
uint16_t rufus_version[4], embedded_sl_version[2];
|
||||
char embedded_sl_version_str[2][12] = { "?.??", "?.??" };
|
||||
RUFUS_UPDATE update = { {0,0,0,0}, {0,0}, NULL, NULL};
|
||||
StrArray DriveID, DriveLabel;
|
||||
extern char szStatusMessage[256];
|
||||
|
||||
static HANDLE format_thid = NULL;
|
||||
static HWND hProgress = NULL, hBoot = NULL, hSelectISO = NULL;
|
||||
static HICON hIconDisc, hIconDown, hIconUp, hIconLang;
|
||||
static StrArray DriveID, DriveLabel;
|
||||
static char szTimer[12] = "00:00:00";
|
||||
static unsigned int timer;
|
||||
static int64_t last_iso_blocking_status;
|
||||
|
@ -609,267 +607,6 @@ static BOOL PopulateProperties(int ComboIndex)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Refresh the list of USB devices
|
||||
*/
|
||||
static 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" };
|
||||
const char* scsi_name = "SCSI";
|
||||
const char* vhd_name = "Virtual Disk";
|
||||
char letter_name[] = " (?:)";
|
||||
BOOL found = FALSE, is_SCSI, is_UASP, is_VHD;
|
||||
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, device_inst;
|
||||
DWORD size, i, j, k, datatype, drive_index;
|
||||
ULONG list_size[ARRAYSIZE(storage_name)], full_list_size;
|
||||
HANDLE hDrive;
|
||||
LONG maxwidth = 0;
|
||||
RECT rect;
|
||||
int s, score, drive_number;
|
||||
char drive_letters[27], *devid, *devid_list = NULL, entry_msg[128];
|
||||
char *label, *entry, buffer[MAX_PATH], str[sizeof("0000:0000")+1];
|
||||
uint16_t vid, pid;
|
||||
GUID _GUID_DEVINTERFACE_DISK = // only known to some...
|
||||
{ 0x53f56307L, 0xb6bf, 0x11d0, {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b} };
|
||||
|
||||
IGNORE_RETVAL(ComboBox_ResetContent(hDeviceList));
|
||||
StrArrayClear(&DriveID);
|
||||
StrArrayClear(&DriveLabel);
|
||||
GetClientRect(hDeviceList, &rect);
|
||||
|
||||
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());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
full_list_size = 0;
|
||||
for (s=0; s<ARRAYSIZE(storage_name); s++) {
|
||||
// Get a list of hardware IDs for all USB storage devices
|
||||
// This will be used to retrieve the VID:PID of our devices
|
||||
CM_Get_Device_ID_List_SizeA(&list_size[s], storage_name[s], CM_GETIDLIST_FILTER_SERVICE);
|
||||
if (list_size[s] != 0)
|
||||
full_list_size += list_size[s]-1; // remove extra NUL terminator
|
||||
}
|
||||
full_list_size += 1; // add extra NUL terminator
|
||||
if (full_list_size < 2)
|
||||
return FALSE;
|
||||
devid_list = (char*)malloc(full_list_size);
|
||||
if (devid_list == NULL) {
|
||||
uprintf("Could not allocate Dev ID list\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Build a single list from all the storage enumerators we know of
|
||||
for (s=0, i=0; s<ARRAYSIZE(storage_name); s++) {
|
||||
if (list_size[s] > 1) {
|
||||
CM_Get_Device_ID_ListA(storage_name[s], &devid_list[i], list_size[s], CM_GETIDLIST_FILTER_SERVICE);
|
||||
// list_size is sometimes larger than required thus we need to find the real end
|
||||
for (i += list_size[s]; i > 2; i--) {
|
||||
if ((devid_list[i-2] != '\0') && (devid_list[i-1] == '\0') && (devid_list[i] == '\0'))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dev_info_data.cbSize = sizeof(dev_info_data);
|
||||
for (i=0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) {
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
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))
|
||||
continue;
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
vid = 0; pid = 0;
|
||||
is_UASP = FALSE, is_VHD = FALSE;
|
||||
if (!SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_FRIENDLYNAME,
|
||||
&datatype, (LPBYTE)buffer, sizeof(buffer), &size)) {
|
||||
uprintf("SetupDiGetDeviceRegistryProperty (Friendly Name) failed: %s\n", WindowsErrorString());
|
||||
// We can afford a failure on this call - just replace the name with "USB Storage Device (Generic)"
|
||||
safe_strcpy(buffer, sizeof(buffer), lmprintf(MSG_045));
|
||||
} else if (safe_strstr(buffer, vhd_name) != NULL) {
|
||||
is_VHD = TRUE;
|
||||
} else {
|
||||
// Get the VID:PID 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...
|
||||
for (devid = devid_list; *devid; devid += strlen(devid) + 1) {
|
||||
if ( (CM_Locate_DevNodeA(&parent_inst, devid, 0) == 0)
|
||||
&& (CM_Get_Child(&device_inst, parent_inst, 0) == 0)
|
||||
&& (device_inst == dev_info_data.DevInst) ) {
|
||||
BOOL post_backslash = FALSE;
|
||||
// If we're not dealing with the USBSTOR part of our list, then this is an UASP device
|
||||
is_UASP = ((((uintptr_t)devid)+2) >= ((uintptr_t)devid_list)+list_size[0]);
|
||||
for (j=0, k=0; (j<strlen(devid))&&(k<2); j++) {
|
||||
// The ID is in the form USB_VENDOR_BUSID\VID_xxxx&PID_xxxx\...
|
||||
if (devid[j] == '\\')
|
||||
post_backslash = TRUE;
|
||||
if (!post_backslash)
|
||||
continue;
|
||||
if (devid[j] == '_') {
|
||||
pid = (uint16_t)strtoul(&devid[j+1], NULL, 16);
|
||||
// We could have used a vid_pid[] table, but keeping vid/pid separate is clearer
|
||||
if (k++==0) vid = pid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_VHD) {
|
||||
uprintf("Found VHD device '%s'\n", buffer);
|
||||
} else {
|
||||
if ((vid == 0) && (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!
|
||||
continue;
|
||||
}
|
||||
safe_strcpy(str, sizeof(str), "????:????"); // Couldn't figure VID:PID
|
||||
} else {
|
||||
safe_sprintf(str, sizeof(str), "%04X:%04X", vid, pid);
|
||||
}
|
||||
uprintf("Found %s device '%s' (%s)\n", is_UASP?"UAS":"USB", buffer, str);
|
||||
}
|
||||
devint_data.cbSize = sizeof(devint_data);
|
||||
hDrive = INVALID_HANDLE_VALUE;
|
||||
devint_detail_data = NULL;
|
||||
for (j=0; ;j++) {
|
||||
safe_closehandle(hDrive);
|
||||
safe_free(devint_detail_data);
|
||||
|
||||
if (!SetupDiEnumDeviceInterfaces(dev_info, &dev_info_data, &_GUID_DEVINTERFACE_DISK, j, &devint_data)) {
|
||||
if(GetLastError() != ERROR_NO_MORE_ITEMS) {
|
||||
uprintf("SetupDiEnumDeviceInterfaces failed: %s\n", WindowsErrorString());
|
||||
} else {
|
||||
uprintf("A device was eliminated because it didn't report itself as a disk\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!SetupDiGetDeviceInterfaceDetailA(dev_info, &devint_data, NULL, 0, &size, NULL)) {
|
||||
if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
||||
devint_detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)calloc(1, size);
|
||||
if (devint_detail_data == NULL) {
|
||||
uprintf("Unable to allocate data for SP_DEVICE_INTERFACE_DETAIL_DATA\n");
|
||||
continue;
|
||||
}
|
||||
devint_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
|
||||
} else {
|
||||
uprintf("SetupDiGetDeviceInterfaceDetail (dummy) failed: %s\n", WindowsErrorString());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (devint_detail_data == NULL) {
|
||||
uprintf("SetupDiGetDeviceInterfaceDetail (dummy) - no data was allocated\n");
|
||||
continue;
|
||||
}
|
||||
if(!SetupDiGetDeviceInterfaceDetailA(dev_info, &devint_data, devint_detail_data, size, &size, NULL)) {
|
||||
uprintf("SetupDiGetDeviceInterfaceDetail (actual) failed: %s\n", WindowsErrorString());
|
||||
continue;
|
||||
}
|
||||
|
||||
hDrive = CreateFileA(devint_detail_data->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if(hDrive == INVALID_HANDLE_VALUE) {
|
||||
uprintf("Could not open '%s': %s\n", devint_detail_data->DevicePath, WindowsErrorString());
|
||||
continue;
|
||||
}
|
||||
|
||||
drive_number = GetDriveNumber(hDrive, devint_detail_data->DevicePath);
|
||||
if (drive_number < 0)
|
||||
continue;
|
||||
|
||||
drive_index = drive_number + DRIVE_INDEX_MIN;
|
||||
if (!IsMediaPresent(drive_index)) {
|
||||
uprintf("Device eliminated because it appears to contain no media\n");
|
||||
safe_closehandle(hDrive);
|
||||
safe_free(devint_detail_data);
|
||||
break;
|
||||
}
|
||||
|
||||
if (GetDriveLabel(drive_index, drive_letters, &label)) {
|
||||
if ((!enable_HDDs) && (!is_VHD) && ((score = IsHDD(drive_index, vid, 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)");
|
||||
safe_closehandle(hDrive);
|
||||
safe_free(devint_detail_data);
|
||||
break;
|
||||
}
|
||||
|
||||
// The empty string is returned for drives that don't have any volumes assigned
|
||||
if (drive_letters[0] == 0) {
|
||||
entry = lmprintf(MSG_046, label, drive_number,
|
||||
SizeToHumanReadable(GetDriveSize(drive_index), FALSE, use_fake_units));
|
||||
} else {
|
||||
// We have multiple volumes assigned to the same device (multiple partitions)
|
||||
// If that is the case, use "Multiple Volumes" instead of the label
|
||||
safe_strcpy(entry_msg, sizeof(entry_msg), ((drive_letters[0] != 0) && (drive_letters[1] != 0))?
|
||||
lmprintf(MSG_047):label);
|
||||
for (k=0; drive_letters[k]; k++) {
|
||||
// Append all the drive letters we detected
|
||||
letter_name[2] = drive_letters[k];
|
||||
if (right_to_left_mode)
|
||||
safe_strcat(entry_msg, sizeof(entry_msg), RIGHT_TO_LEFT_MARK);
|
||||
safe_strcat(entry_msg, sizeof(entry_msg), letter_name);
|
||||
if (drive_letters[k] == app_dir[0]) break;
|
||||
}
|
||||
// Repeat as we need to break the outside loop
|
||||
if (drive_letters[k] == app_dir[0]) {
|
||||
uprintf("Removing %c: from the list: This is the disk from which " APPLICATION_NAME " is running!\n", app_dir[0]);
|
||||
safe_closehandle(hDrive);
|
||||
safe_free(devint_detail_data);
|
||||
break;
|
||||
}
|
||||
safe_sprintf(&entry_msg[strlen(entry_msg)], sizeof(entry_msg) - strlen(entry_msg),
|
||||
"%s [%s]", (right_to_left_mode)?RIGHT_TO_LEFT_MARK:"", SizeToHumanReadable(GetDriveSize(drive_index), FALSE, use_fake_units));
|
||||
entry = entry_msg;
|
||||
}
|
||||
|
||||
// Must ensure that the combo box is UNSORTED for indexes to be the same
|
||||
StrArrayAdd(&DriveID, buffer);
|
||||
StrArrayAdd(&DriveLabel, label);
|
||||
|
||||
IGNORE_RETVAL(ComboBox_SetItemData(hDeviceList, ComboBox_AddStringU(hDeviceList, entry), drive_index));
|
||||
maxwidth = max(maxwidth, GetEntryWidth(hDeviceList, entry));
|
||||
safe_closehandle(hDrive);
|
||||
safe_free(devint_detail_data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
SetupDiDestroyDeviceInfoList(dev_info);
|
||||
|
||||
// Adjust the Dropdown width to the maximum text size
|
||||
SendMessage(hDeviceList, CB_SETDROPPEDWIDTH, (WPARAM)maxwidth, 0);
|
||||
|
||||
if (devnum >= DRIVE_INDEX_MIN) {
|
||||
for (i=0; i<ComboBox_GetCount(hDeviceList); i++) {
|
||||
if ((DWORD)ComboBox_GetItemData(hDeviceList, i) == devnum) {
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
i = 0;
|
||||
IGNORE_RETVAL(ComboBox_SetCurSel(hDeviceList, i));
|
||||
SendMessage(hMainDialog, WM_COMMAND, (CBN_SELCHANGE<<16) | IDC_DEVICE, 0);
|
||||
SendMessage(hMainDialog, WM_COMMAND, (CBN_SELCHANGE<<16) | IDC_FILESYSTEM,
|
||||
ComboBox_GetCurSel(hFileSystem));
|
||||
safe_free(devid_list);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up progress bar real estate allocation
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue