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…
	
	Add table
		Add a link
		
	
		Reference in a new issue