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; | ||||
| 		} | ||||
| 
 | ||||
| 		/* 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)) | ||||
|  |  | |||
|  | @ -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; | ||||
| 			} | ||||
|  |  | |||
							
								
								
									
										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 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); | ||||
|  |  | |||
							
								
								
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								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" | ||||
|  |  | |||
							
								
								
									
										284
									
								
								src/usb.c
									
										
									
									
									
								
							
							
						
						
									
										284
									
								
								src/usb.c
									
										
									
									
									
								
							|  | @ -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; | ||||
|  |  | |||
							
								
								
									
										19
									
								
								src/usb.h
									
										
									
									
									
								
							
							
						
						
									
										19
									
								
								src/usb.h
									
										
									
									
									
								
							|  | @ -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 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue