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; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * 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, | ||||
|  * 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) | ||||
| { | ||||
| 	DWORD size; | ||||
| 	BOOL s, r = FALSE; | ||||
| 	VOLUME_DISK_EXTENTS DiskExtents; | ||||
| 	BOOL r = FALSE; | ||||
| 	HANDLE hDrive = INVALID_HANDLE_VALUE; | ||||
| 	UINT _drive_type; | ||||
| 	int i = 0; | ||||
|  | @ -318,14 +351,7 @@ static BOOL _GetDriveLettersAndType(DWORD DriveIndex, char* drive_letters, UINT* | |||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		s = DeviceIoControl(hDrive, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, | ||||
| 			&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) { | ||||
| 		if (GetDriveNumber(hDrive, logical_drive) == DriveIndex) { | ||||
| 			r = TRUE; | ||||
| 			if (drive_letters != NULL) | ||||
| 				drive_letters[i++] = *drive; | ||||
|  |  | |||
							
								
								
									
										14
									
								
								src/drive.h
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								src/drive.h
									
										
									
									
									
								
							|  | @ -24,11 +24,25 @@ | |||
| 
 | ||||
| #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); | ||||
| HANDLE GetPhysicalHandle(DWORD DriveIndex, BOOL bWriteAccess, BOOL bLockDrive); | ||||
| char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash, BOOL bSilent); | ||||
| BOOL WaitForLogical(DWORD DriveIndex); | ||||
| HANDLE GetLogicalHandle(DWORD DriveIndex, BOOL bWriteAccess, BOOL bLockDrive); | ||||
| int GetDriveNumber(HANDLE hDrive, char* path); | ||||
| BOOL GetDriveLetters(DWORD DriveIndex, char* drive_letters); | ||||
| UINT GetDriveTypeFromIndex(DWORD DriveIndex); | ||||
| 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_DEVICE_INTERFACE_DATA devint_data; | ||||
| 	PSP_DEVICE_INTERFACE_DETAIL_DATA_A devint_detail_data; | ||||
| 	VOLUME_DISK_EXTENTS DiskExtents; | ||||
| 	DEVINST parent_inst, device_inst; | ||||
| 	DWORD size, i, j, k, datatype, drive_index; | ||||
| 	ULONG list_size[ARRAYSIZE(usbstor_name)], full_list_size; | ||||
| 	HANDLE hDrive; | ||||
| 	LONG maxwidth = 0; | ||||
| 	RECT rect; | ||||
| 	int s, score; | ||||
| 	int s, score, drive_number; | ||||
| 	char drive_letters[27], *devid, *devid_list = NULL, entry_msg[128]; | ||||
| 	char *label, *entry, buffer[MAX_PATH], str[sizeof("0000:0000")+1]; | ||||
| 	uint16_t vid, pid; | ||||
|  | @ -798,21 +797,11 @@ static BOOL GetUSBDevices(DWORD devnum) | |||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
| 			if (!DeviceIoControl(hDrive, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, | ||||
| 				&DiskExtents, sizeof(DiskExtents), &size, NULL) || (size <= 0) || (DiskExtents.NumberOfDiskExtents < 1) ) { | ||||
| 				uprintf("Could not get device number for device %s: %s\n", devint_detail_data->DevicePath, WindowsErrorString()); | ||||
| 			drive_number = GetDriveNumber(hDrive, devint_detail_data->DevicePath); | ||||
| 			if (drive_number < 0) | ||||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
| 			if (DiskExtents.NumberOfDiskExtents >= 2) { | ||||
| 				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; | ||||
| 			drive_index = drive_number + DRIVE_INDEX_MIN; | ||||
| 			if (!IsMediaPresent(drive_index)) { | ||||
| 				uprintf("Device eliminated because it appears to contain no media\n"); | ||||
| 				safe_closehandle(hDrive); | ||||
|  | @ -832,7 +821,7 @@ static BOOL GetUSBDevices(DWORD devnum) | |||
| 
 | ||||
| 				// The empty string is returned for drives that don't have any volumes assigned
 | ||||
| 				if (drive_letters[0] == 0) { | ||||
| 					entry = lmprintf(MSG_046, label, DiskExtents.Extents[0].DiskNumber); | ||||
| 					entry = lmprintf(MSG_046, label, drive_number); | ||||
| 				} else { | ||||
| 					// We have multiple volumes assigned to the same device (multiple partitions)
 | ||||
| 					// 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(&DriveLabel, label); | ||||
| 
 | ||||
| 				IGNORE_RETVAL(ComboBox_SetItemData(hDeviceList, ComboBox_AddStringU(hDeviceList, entry), | ||||
| 					DiskExtents.Extents[0].DiskNumber + DRIVE_INDEX_MIN)); | ||||
| 				IGNORE_RETVAL(ComboBox_SetItemData(hDeviceList, ComboBox_AddStringU(hDeviceList, entry), drive_index)); | ||||
| 				maxwidth = max(maxwidth, GetEntryWidth(hDeviceList, entry)); | ||||
| 				safe_closehandle(hDrive); | ||||
| 				safe_free(devint_detail_data); | ||||
|  |  | |||
							
								
								
									
										12
									
								
								src/rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								src/rufus.rc
									
										
									
									
									
								
							|  | @ -32,7 +32,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL | |||
| 
 | ||||
| IDD_DIALOG DIALOGEX 12, 12, 206, 329 | ||||
| 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 | ||||
| BEGIN | ||||
|     DEFPUSHBUTTON   "Start",IDC_START,94,291,50,14 | ||||
|  | @ -165,7 +165,7 @@ END | |||
| RTL_IDD_DIALOG DIALOGEX 12, 12, 206, 329 | ||||
| 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 | ||||
| CAPTION "Rufus 1.4.4.425" | ||||
| CAPTION "Rufus 1.4.4.426" | ||||
| FONT 8, "MS Shell Dlg", 400, 0, 0x1 | ||||
| BEGIN | ||||
|     DEFPUSHBUTTON   "Start",IDC_START,94,291,50,14 | ||||
|  | @ -427,8 +427,8 @@ END | |||
| // | ||||
| 
 | ||||
| VS_VERSION_INFO VERSIONINFO | ||||
|  FILEVERSION 1,4,4,425 | ||||
|  PRODUCTVERSION 1,4,4,425 | ||||
|  FILEVERSION 1,4,4,426 | ||||
|  PRODUCTVERSION 1,4,4,426 | ||||
|  FILEFLAGSMASK 0x3fL | ||||
| #ifdef _DEBUG | ||||
|  FILEFLAGS 0x1L | ||||
|  | @ -445,13 +445,13 @@ BEGIN | |||
|         BEGIN | ||||
|             VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" | ||||
|             VALUE "FileDescription", "Rufus" | ||||
|             VALUE "FileVersion", "1.4.4.425" | ||||
|             VALUE "FileVersion", "1.4.4.426" | ||||
|             VALUE "InternalName", "Rufus" | ||||
|             VALUE "LegalCopyright", "© 2011-2014 Pete Batard (GPL v3)" | ||||
|             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" | ||||
|             VALUE "OriginalFilename", "rufus.exe" | ||||
|             VALUE "ProductName", "Rufus" | ||||
|             VALUE "ProductVersion", "1.4.4.425" | ||||
|             VALUE "ProductVersion", "1.4.4.426" | ||||
|         END | ||||
|     END | ||||
|     BLOCK "VarFileInfo" | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue