mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[core] add HDD vs UFD detection
* Initial scoring to try to differentiate UFDs from HDDs (#219) * Also improve GetDriveLetter() and add a global for fixed vs removable * Also fix a bug with reporting of VID:PID with multiple devices * Also fix a warning in localization
This commit is contained in:
		
							parent
							
								
									803a4bff1c
								
							
						
					
					
						commit
						aa0bf0ee2b
					
				
					 7 changed files with 165 additions and 38 deletions
				
			
		
							
								
								
									
										38
									
								
								src/drive.c
									
										
									
									
									
								
							
							
						
						
									
										38
									
								
								src/drive.c
									
										
									
									
									
								
							|  | @ -36,7 +36,7 @@ | ||||||
|  * Globals |  * Globals | ||||||
|  */ |  */ | ||||||
| RUFUS_DRIVE_INFO SelectedDrive; | RUFUS_DRIVE_INFO SelectedDrive; | ||||||
| extern BOOL enable_fixed_disks; | extern UINT drive_type; | ||||||
| 
 | 
 | ||||||
| // TODO: add a DetectSectorSize()?
 | // TODO: add a DetectSectorSize()?
 | ||||||
| // http://msdn.microsoft.com/en-us/library/ff800831.aspx
 | // http://msdn.microsoft.com/en-us/library/ff800831.aspx
 | ||||||
|  | @ -136,11 +136,11 @@ char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash, BOOL bSilent | ||||||
| 	char path[MAX_PATH]; | 	char path[MAX_PATH]; | ||||||
| 	VOLUME_DISK_EXTENTS DiskExtents; | 	VOLUME_DISK_EXTENTS DiskExtents; | ||||||
| 	DWORD size; | 	DWORD size; | ||||||
| 	UINT drive_type; |  | ||||||
| 	int i, j; | 	int i, j; | ||||||
| 	static const char* ignore_device[] = { "\\Device\\CdRom", "\\Device\\Floppy" }; | 	static const char* ignore_device[] = { "\\Device\\CdRom", "\\Device\\Floppy" }; | ||||||
| 	static const char* volume_start = "\\\\?\\"; | 	static const char* volume_start = "\\\\?\\"; | ||||||
| 
 | 
 | ||||||
|  | 	drive_type = DRIVE_UNKNOWN; | ||||||
| 	CheckDriveIndex(DriveIndex); | 	CheckDriveIndex(DriveIndex); | ||||||
| 
 | 
 | ||||||
| 	for (i=0; hDrive == INVALID_HANDLE_VALUE; i++) { | 	for (i=0; hDrive == INVALID_HANDLE_VALUE; i++) { | ||||||
|  | @ -167,9 +167,7 @@ char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash, BOOL bSilent | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		drive_type = GetDriveTypeA(volume_name); | 		drive_type = GetDriveTypeA(volume_name); | ||||||
| 		// NB: the HP utility allows drive_type == DRIVE_FIXED, which we don't allow by default
 | 		if ((drive_type != DRIVE_REMOVABLE) && (drive_type != DRIVE_FIXED)) | ||||||
| 		// Using Alt-F in Rufus does enable listing, but this mode is unsupported.
 |  | ||||||
| 		if ((drive_type != DRIVE_REMOVABLE) && ((!enable_fixed_disks) || (drive_type != DRIVE_FIXED))) |  | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
| 		volume_name[len-1] = 0; | 		volume_name[len-1] = 0; | ||||||
|  | @ -257,16 +255,17 @@ HANDLE GetLogicalHandle(DWORD DriveIndex, BOOL bWriteAccess, BOOL bLockDrive) | ||||||
| /*
 | /*
 | ||||||
|  * Returns the first drive letter for a volume located on the drive identified by DriveIndex |  * Returns the first drive letter for a volume located on the drive identified by DriveIndex | ||||||
|  */ |  */ | ||||||
| char GetDriveLetter(DWORD DriveIndex) | BOOL GetDriveLetter(DWORD DriveIndex, char* drive_letter) | ||||||
| { | { | ||||||
| 	DWORD size; | 	DWORD size; | ||||||
| 	BOOL r; | 	BOOL r = FALSE; | ||||||
| 	STORAGE_DEVICE_NUMBER_REDEF device_number = {0}; | 	STORAGE_DEVICE_NUMBER_REDEF device_number = {0}; | ||||||
| 	UINT drive_type; |  | ||||||
| 	HANDLE hDrive = INVALID_HANDLE_VALUE; | 	HANDLE hDrive = INVALID_HANDLE_VALUE; | ||||||
| 	char *drive, drives[26*4];	/* "D:\", "E:\", etc. */ | 	char *drive, drives[26*4];	/* "D:\", "E:\", etc. */ | ||||||
| 	char logical_drive[] = "\\\\.\\#:"; | 	char logical_drive[] = "\\\\.\\#:"; | ||||||
| 	char drive_letter = ' '; | 
 | ||||||
|  | 	drive_type = DRIVE_UNKNOWN; | ||||||
|  | 	*drive_letter = ' '; | ||||||
| 	CheckDriveIndex(DriveIndex); | 	CheckDriveIndex(DriveIndex); | ||||||
| 
 | 
 | ||||||
| 	size = GetLogicalDriveStringsA(sizeof(drives), drives); | 	size = GetLogicalDriveStringsA(sizeof(drives), drives); | ||||||
|  | @ -279,6 +278,7 @@ char GetDriveLetter(DWORD DriveIndex) | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	r = TRUE; | ||||||
| 	for (drive = drives ;*drive; drive += safe_strlen(drive)+1) { | 	for (drive = drives ;*drive; drive += safe_strlen(drive)+1) { | ||||||
| 		if (!isalpha(*drive)) | 		if (!isalpha(*drive)) | ||||||
| 			continue; | 			continue; | ||||||
|  | @ -292,9 +292,8 @@ char GetDriveLetter(DWORD DriveIndex) | ||||||
| 			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 for details. */
 | ||||||
| 		drive_type = GetDriveTypeA(drive); | 		drive_type = GetDriveTypeA(drive); | ||||||
| 		// NB: the HP utility allows drive_type == DRIVE_FIXED, which we don't allow by default
 | 
 | ||||||
| 		// Using Alt-F in Rufus does enable listing, but this mode is unsupported.
 | 		if ((drive_type != DRIVE_REMOVABLE) && (drive_type != DRIVE_FIXED)) | ||||||
| 		if ((drive_type != DRIVE_REMOVABLE) && ((!enable_fixed_disks) || (drive_type != DRIVE_FIXED))) |  | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
| 		safe_sprintf(logical_drive, sizeof(logical_drive), "\\\\.\\%c:", drive[0]); | 		safe_sprintf(logical_drive, sizeof(logical_drive), "\\\\.\\%c:", drive[0]); | ||||||
|  | @ -305,19 +304,19 @@ char GetDriveLetter(DWORD DriveIndex) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		r = DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, | 		r = DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, | ||||||
| 			0, &device_number, sizeof(device_number), &size, NULL); | 			0, &device_number, sizeof(device_number), &size, NULL) && (size > 0); | ||||||
| 		safe_closehandle(hDrive); | 		safe_closehandle(hDrive); | ||||||
| 		if ((!r) || (size <= 0)) { | 		if (!r) { | ||||||
| 			uprintf("Could not get device number for device %s: %s\n", | 			uprintf("Could not get device number for device %s: %s\n", | ||||||
| 				logical_drive, WindowsErrorString()); | 				logical_drive, WindowsErrorString()); | ||||||
| 		} else if (device_number.DeviceNumber == DriveIndex) { | 		} else if (device_number.DeviceNumber == DriveIndex) { | ||||||
| 			drive_letter = *drive; | 			*drive_letter = *drive; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| out: | out: | ||||||
| 	return drive_letter; | 	return r; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  | @ -368,10 +367,11 @@ BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label) | ||||||
| 
 | 
 | ||||||
| 	*label = STR_NO_LABEL; | 	*label = STR_NO_LABEL; | ||||||
| 
 | 
 | ||||||
| 	*letter = GetDriveLetter(DriveIndex); | 	if (!GetDriveLetter(DriveIndex, letter)) | ||||||
|  | 		return FALSE; | ||||||
| 	if (*letter == ' ') { | 	if (*letter == ' ') { | ||||||
| 		// Drive without volume assigned - Tie to the display of fixed disks
 | 		// Drive without volume assigned - always enabled
 | ||||||
| 		return enable_fixed_disks; | 		return TRUE; | ||||||
| 	} | 	} | ||||||
| 	AutorunPath[0] = *letter; | 	AutorunPath[0] = *letter; | ||||||
| 	wDrivePath[0] = *letter; | 	wDrivePath[0] = *letter; | ||||||
|  |  | ||||||
|  | @ -1195,7 +1195,11 @@ DWORD WINAPI FormatThread(LPVOID param) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// At this stage with have both a handle and a lock to the physical drive...
 | 	// At this stage with have both a handle and a lock to the physical drive...
 | ||||||
| 	drive_name[0] = GetDriveLetter(DriveIndex); | 	if (!GetDriveLetter(DriveIndex, &drive_name[0])) { | ||||||
|  | 		uprintf("Failed to get a drive letter\n"); | ||||||
|  | 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_ASSIGN_LETTER); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
| 	if (drive_name[0] == ' ') { | 	if (drive_name[0] == ' ') { | ||||||
| 		uprintf("No drive letter was assigned...\n"); | 		uprintf("No drive letter was assigned...\n"); | ||||||
| 		drive_name[0] =  GetUnusedDriveLetter(); | 		drive_name[0] =  GetUnusedDriveLetter(); | ||||||
|  |  | ||||||
|  | @ -199,7 +199,7 @@ static uint32_t htab_hash(char* str) | ||||||
| 		do { | 		do { | ||||||
| 			// Because size is prime this guarantees to step through all available indexes
 | 			// Because size is prime this guarantees to step through all available indexes
 | ||||||
| 			if (idx <= hval2) { | 			if (idx <= hval2) { | ||||||
| 				idx = htab_size + idx - hval2; | 				idx = ((uint32_t)htab_size) + idx - hval2; | ||||||
| 			} else { | 			} else { | ||||||
| 				idx -= hval2; | 				idx -= hval2; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
							
								
								
									
										29
									
								
								src/rufus.c
									
										
									
									
									
								
							
							
						
						
									
										29
									
								
								src/rufus.c
									
										
									
									
									
								
							|  | @ -117,7 +117,8 @@ HWND hDeviceList, hPartitionScheme, hFileSystem, hClusterSize, hLabel, hBootType | ||||||
| HWND hISOProgressDlg = NULL, hLogDlg = NULL, hISOProgressBar, hISOFileName, hDiskID; | HWND hISOProgressDlg = NULL, hLogDlg = NULL, hISOProgressBar, hISOFileName, hDiskID; | ||||||
| BOOL use_own_c32[NB_OLD_C32] = {FALSE, FALSE}, detect_fakes = TRUE, mbr_selected_by_user = FALSE; | BOOL use_own_c32[NB_OLD_C32] = {FALSE, FALSE}, detect_fakes = TRUE, mbr_selected_by_user = FALSE; | ||||||
| BOOL iso_op_in_progress = FALSE, format_op_in_progress = FALSE; | BOOL iso_op_in_progress = FALSE, format_op_in_progress = FALSE; | ||||||
| BOOL enable_fixed_disks = FALSE, advanced_mode = TRUE, force_update = FALSE; | BOOL enable_HDDs = FALSE, advanced_mode = TRUE, force_update = FALSE; | ||||||
|  | UINT drive_type = DRIVE_UNKNOWN; | ||||||
| int dialog_showing = 0; | int dialog_showing = 0; | ||||||
| uint16_t rufus_version[4]; | uint16_t rufus_version[4]; | ||||||
| RUFUS_UPDATE update = { {0,0,0,0}, {0,0}, NULL, NULL}; | RUFUS_UPDATE update = { {0,0,0,0}, {0,0}, NULL, NULL}; | ||||||
|  | @ -602,6 +603,7 @@ static BOOL GetUSBDevices(DWORD devnum) | ||||||
| 	HANDLE hDrive; | 	HANDLE hDrive; | ||||||
| 	LONG maxwidth = 0; | 	LONG maxwidth = 0; | ||||||
| 	RECT rect; | 	RECT rect; | ||||||
|  | 	int score; | ||||||
| 	char drive_letter, *devid, *devid_list = NULL; | 	char drive_letter, *devid, *devid_list = NULL; | ||||||
| 	char *label, *entry, buffer[MAX_PATH], str[sizeof("0000:0000")+1]; | 	char *label, *entry, buffer[MAX_PATH], str[sizeof("0000:0000")+1]; | ||||||
| 	const char* usbstor_name = "USBSTOR"; | 	const char* usbstor_name = "USBSTOR"; | ||||||
|  | @ -653,7 +655,7 @@ static BOOL GetUSBDevices(DWORD devnum) | ||||||
| 		} else { | 		} else { | ||||||
| 			// Get the VID:PID of the device. We could avoid doing this lookup every time by keeping
 | 			// 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...
 | 			// a lookup table, but there shouldn't be that many USB storage devices connected...
 | ||||||
| 			for (devid = devid_list; *devid; devid += strlen(devid_list) + 1) { | 			for (devid = devid_list; *devid; devid += strlen(devid) + 1) { | ||||||
| 				if ( (CM_Locate_DevNodeA(&parent_inst, devid, 0) == 0) | 				if ( (CM_Locate_DevNodeA(&parent_inst, devid, 0) == 0) | ||||||
| 				  && (CM_Get_Child(&device_inst, parent_inst, 0) == 0) | 				  && (CM_Get_Child(&device_inst, parent_inst, 0) == 0) | ||||||
| 				  && (device_inst == dev_info_data.DevInst) ) { | 				  && (device_inst == dev_info_data.DevInst) ) { | ||||||
|  | @ -684,7 +686,7 @@ static BOOL GetUSBDevices(DWORD devnum) | ||||||
| 				if(GetLastError() != ERROR_NO_MORE_ITEMS) { | 				if(GetLastError() != ERROR_NO_MORE_ITEMS) { | ||||||
| 					uprintf("SetupDiEnumDeviceInterfaces failed: %s\n", WindowsErrorString()); | 					uprintf("SetupDiEnumDeviceInterfaces failed: %s\n", WindowsErrorString()); | ||||||
| 				} else { | 				} else { | ||||||
| 					uprintf("A device was eliminated because it didn't report itself as a non fixed USB disk\n"); | 					uprintf("A device was eliminated because it didn't report itself as a disk\n"); | ||||||
| 				} | 				} | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
|  | @ -730,12 +732,19 @@ static BOOL GetUSBDevices(DWORD devnum) | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| //			Identify(hDrive);
 |  | ||||||
| 
 |  | ||||||
| 			if (GetDriveLabel(device_number.DeviceNumber + DRIVE_INDEX_MIN, &drive_letter, &label)) { | 			if (GetDriveLabel(device_number.DeviceNumber + DRIVE_INDEX_MIN, &drive_letter, &label)) { | ||||||
| 				// Must ensure that the combo box is UNSORTED for indexes to be the same
 | 				// Must ensure that the combo box is UNSORTED for indexes to be the same
 | ||||||
| 				StrArrayAdd(&DriveID, buffer); | 				StrArrayAdd(&DriveID, buffer); | ||||||
| 				StrArrayAdd(&DriveLabel, label); | 				StrArrayAdd(&DriveLabel, label); | ||||||
|  | 
 | ||||||
|  | 				if ((!enable_HDDs) && ((score = IsHDD(drive_type, vid, pid, buffer)) > IS_HDD_THRESHOLD)) { | ||||||
|  | 					uprintf("USB HDD device removed (score %d > %d) " | ||||||
|  | 						"[Note: You can enable USB HDDs in the Advanced Options]\n", score, IS_HDD_THRESHOLD); | ||||||
|  | 					safe_closehandle(hDrive); | ||||||
|  | 					safe_free(devint_detail_data); | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
| 				// Drive letter ' ' is returned for drives that don't have a volume assigned yet
 | 				// Drive letter ' ' is returned for drives that don't have a volume assigned yet
 | ||||||
| 				if (drive_letter == ' ') { | 				if (drive_letter == ' ') { | ||||||
| 					entry = lmprintf(MSG_046, label, device_number.DeviceNumber); | 					entry = lmprintf(MSG_046, label, device_number.DeviceNumber); | ||||||
|  | @ -1809,8 +1818,8 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | ||||||
| 			break; | 			break; | ||||||
| 		case IDC_ENABLE_FIXED_DISKS: | 		case IDC_ENABLE_FIXED_DISKS: | ||||||
| 			if ((HIWORD(wParam)) == BN_CLICKED) { | 			if ((HIWORD(wParam)) == BN_CLICKED) { | ||||||
| 				enable_fixed_disks = !enable_fixed_disks; | 				enable_HDDs = !enable_HDDs; | ||||||
| 				PrintStatus2000(lmprintf(MSG_253), enable_fixed_disks); | 				PrintStatus2000(lmprintf(MSG_253), enable_HDDs); | ||||||
| 				GetUSBDevices(0); | 				GetUSBDevices(0); | ||||||
| 			} | 			} | ||||||
| 			break; | 			break; | ||||||
|  | @ -2030,7 +2039,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine | ||||||
| 		while ((opt = getopt_long(argc, argv, "?fhi:w:l:", long_options, &option_index)) != EOF) | 		while ((opt = getopt_long(argc, argv, "?fhi:w:l:", long_options, &option_index)) != EOF) | ||||||
| 			switch (opt) { | 			switch (opt) { | ||||||
| 			case 'f': | 			case 'f': | ||||||
| 				enable_fixed_disks = TRUE; | 				enable_HDDs = TRUE; | ||||||
| 				break; | 				break; | ||||||
| 			case 'i': | 			case 'i': | ||||||
| 				if (_access(optarg, 0) != -1) { | 				if (_access(optarg, 0) != -1) { | ||||||
|  | @ -2166,8 +2175,8 @@ relaunch: | ||||||
| 			// This is a safety feature, to avoid someone unintentionally formatting a backup 
 | 			// This is a safety feature, to avoid someone unintentionally formatting a backup 
 | ||||||
| 			// drive instead of an USB key. If this is enabled, Rufus will allow fixed disk formatting.
 | 			// drive instead of an USB key. If this is enabled, Rufus will allow fixed disk formatting.
 | ||||||
| 			if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'F')) { | 			if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'F')) { | ||||||
| 				enable_fixed_disks = !enable_fixed_disks; | 				enable_HDDs = !enable_HDDs; | ||||||
| 				PrintStatus2000(lmprintf(MSG_253), enable_fixed_disks); | 				PrintStatus2000(lmprintf(MSG_253), enable_HDDs); | ||||||
| 				GetUSBDevices(0); | 				GetUSBDevices(0); | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | @ -56,6 +56,7 @@ | ||||||
| #define UDF_FORMAT_SPEED            3.1f		// Speed estimate at which we expect UDF drives to be formatted (GB/s)
 | #define UDF_FORMAT_SPEED            3.1f		// Speed estimate at which we expect UDF drives to be formatted (GB/s)
 | ||||||
| #define UDF_FORMAT_WARN             20			// Duration (in seconds) above which we warn about long UDF formatting times
 | #define UDF_FORMAT_WARN             20			// Duration (in seconds) above which we warn about long UDF formatting times
 | ||||||
| #define MAX_FAT32_SIZE              2.0f		// Threshold above which we disable FAT32 formatting (in TB)
 | #define MAX_FAT32_SIZE              2.0f		// Threshold above which we disable FAT32 formatting (in TB)
 | ||||||
|  | #define IS_HDD_THRESHOLD            5 | ||||||
| #define WHITE                       RGB(255,255,255) | #define WHITE                       RGB(255,255,255) | ||||||
| #define SEPARATOR_GREY              RGB(223,223,223) | #define SEPARATOR_GREY              RGB(223,223,223) | ||||||
| #define RUFUS_URL                   "http://rufus.akeo.ie"
 | #define RUFUS_URL                   "http://rufus.akeo.ie"
 | ||||||
|  | @ -319,7 +320,7 @@ extern HANDLE GetPhysicalHandle(DWORD DriveIndex, BOOL bWriteAccess, BOOL bLockD | ||||||
| extern BOOL WaitForLogical(DWORD DriveIndex); | extern BOOL WaitForLogical(DWORD DriveIndex); | ||||||
| extern char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash, BOOL bSilent); | extern char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash, BOOL bSilent); | ||||||
| extern HANDLE GetLogicalHandle(DWORD DriveIndex, BOOL bWriteAccess, BOOL bLockDrive); | extern HANDLE GetLogicalHandle(DWORD DriveIndex, BOOL bWriteAccess, BOOL bLockDrive); | ||||||
| extern char GetDriveLetter(DWORD DriveIndex); | extern BOOL GetDriveLetter(DWORD DriveIndex, char* drive_letter); | ||||||
| extern char GetUnusedDriveLetter(void); | extern char GetUnusedDriveLetter(void); | ||||||
| extern BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL mbr_uefi_marker); | extern BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL mbr_uefi_marker); | ||||||
| extern BOOL DeletePartitions(HANDLE hDrive); | extern BOOL DeletePartitions(HANDLE hDrive); | ||||||
|  | @ -350,7 +351,7 @@ extern char* replace_in_token_data(const char* filename, const char* token, cons | ||||||
| extern void parse_update(char* buf, size_t len); | extern void parse_update(char* buf, size_t len); | ||||||
| extern BOOL WimExtractCheck(void); | extern BOOL WimExtractCheck(void); | ||||||
| extern BOOL WimExtractFile(const char* wim_image, int index, const char* src, const char* dst); | extern BOOL WimExtractFile(const char* wim_image, int index, const char* src, const char* dst); | ||||||
| extern BOOL Identify(HANDLE hPhysical); | extern int IsHDD(UINT drive_type, uint16_t vid, uint16_t pid, const char* strid); | ||||||
| 
 | 
 | ||||||
| static __inline BOOL UnlockDrive(HANDLE hDrive) | static __inline BOOL UnlockDrive(HANDLE hDrive) | ||||||
| { | { | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							|  | @ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL | ||||||
| IDD_DIALOG DIALOGEX 12, 12, 206, 329 | IDD_DIALOG DIALOGEX 12, 12, 206, 329 | ||||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU | STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||||
| EXSTYLE WS_EX_APPWINDOW | EXSTYLE WS_EX_APPWINDOW | ||||||
| CAPTION "Rufus v1.4.0.315" | CAPTION "Rufus v1.4.0.316" | ||||||
| FONT 8, "MS Shell Dlg", 400, 0, 0x1 | FONT 8, "MS Shell Dlg", 400, 0, 0x1 | ||||||
| BEGIN | BEGIN | ||||||
|     DEFPUSHBUTTON   "Start",IDC_START,94,291,50,14 |     DEFPUSHBUTTON   "Start",IDC_START,94,291,50,14 | ||||||
|  | @ -289,8 +289,8 @@ END | ||||||
| // | // | ||||||
| 
 | 
 | ||||||
| VS_VERSION_INFO VERSIONINFO | VS_VERSION_INFO VERSIONINFO | ||||||
|  FILEVERSION 1,4,0,315 |  FILEVERSION 1,4,0,316 | ||||||
|  PRODUCTVERSION 1,4,0,315 |  PRODUCTVERSION 1,4,0,316 | ||||||
|  FILEFLAGSMASK 0x3fL |  FILEFLAGSMASK 0x3fL | ||||||
| #ifdef _DEBUG | #ifdef _DEBUG | ||||||
|  FILEFLAGS 0x1L |  FILEFLAGS 0x1L | ||||||
|  | @ -307,13 +307,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", "1.4.0.315" |             VALUE "FileVersion", "1.4.0.316" | ||||||
|             VALUE "InternalName", "Rufus" |             VALUE "InternalName", "Rufus" | ||||||
|             VALUE "LegalCopyright", "© 2011-2013 Pete Batard (GPL v3)" |             VALUE "LegalCopyright", "© 2011-2013 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", "1.4.0.315" |             VALUE "ProductVersion", "1.4.0.316" | ||||||
|         END |         END | ||||||
|     END |     END | ||||||
|     BLOCK "VarFileInfo" |     BLOCK "VarFileInfo" | ||||||
|  |  | ||||||
							
								
								
									
										113
									
								
								src/smart.c
									
										
									
									
									
								
							
							
						
						
									
										113
									
								
								src/smart.c
									
										
									
									
									
								
							|  | @ -397,4 +397,117 @@ BOOL SmartGetVersion(HANDLE hdevice) | ||||||
|  * - if IDENTIFY reports SMART capabilities |  * - if IDENTIFY reports SMART capabilities | ||||||
|  * - if it has extra non hidden partitions that aren't Windows |  * - if it has extra non hidden partitions that aren't Windows | ||||||
|  * - if the VID:PID (or VID) is of known USB to IDE/SATA bridge or known UFD maker |  * - if the VID:PID (or VID) is of known USB to IDE/SATA bridge or known UFD maker | ||||||
|  |  * - removable flag (how do you actually find that one?) | ||||||
|  */ |  */ | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  | 	const char* name; | ||||||
|  | 	const int score; | ||||||
|  | } str_score; | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  | 	const uint16_t vid; | ||||||
|  | 	const int score; | ||||||
|  | } vid_score; | ||||||
|  | 
 | ||||||
|  | // If a disk ID starts with these, we consider it likely to be an HDD
 | ||||||
|  | // The info from http://knowledge.seagate.com/articles/en_US/FAQ/204763en is a start, but not
 | ||||||
|  | // entirely accurate for our usage as some models will be prefixed with the manufacturer name
 | ||||||
|  | // '#' below means any number in [0-9]
 | ||||||
|  | static str_score manufacturer_str[] = { | ||||||
|  | 	{ "HP ", 10 }, | ||||||
|  | 	{ "ST#", 10 }, | ||||||
|  | 	{ "MX#", 10 }, | ||||||
|  | 	{ "WDC", 10 }, | ||||||
|  | 	{ "IBM", 10 }, | ||||||
|  | 	{ "STM#", 10 }, | ||||||
|  | 	{ "HTS#", 10 }, | ||||||
|  | 	{ "MAXTOR", 10 }, | ||||||
|  | 	{ "HITACHI", 10 }, | ||||||
|  | 	{ "SEAGATE", 10 }, | ||||||
|  | 	{ "SAMSUNG", 10 }, | ||||||
|  | 	{ "FUJITSU", 10 }, | ||||||
|  | 	{ "TOSHIBA", 10 }, | ||||||
|  | 	{ "QUANTUM", 10 }, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // http://www.linux-usb.org/usb.ids
 | ||||||
|  | static vid_score manufacturer_vid[] = { | ||||||
|  | 	{ 0x04b4, 10 },	// Cypress
 | ||||||
|  | 	{ 0x067b, 10 },	// Prolific
 | ||||||
|  | 	{ 0x0bc2, 10 },	// Seagate
 | ||||||
|  | 	{ 0x152d, 10 }, // JMicron
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * This attempts to detect whether a drive is an USB HDD or an USB Flash Drive (UFD). | ||||||
|  |  * If someone already has an USB HDD plugged in (say as a backup drive) and plugs an | ||||||
|  |  * UFD we *try* to do what we can to avoid them formatting that drive by mistake. | ||||||
|  |  * But because there is no foolproof (let alone easy), way to differentiate UFDs from | ||||||
|  |  * HDDs, thanks to every manufacturer, Microsoft, and their mothers making it  | ||||||
|  |  * exceedingly troublesome to find out what type of hardware we are actually accessing | ||||||
|  |  * please pay heed to the following warning: | ||||||
|  |  * | ||||||
|  |  * WARNING: NO PROMISE IS MADE  ABOUT THIS ALGORITHM BEING ABLE TO CORRECTLY | ||||||
|  |  * DIFFERENTIATE AN USB HDD FROM A FLASH DRIVE. ALSO, REMEMBER THAT THE LICENSE OF THIS | ||||||
|  |  * APPLICATION MAKES ABSOLUETLY NO PROMISE ABOUT DATA PRESERVATION (PROVIDED "AS IS"). | ||||||
|  |  * THUS, IF DATA LOSS IS INCURRED DUE TO THE ALGORITHM BELOW, OR ANY OTHER PART OF THIS | ||||||
|  |  * APPLICATION, THE RESPONSIBILITY IS ENTIRELY ON YOU! | ||||||
|  |  * | ||||||
|  |  * But let me just elaborate further on why differentiating UFDs from HDDs is not as | ||||||
|  |  * 'simple' as it seems: | ||||||
|  |  * - many USB flash drives manufacturer will present UFDs as non-removable, which used | ||||||
|  |  *   to be reserved for HDDs => we can't use that as differentiator. | ||||||
|  |  * - some UFDs (SanDisk Extreme) have added S.M.A.R.T. support, which also used to be | ||||||
|  |  *   reserved for HDDs => can't use that either | ||||||
|  |  * - even if S.M.A.R.T. was enough, not all USB->IDE or USB->SATA bridges support ATA | ||||||
|  |  *   passthrough, which is required S.M.A.R.T. data, and each manufacturer of an  | ||||||
|  |  *   USB<->(S)ATA bridge seem to have their own method of implementing passthrough. | ||||||
|  |  * - SSDs have also changed the deal completely, as you can get something that looks | ||||||
|  |  *   like Flash but that is really an HDD. | ||||||
|  |  * - Some manufacturers (eg. ALI) provide both USB Flash controllers and USB IDE/SATA | ||||||
|  |  *   controllers, so we can't exactly use the VID to say for sure what we're looking at. | ||||||
|  |  * - Finally, Microsoft is abdsolutely no help either (which is kind of understandable | ||||||
|  |  *   from the above) => there is no magic API we can query that will tell us what we're | ||||||
|  |  *   really looking at. | ||||||
|  |  * | ||||||
|  |  * What you have below, then, is our *current best guess* at differentiating an UFD from | ||||||
|  |  * an HDD. Short of a crystal ball however, this remains just a guess, which may be way | ||||||
|  |  * off mark. Still, Rufus does produce PROMINENT warnings before you format a drive, and | ||||||
|  |  * also provides extensive info about the drive (from the toolips and the log) => PAY | ||||||
|  |  * ATTENTION TO THESE OR PAY THE PRICE! | ||||||
|  |  */ | ||||||
|  | int IsHDD(UINT drive_type, uint16_t vid, uint16_t pid, const char* strid) | ||||||
|  | { | ||||||
|  | 	int score = 0; | ||||||
|  | 	size_t i, mlen, ilen; | ||||||
|  | 	BOOL wc; | ||||||
|  | 
 | ||||||
|  | 	if (drive_type == DRIVE_FIXED) | ||||||
|  | 		score += 3; | ||||||
|  | 
 | ||||||
|  | 	ilen = safe_strlen(strid); | ||||||
|  | 	for (i=0; i<ARRAYSIZE(manufacturer_str); i++) { | ||||||
|  | 		mlen = strlen(manufacturer_str[i].name); | ||||||
|  | 		if (mlen > ilen) | ||||||
|  | 			break; | ||||||
|  | 		wc = (manufacturer_str[i].name[mlen-1] == '#'); | ||||||
|  | 		if ( (_strnicmp(strid, manufacturer_str[i].name, mlen-((wc)?1:0)) == 0) | ||||||
|  | 		  && ((!wc) || ((strid[mlen] >= '0') && (strid[mlen] <= '9'))) ) { | ||||||
|  | 			score += manufacturer_str[i].score; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (i=0; i<ARRAYSIZE(manufacturer_vid); i++) { | ||||||
|  | 		if (vid == manufacturer_vid[i].vid) { | ||||||
|  | 			score += manufacturer_vid[i].score; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// TODO: try to perform inquiry if uncertain
 | ||||||
|  | 	// TODO: lower the score for well known UFD manufacturers (ADATA, SanDisk, etc.)
 | ||||||
|  | 	return score; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue