mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[core] fix detection of fixed drives
* Thanks to MS' shortsightedness, neither of IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS or IOCTL_STORAGE_GET_DEVICE_NUMBER alone are enough to retrieve a disk number: IOCTL_STORAGE_GET_DEVICE_NUMBER doesn't work for LVM drives and IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS doesn't work for USB fixed drives, so we must use both. Isn't it great? * Closes #292
This commit is contained in:
		
							parent
							
								
									07d5a61f2a
								
							
						
					
					
						commit
						8c1dd2ca91
					
				
					 4 changed files with 62 additions and 34 deletions
				
			
		
							
								
								
									
										46
									
								
								src/drive.c
									
										
									
									
									
								
							
							
						
						
									
										46
									
								
								src/drive.c
									
										
									
									
									
								
							|  | @ -262,6 +262,40 @@ HANDLE GetLogicalHandle(DWORD DriveIndex, BOOL bWriteAccess, BOOL bLockDrive) | ||||||
| 	return hLogical; | 	return hLogical; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * Who would have thought that Microsoft would make it so unbelievably hard to | ||||||
|  |  * get the frickin' device number for a drive? You have to use TWO different | ||||||
|  |  * methods to have a chance to get it! | ||||||
|  |  */ | ||||||
|  | int GetDriveNumber(HANDLE hDrive, char* path) | ||||||
|  | { | ||||||
|  | 	STORAGE_DEVICE_NUMBER_REDEF DeviceNumber; | ||||||
|  | 	VOLUME_DISK_EXTENTS_REDEF DiskExtents; | ||||||
|  | 	DWORD size; | ||||||
|  | 	int r = -1; | ||||||
|  | 
 | ||||||
|  | 	if (!DeviceIoControl(hDrive, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, | ||||||
|  | 		&DiskExtents, sizeof(DiskExtents), &size, NULL) || (size <= 0) || (DiskExtents.NumberOfDiskExtents < 1) ) { | ||||||
|  | 		// DiskExtents are NO_GO (which is the case for external USB HDDs...)
 | ||||||
|  | 		if(!DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, | ||||||
|  | 			&DeviceNumber, sizeof(DeviceNumber), &size, NULL ) || (size <= 0)) { | ||||||
|  | 			uprintf("Could not get device number for device %s: %s", path, WindowsErrorString()); | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 		r = (int)DeviceNumber.DeviceNumber; | ||||||
|  | 	} else if (DiskExtents.NumberOfDiskExtents >= 2) { | ||||||
|  | 		uprintf("Ignoring drive '%s' as it spans multiple disks (RAID?)", path); | ||||||
|  | 		return -1; | ||||||
|  | 	} else { | ||||||
|  | 		r = (int)DiskExtents.Extents[0].DiskNumber; | ||||||
|  | 	} | ||||||
|  | 	if (r >= MAX_DRIVES) { | ||||||
|  | 		uprintf("Device Number for device %s is too big (%d) - ignoring device", path, r); | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 	return r; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Returns the drive letters for all volumes located on the drive identified by DriveIndex, |  * Returns the drive letters for all volumes located on the drive identified by DriveIndex, | ||||||
|  * as well as the drive type. This is used as base for the 2 function calls that follow. |  * as well as the drive type. This is used as base for the 2 function calls that follow. | ||||||
|  | @ -269,8 +303,7 @@ HANDLE GetLogicalHandle(DWORD DriveIndex, BOOL bWriteAccess, BOOL bLockDrive) | ||||||
| static BOOL _GetDriveLettersAndType(DWORD DriveIndex, char* drive_letters, UINT* drive_type) | static BOOL _GetDriveLettersAndType(DWORD DriveIndex, char* drive_letters, UINT* drive_type) | ||||||
| { | { | ||||||
| 	DWORD size; | 	DWORD size; | ||||||
| 	BOOL s, r = FALSE; | 	BOOL r = FALSE; | ||||||
| 	VOLUME_DISK_EXTENTS DiskExtents; |  | ||||||
| 	HANDLE hDrive = INVALID_HANDLE_VALUE; | 	HANDLE hDrive = INVALID_HANDLE_VALUE; | ||||||
| 	UINT _drive_type; | 	UINT _drive_type; | ||||||
| 	int i = 0; | 	int i = 0; | ||||||
|  | @ -318,14 +351,7 @@ static BOOL _GetDriveLettersAndType(DWORD DriveIndex, char* drive_letters, UINT* | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		s = DeviceIoControl(hDrive, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, | 		if (GetDriveNumber(hDrive, logical_drive) == DriveIndex) { | ||||||
| 			&DiskExtents, sizeof(DiskExtents), &size, NULL) && (size > 0) && (DiskExtents.NumberOfDiskExtents >= 1); |  | ||||||
| 		safe_closehandle(hDrive); |  | ||||||
| 		if (!s) { |  | ||||||
| 			uprintf("Could not get device number for %c: - %s\n", drive[0], WindowsErrorString()); |  | ||||||
| 		} else if (DiskExtents.NumberOfDiskExtents >= 2) { |  | ||||||
| 			uprintf("Ignoring drive %c: as it spans multiple disks (RAID?)", drive[0]); |  | ||||||
| 		} else if (DiskExtents.Extents[0].DiskNumber == DriveIndex) { |  | ||||||
| 			r = TRUE; | 			r = TRUE; | ||||||
| 			if (drive_letters != NULL) | 			if (drive_letters != NULL) | ||||||
| 				drive_letters[i++] = *drive; | 				drive_letters[i++] = *drive; | ||||||
|  |  | ||||||
							
								
								
									
										14
									
								
								src/drive.h
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								src/drive.h
									
										
									
									
									
								
							|  | @ -24,11 +24,25 @@ | ||||||
| 
 | 
 | ||||||
| #define RUFUS_EXTRA_PARTITION_TYPE	0xea | #define RUFUS_EXTRA_PARTITION_TYPE	0xea | ||||||
| 
 | 
 | ||||||
|  | /* We need a redef of these MS structure */ | ||||||
|  | typedef struct { | ||||||
|  | 	DWORD DeviceType; | ||||||
|  | 	ULONG DeviceNumber; | ||||||
|  | 	ULONG PartitionNumber; | ||||||
|  | } STORAGE_DEVICE_NUMBER_REDEF; | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  | 	DWORD NumberOfDiskExtents; | ||||||
|  | 	// The one from MS uses ANYSIZE_ARRAY, which can lead to all kind of problems
 | ||||||
|  | 	DISK_EXTENT Extents[8]; | ||||||
|  | } VOLUME_DISK_EXTENTS_REDEF; | ||||||
|  | 
 | ||||||
| char* GetPhysicalName(DWORD DriveIndex); | char* GetPhysicalName(DWORD DriveIndex); | ||||||
| HANDLE GetPhysicalHandle(DWORD DriveIndex, BOOL bWriteAccess, BOOL bLockDrive); | HANDLE GetPhysicalHandle(DWORD DriveIndex, BOOL bWriteAccess, BOOL bLockDrive); | ||||||
| char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash, BOOL bSilent); | char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash, BOOL bSilent); | ||||||
| BOOL WaitForLogical(DWORD DriveIndex); | BOOL WaitForLogical(DWORD DriveIndex); | ||||||
| HANDLE GetLogicalHandle(DWORD DriveIndex, BOOL bWriteAccess, BOOL bLockDrive); | HANDLE GetLogicalHandle(DWORD DriveIndex, BOOL bWriteAccess, BOOL bLockDrive); | ||||||
|  | int GetDriveNumber(HANDLE hDrive, char* path); | ||||||
| BOOL GetDriveLetters(DWORD DriveIndex, char* drive_letters); | BOOL GetDriveLetters(DWORD DriveIndex, char* drive_letters); | ||||||
| UINT GetDriveTypeFromIndex(DWORD DriveIndex); | UINT GetDriveTypeFromIndex(DWORD DriveIndex); | ||||||
| char GetUnusedDriveLetter(void); | char GetUnusedDriveLetter(void); | ||||||
|  |  | ||||||
							
								
								
									
										24
									
								
								src/rufus.c
									
										
									
									
									
								
							
							
						
						
									
										24
									
								
								src/rufus.c
									
										
									
									
									
								
							|  | @ -647,14 +647,13 @@ static BOOL GetUSBDevices(DWORD devnum) | ||||||
| 	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; | ||||||
| 	VOLUME_DISK_EXTENTS DiskExtents; |  | ||||||
| 	DEVINST parent_inst, device_inst; | 	DEVINST parent_inst, device_inst; | ||||||
| 	DWORD size, i, j, k, datatype, drive_index; | 	DWORD size, i, j, k, datatype, drive_index; | ||||||
| 	ULONG list_size[ARRAYSIZE(usbstor_name)], full_list_size; | 	ULONG list_size[ARRAYSIZE(usbstor_name)], full_list_size; | ||||||
| 	HANDLE hDrive; | 	HANDLE hDrive; | ||||||
| 	LONG maxwidth = 0; | 	LONG maxwidth = 0; | ||||||
| 	RECT rect; | 	RECT rect; | ||||||
| 	int s, score; | 	int s, score, drive_number; | ||||||
| 	char drive_letters[27], *devid, *devid_list = NULL, entry_msg[128]; | 	char drive_letters[27], *devid, *devid_list = NULL, entry_msg[128]; | ||||||
| 	char *label, *entry, buffer[MAX_PATH], str[sizeof("0000:0000")+1]; | 	char *label, *entry, buffer[MAX_PATH], str[sizeof("0000:0000")+1]; | ||||||
| 	uint16_t vid, pid; | 	uint16_t vid, pid; | ||||||
|  | @ -798,21 +797,11 @@ static BOOL GetUSBDevices(DWORD devnum) | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if (!DeviceIoControl(hDrive, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, | 			drive_number = GetDriveNumber(hDrive, devint_detail_data->DevicePath); | ||||||
| 				&DiskExtents, sizeof(DiskExtents), &size, NULL) || (size <= 0) || (DiskExtents.NumberOfDiskExtents < 1) ) { | 			if (drive_number < 0) | ||||||
| 				uprintf("Could not get device number for device %s: %s\n", devint_detail_data->DevicePath, WindowsErrorString()); |  | ||||||
| 				continue; | 				continue; | ||||||
| 			} |  | ||||||
| 
 | 
 | ||||||
| 			if (DiskExtents.NumberOfDiskExtents >= 2) { | 			drive_index = drive_number + DRIVE_INDEX_MIN; | ||||||
| 				uprintf("Ignoring drive '%s' as it spans multiple disks (RAID?)", devint_detail_data->DevicePath); |  | ||||||
| 				continue; |  | ||||||
| 			} else if (DiskExtents.Extents[0].DiskNumber >= MAX_DRIVES) { |  | ||||||
| 				uprintf("Device Number %d is too big - ignoring device\n"); |  | ||||||
| 				continue; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			drive_index = DiskExtents.Extents[0].DiskNumber + DRIVE_INDEX_MIN; |  | ||||||
| 			if (!IsMediaPresent(drive_index)) { | 			if (!IsMediaPresent(drive_index)) { | ||||||
| 				uprintf("Device eliminated because it appears to contain no media\n"); | 				uprintf("Device eliminated because it appears to contain no media\n"); | ||||||
| 				safe_closehandle(hDrive); | 				safe_closehandle(hDrive); | ||||||
|  | @ -832,7 +821,7 @@ static BOOL GetUSBDevices(DWORD devnum) | ||||||
| 
 | 
 | ||||||
| 				// The empty string is returned for drives that don't have any volumes assigned
 | 				// The empty string is returned for drives that don't have any volumes assigned
 | ||||||
| 				if (drive_letters[0] == 0) { | 				if (drive_letters[0] == 0) { | ||||||
| 					entry = lmprintf(MSG_046, label, DiskExtents.Extents[0].DiskNumber); | 					entry = lmprintf(MSG_046, label, drive_number); | ||||||
| 				} else { | 				} else { | ||||||
| 					// We have multiple volumes assigned to the same device (multiple partitions)
 | 					// We have multiple volumes assigned to the same device (multiple partitions)
 | ||||||
| 					// If that is the case, use "Multiple Volumes" instead of the label
 | 					// If that is the case, use "Multiple Volumes" instead of the label
 | ||||||
|  | @ -860,8 +849,7 @@ static BOOL GetUSBDevices(DWORD devnum) | ||||||
| 				StrArrayAdd(&DriveID, buffer); | 				StrArrayAdd(&DriveID, buffer); | ||||||
| 				StrArrayAdd(&DriveLabel, label); | 				StrArrayAdd(&DriveLabel, label); | ||||||
| 
 | 
 | ||||||
| 				IGNORE_RETVAL(ComboBox_SetItemData(hDeviceList, ComboBox_AddStringU(hDeviceList, entry), | 				IGNORE_RETVAL(ComboBox_SetItemData(hDeviceList, ComboBox_AddStringU(hDeviceList, entry), drive_index)); | ||||||
| 					DiskExtents.Extents[0].DiskNumber + DRIVE_INDEX_MIN)); |  | ||||||
| 				maxwidth = max(maxwidth, GetEntryWidth(hDeviceList, entry)); | 				maxwidth = max(maxwidth, GetEntryWidth(hDeviceList, entry)); | ||||||
| 				safe_closehandle(hDrive); | 				safe_closehandle(hDrive); | ||||||
| 				safe_free(devint_detail_data); | 				safe_free(devint_detail_data); | ||||||
|  |  | ||||||
							
								
								
									
										12
									
								
								src/rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								src/rufus.rc
									
										
									
									
									
								
							|  | @ -32,7 +32,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 | ||||||
| CAPTION "Rufus 1.4.4.425" | CAPTION "Rufus 1.4.4.426" | ||||||
| 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 | ||||||
|  | @ -165,7 +165,7 @@ END | ||||||
| RTL_IDD_DIALOG DIALOGEX 12, 12, 206, 329 | RTL_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_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL | EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL | ||||||
| CAPTION "Rufus 1.4.4.425" | CAPTION "Rufus 1.4.4.426" | ||||||
| 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 | ||||||
|  | @ -427,8 +427,8 @@ END | ||||||
| // | // | ||||||
| 
 | 
 | ||||||
| VS_VERSION_INFO VERSIONINFO | VS_VERSION_INFO VERSIONINFO | ||||||
|  FILEVERSION 1,4,4,425 |  FILEVERSION 1,4,4,426 | ||||||
|  PRODUCTVERSION 1,4,4,425 |  PRODUCTVERSION 1,4,4,426 | ||||||
|  FILEFLAGSMASK 0x3fL |  FILEFLAGSMASK 0x3fL | ||||||
| #ifdef _DEBUG | #ifdef _DEBUG | ||||||
|  FILEFLAGS 0x1L |  FILEFLAGS 0x1L | ||||||
|  | @ -445,13 +445,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.4.425" |             VALUE "FileVersion", "1.4.4.426" | ||||||
|             VALUE "InternalName", "Rufus" |             VALUE "InternalName", "Rufus" | ||||||
|             VALUE "LegalCopyright", "© 2011-2014 Pete Batard (GPL v3)" |             VALUE "LegalCopyright", "© 2011-2014 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.4.425" |             VALUE "ProductVersion", "1.4.4.426" | ||||||
|         END |         END | ||||||
|     END |     END | ||||||
|     BLOCK "VarFileInfo" |     BLOCK "VarFileInfo" | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue