mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[core] low level drive handling redesign
* Better split of physical vs logical * Add handling of unmounted volumes by GUID * Force large FAT32 cheat mode * Improve user messages and fix some UI issues
This commit is contained in:
		
							parent
							
								
									d56615cd20
								
							
						
					
					
						commit
						4da36fa321
					
				
					 7 changed files with 434 additions and 189 deletions
				
			
		
							
								
								
									
										399
									
								
								src/drive.c
									
										
									
									
									
								
							
							
						
						
									
										399
									
								
								src/drive.c
									
										
									
									
									
								
							|  | @ -38,106 +38,42 @@ RUFUS_DRIVE_INFO SelectedDrive; | ||||||
| extern BOOL enable_fixed_disks; | extern BOOL enable_fixed_disks; | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Open a drive or volume with optional write and lock access |  * Working with drive indexes quite risky (left unchecked,inadvertently passing 0 as | ||||||
|  * Returns INVALID_HANDLE_VALUE (/!\ which is DIFFERENT from NULL /!\) on failure. |  * index would return a handle to C:, which we might then proceed to unknowingly | ||||||
|  * This call is quite risky (left unchecked, inadvertently passing 0 as index would |  * clear the MBR of!), so we mitigate the risk by forcing our indexes to belong to | ||||||
|  * return a handle to C:, which we might then proceed to unknowingly repartition!), |  * the specific range [DRIVE_INDEX_MIN; DRIVE_INDEX_MAX]. | ||||||
|  * so we apply the following mitigation factors: |  | ||||||
|  * - Valid indexes must belong to a specific range [DRIVE_INDEX_MIN; DRIVE_INDEX_MAX] |  | ||||||
|  * - When opening for write access, we lock the volume. If that fails, which would |  | ||||||
|  *   typically be the case on C:\ or any other drive in use, we report failure |  | ||||||
|  * - We report the full path of any drive that was successfully opened for write acces |  | ||||||
|  */ |  */ | ||||||
| HANDLE GetDriveHandle(DWORD DriveIndex, char* DriveLetter, BOOL bWriteAccess, BOOL bLockDrive) | #define CheckDriveIndex(DriveIndex) do { \ | ||||||
|  | 	if ((DriveIndex < DRIVE_INDEX_MIN) || (DriveIndex > DRIVE_INDEX_MAX)) { \ | ||||||
|  | 		uprintf("WARNING: Bad index value. Please check the code!\n"); \ | ||||||
|  | 		goto out; \ | ||||||
|  | 	} \ | ||||||
|  | 	DriveIndex -= DRIVE_INDEX_MIN; } while (0) | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Open a drive or volume with optional write and lock access | ||||||
|  |  * Return INVALID_HANDLE_VALUE (/!\ which is DIFFERENT from NULL /!\) on failure. | ||||||
|  |  */ | ||||||
|  | static HANDLE GetHandle(char* Path, BOOL bWriteAccess, BOOL bLockDrive) | ||||||
| { | { | ||||||
| 	BOOL r; |  | ||||||
| 	DWORD size; | 	DWORD size; | ||||||
| 	HANDLE hDrive = INVALID_HANDLE_VALUE; | 	HANDLE hDrive = INVALID_HANDLE_VALUE; | ||||||
| 	STORAGE_DEVICE_NUMBER_REDEF device_number = {0}; |  | ||||||
| 	UINT drive_type; |  | ||||||
| 	char drives[26*4];	/* "D:\", "E:\", etc. */ |  | ||||||
| 	char *drive = drives; |  | ||||||
| 	char logical_drive[] = "\\\\.\\#:"; |  | ||||||
| 	char physical_drive[24]; |  | ||||||
| 
 | 
 | ||||||
| 	DriveIndex &= DRIVE_INDEX_MASK; | 	if (Path == NULL) | ||||||
| 	if ((DriveIndex < DRIVE_INDEX_MIN) || (DriveIndex > DRIVE_INDEX_MAX)) { | 		goto out; | ||||||
| 		uprintf("WARNING: Bad index value. Please check the code!\n"); | 	hDrive = CreateFileA(Path, GENERIC_READ|(bWriteAccess?GENERIC_WRITE:0), | ||||||
|  | 		FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); | ||||||
|  | 	if (hDrive == INVALID_HANDLE_VALUE) { | ||||||
|  | 		uprintf("Could not open drive %s: %s\n", Path, WindowsErrorString()); | ||||||
|  | 		goto out; | ||||||
| 	} | 	} | ||||||
| 	DriveIndex -= DRIVE_INDEX_MIN; |  | ||||||
| 
 | 
 | ||||||
| 	// If no drive letter is requested, open a physical drive
 | 	if (bWriteAccess) { | ||||||
| 	if (DriveLetter == NULL) { | 		uprintf("Caution: Opened drive %s for write access\n", Path); | ||||||
| 		safe_sprintf(physical_drive, sizeof(physical_drive), "\\\\.\\PHYSICALDRIVE%d", DriveIndex); |  | ||||||
| 		hDrive = CreateFileA(physical_drive, GENERIC_READ|(bWriteAccess?GENERIC_WRITE:0), |  | ||||||
| 			FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); |  | ||||||
| 		if (hDrive == INVALID_HANDLE_VALUE) { |  | ||||||
| 			uprintf("Could not open drive %s: %s\n", physical_drive, WindowsErrorString()); |  | ||||||
| 			goto out; |  | ||||||
| 		} |  | ||||||
| 		if (bWriteAccess) { |  | ||||||
| 			uprintf("Caution: Opened %s drive for write access\n", &physical_drive[4]); |  | ||||||
| 		} |  | ||||||
| 	} else { |  | ||||||
| 		*DriveLetter = ' '; |  | ||||||
| 		size = GetLogicalDriveStringsA(sizeof(drives), drives); |  | ||||||
| 		if (size == 0) { |  | ||||||
| 			uprintf("GetLogicalDriveStrings failed: %s\n", WindowsErrorString()); |  | ||||||
| 			goto out; |  | ||||||
| 		} |  | ||||||
| 		if (size > sizeof(drives)) { |  | ||||||
| 			uprintf("GetLogicalDriveStrings: buffer too small (required %d vs %d)\n", size, sizeof(drives)); |  | ||||||
| 			goto out; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		hDrive = INVALID_HANDLE_VALUE; |  | ||||||
| 		for ( ;*drive; drive += safe_strlen(drive)+1) { |  | ||||||
| 			if (!isalpha(*drive)) |  | ||||||
| 				continue; |  | ||||||
| 			*drive = (char)toupper((int)*drive); |  | ||||||
| 			if (*drive < 'C') { |  | ||||||
| 				continue; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			/* IOCTL_STORAGE_GET_DEVICE_NUMBER's STORAGE_DEVICE_NUMBER.DeviceNumber is
 |  | ||||||
| 			   not unique! An HDD, a DVD and probably other drives can have the same |  | ||||||
| 			   value there => Use GetDriveType() to filter out unwanted devices. |  | ||||||
| 			   See https://github.com/pbatard/rufus/issues/32 for details. */
 |  | ||||||
| 			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) && ((!enable_fixed_disks) || (drive_type != DRIVE_FIXED))) |  | ||||||
| 				continue; |  | ||||||
| 
 |  | ||||||
| 			safe_sprintf(logical_drive, sizeof(logical_drive), "\\\\.\\%c:", drive[0]); |  | ||||||
| 			hDrive = CreateFileA(logical_drive, GENERIC_READ|(bWriteAccess?GENERIC_WRITE:0), |  | ||||||
| 				FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); |  | ||||||
| 			if (hDrive == INVALID_HANDLE_VALUE) { |  | ||||||
| 				uprintf("Warning: could not open drive %c: %s\n", drive[0], WindowsErrorString()); |  | ||||||
| 				continue; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			r = DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, |  | ||||||
| 				0, &device_number, sizeof(device_number), &size, NULL); |  | ||||||
| 			if ((!r) || (size <= 0)) { |  | ||||||
| 				uprintf("IOCTL_STORAGE_GET_DEVICE_NUMBER failed for device %s: %s\n", |  | ||||||
| 					logical_drive, WindowsErrorString()); |  | ||||||
| 			} else if (device_number.DeviceNumber == DriveIndex) { |  | ||||||
| 				break; |  | ||||||
| 			} |  | ||||||
| 			safe_closehandle(hDrive); |  | ||||||
| 		} |  | ||||||
| 		if (hDrive == INVALID_HANDLE_VALUE) { |  | ||||||
| 			goto out; |  | ||||||
| 		} |  | ||||||
| 		if (bWriteAccess) { |  | ||||||
| 			uprintf("Caution: Opened %s drive for write access\n", &logical_drive[4]); |  | ||||||
| 		} |  | ||||||
| 		*DriveLetter = *drive?*drive:' '; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if ((bLockDrive) && (!DeviceIoControl(hDrive, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &size, NULL))) { | 	if ((bLockDrive) && (!DeviceIoControl(hDrive, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &size, NULL))) { | ||||||
| 		uprintf("Could not get exclusive access to %s %s\n", logical_drive, WindowsErrorString()); | 		uprintf("Could not get exclusive access to device %s: %s\n", Path, WindowsErrorString()); | ||||||
| 		safe_closehandle(hDrive); | 		safe_closehandle(hDrive); | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
|  | @ -146,12 +82,244 @@ out: | ||||||
| 	return hDrive; | 	return hDrive; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* 
 | ||||||
|  |  * Return the path to access the physical drive, or NULL on error. | ||||||
|  |  * The string is allocated and must be freed (to ensure concurrent access) | ||||||
|  |  */ | ||||||
|  | char* GetPhysicalName(DWORD DriveIndex) | ||||||
|  | { | ||||||
|  | 	BOOL success = FALSE; | ||||||
|  | 	char physical_name[24]; | ||||||
|  | 	char* r = NULL; | ||||||
|  | 
 | ||||||
|  | 	CheckDriveIndex(DriveIndex); | ||||||
|  | 	safe_sprintf(physical_name, sizeof(physical_name), "\\\\.\\PHYSICALDRIVE%d", DriveIndex); | ||||||
|  | 	success = TRUE; | ||||||
|  | out: | ||||||
|  | 	return (success)?safe_strdup(physical_name):NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* 
 | ||||||
|  |  * Return a handle to the physical drive identified by DriveIndex | ||||||
|  |  */ | ||||||
|  | HANDLE GetPhysicalHandle(DWORD DriveIndex, BOOL bWriteAccess, BOOL bLockDrive) | ||||||
|  | { | ||||||
|  | 	HANDLE hPhysical = INVALID_HANDLE_VALUE; | ||||||
|  | 	char* PhysicalPath = GetPhysicalName(DriveIndex); | ||||||
|  | 	hPhysical = GetHandle(PhysicalPath, bWriteAccess, bLockDrive); | ||||||
|  | 	safe_free(PhysicalPath); | ||||||
|  | 	return hPhysical; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Return the first GUID volume name for the associated drive or NULL if not found
 | ||||||
|  | // See http://msdn.microsoft.com/en-us/library/cc542456.aspx
 | ||||||
|  | // The returned string is allocated and must be freed
 | ||||||
|  | // TODO: a drive may have multiple volumes - should we handle those?
 | ||||||
|  | char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash) | ||||||
|  | { | ||||||
|  | 	BOOL success = FALSE; | ||||||
|  | 	char volume_name[MAX_PATH]; | ||||||
|  | 	HANDLE hDrive = INVALID_HANDLE_VALUE, hVolume = INVALID_HANDLE_VALUE; | ||||||
|  | 	size_t len; | ||||||
|  | 	char path[MAX_PATH]; | ||||||
|  | 	VOLUME_DISK_EXTENTS DiskExtents; | ||||||
|  | 	DWORD size; | ||||||
|  | 	UINT drive_type; | ||||||
|  | 	int i, j; | ||||||
|  | 	static const char* ignore_device[] = { "\\Device\\CdRom", "\\Device\\Floppy" }; | ||||||
|  | 
 | ||||||
|  | 	CheckDriveIndex(DriveIndex); | ||||||
|  | 
 | ||||||
|  | 	for (i=0; hDrive == INVALID_HANDLE_VALUE; i++) { | ||||||
|  | 		if (i == 0) { | ||||||
|  | 			hVolume = FindFirstVolumeA(volume_name, sizeof(volume_name)); | ||||||
|  | 			if (hVolume == INVALID_HANDLE_VALUE) { | ||||||
|  | 				uprintf("Could not access first GUID volume: %s\n", WindowsErrorString()); | ||||||
|  | 				goto out; | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			if (!FindNextVolumeA(hVolume, volume_name, sizeof(volume_name))) { | ||||||
|  | 				if (GetLastError() != ERROR_NO_MORE_FILES) { | ||||||
|  | 					uprintf("Could not access next GUID volume: %s\n", WindowsErrorString()); | ||||||
|  | 				} | ||||||
|  | 				goto out; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// Sanity checks
 | ||||||
|  | 		len = safe_strlen(volume_name); | ||||||
|  | 		if ((len <= 1) || (safe_strnicmp(volume_name, "\\\\?\\", 4) != 0) || (volume_name[len-1] != '\\')) { | ||||||
|  | 			uprintf("'%s' is not a GUID volume name\n", volume_name); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		drive_type = GetDriveTypeA(volume_name); | ||||||
|  | 		// 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) && ((!enable_fixed_disks) || (drive_type != DRIVE_FIXED))) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		volume_name[len-1] = 0; | ||||||
|  | 
 | ||||||
|  | 		if (QueryDosDeviceA(&volume_name[4], path, sizeof(path)) == 0) { | ||||||
|  | 			uprintf("Failed to get device path for GUID volume '%s': %s\n", volume_name, WindowsErrorString()); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		for (j=0; (j<ARRAYSIZE(ignore_device)) && | ||||||
|  | 			(safe_strnicmp(path, ignore_device[j], safe_strlen(ignore_device[j])) != 0); j++); | ||||||
|  | 		if (j < ARRAYSIZE(ignore_device)) { | ||||||
|  | 			uprintf("Skipping GUID volume for '%s'\n", path); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// If we can't have FILE_SHARE_WRITE, forget it
 | ||||||
|  | 		hDrive = CreateFileA(volume_name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); | ||||||
|  | 		if (hDrive == INVALID_HANDLE_VALUE) { | ||||||
|  | 			uprintf("Could not open GUID volume '%s': %s\n", volume_name, WindowsErrorString()); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if ((!DeviceIoControl(hDrive, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, | ||||||
|  | 			&DiskExtents, sizeof(DiskExtents), &size, NULL)) || (size <= 0)) { | ||||||
|  | 			uprintf("Could not get Disk Extents: %s\n", WindowsErrorString()); | ||||||
|  | 			safe_closehandle(hDrive); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		safe_closehandle(hDrive); | ||||||
|  | 		if ((DiskExtents.NumberOfDiskExtents >= 1) && (DiskExtents.Extents[0].DiskNumber == DriveIndex)) { | ||||||
|  | 			if (bKeepTrailingBackslash) | ||||||
|  | 				volume_name[len-1] = '\\'; | ||||||
|  | 			success = TRUE; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	if (hVolume != INVALID_HANDLE_VALUE) | ||||||
|  | 		FindVolumeClose(hVolume); | ||||||
|  | 	return (success)?safe_strdup(volume_name):NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* 
 | ||||||
|  |  * Return a handle to the first logical volume on the disk identified by DriveIndex | ||||||
|  |  */ | ||||||
|  | HANDLE GetLogicalHandle(DWORD DriveIndex, BOOL bWriteAccess, BOOL bLockDrive) | ||||||
|  | { | ||||||
|  | 	HANDLE hLogical = INVALID_HANDLE_VALUE; | ||||||
|  | 	char* LogicalPath = GetLogicalName(DriveIndex, FALSE); | ||||||
|  | 	hLogical = GetHandle(LogicalPath, bWriteAccess, bLockDrive); | ||||||
|  | 	safe_free(LogicalPath); | ||||||
|  | 	return hLogical; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Returns the first drive letter for a volume located on the drive identified by DriveIndex | ||||||
|  |  * TODO: should we return all the drive letters? | ||||||
|  |  */ | ||||||
|  | char GetDriveLetter(DWORD DriveIndex) | ||||||
|  | { | ||||||
|  | 	DWORD size; | ||||||
|  | 	BOOL r; | ||||||
|  | 	STORAGE_DEVICE_NUMBER_REDEF device_number = {0}; | ||||||
|  | 	UINT drive_type; | ||||||
|  | 	HANDLE hDrive = INVALID_HANDLE_VALUE; | ||||||
|  | 	char *drive, drives[26*4];	/* "D:\", "E:\", etc. */ | ||||||
|  | 	char logical_drive[] = "\\\\.\\#:"; | ||||||
|  | 	char drive_letter = ' '; | ||||||
|  | 	CheckDriveIndex(DriveIndex); | ||||||
|  | 
 | ||||||
|  | 	size = GetLogicalDriveStringsA(sizeof(drives), drives); | ||||||
|  | 	if (size == 0) { | ||||||
|  | 		uprintf("GetLogicalDriveStrings failed: %s\n", WindowsErrorString()); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 	if (size > sizeof(drives)) { | ||||||
|  | 		uprintf("GetLogicalDriveStrings: buffer too small (required %d vs %d)\n", size, sizeof(drives)); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (drive = drives ;*drive; drive += safe_strlen(drive)+1) { | ||||||
|  | 		if (!isalpha(*drive)) | ||||||
|  | 			continue; | ||||||
|  | 		*drive = (char)toupper((int)*drive); | ||||||
|  | 		if (*drive < 'C') { | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		/* IOCTL_STORAGE_GET_DEVICE_NUMBER's STORAGE_DEVICE_NUMBER.DeviceNumber is
 | ||||||
|  | 			not unique! An HDD, a DVD and probably other drives can have the same | ||||||
|  | 			value there => Use GetDriveType() to filter out unwanted devices. | ||||||
|  | 			See https://github.com/pbatard/rufus/issues/32 for details. */
 | ||||||
|  | 		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) && ((!enable_fixed_disks) || (drive_type != DRIVE_FIXED))) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		safe_sprintf(logical_drive, sizeof(logical_drive), "\\\\.\\%c:", drive[0]); | ||||||
|  | 		hDrive = CreateFileA(logical_drive, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); | ||||||
|  | 		if (hDrive == INVALID_HANDLE_VALUE) { | ||||||
|  | 			uprintf("Warning: could not open drive %c: %s\n", drive[0], WindowsErrorString()); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		r = DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, | ||||||
|  | 			0, &device_number, sizeof(device_number), &size, NULL); | ||||||
|  | 		safe_closehandle(hDrive); | ||||||
|  | 		if ((!r) || (size <= 0)) { | ||||||
|  | 			uprintf("Could not get device number for device %s: %s\n", | ||||||
|  | 				logical_drive, WindowsErrorString()); | ||||||
|  | 		} else if (device_number.DeviceNumber == DriveIndex) { | ||||||
|  | 			drive_letter = *drive; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	return drive_letter; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Return the next unused drive letter from the system | ||||||
|  |  */ | ||||||
|  | char GetUnusedDriveLetter(void) | ||||||
|  | { | ||||||
|  | 	DWORD size; | ||||||
|  | 	char drive_letter, *drive, drives[26*4];	/* "D:\", "E:\", etc. */ | ||||||
|  | 
 | ||||||
|  | 	size = GetLogicalDriveStringsA(sizeof(drives), drives); | ||||||
|  | 	if (size == 0) { | ||||||
|  | 		uprintf("GetLogicalDriveStrings failed: %s\n", WindowsErrorString()); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 	if (size > sizeof(drives)) { | ||||||
|  | 		uprintf("GetLogicalDriveStrings: buffer too small (required %d vs %d)\n", size, sizeof(drives)); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (drive_letter = 'C'; drive_letter < 'Z'; drive_letter++) { | ||||||
|  | 		for (drive = drives ;*drive; drive += safe_strlen(drive)+1) { | ||||||
|  | 			if (!isalpha(*drive)) | ||||||
|  | 				continue; | ||||||
|  | 			if (drive_letter == (char)toupper((int)*drive)) | ||||||
|  | 				break; | ||||||
|  | 		} | ||||||
|  | 		if (!*drive) | ||||||
|  | 			break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | out: | ||||||
|  | 	return (drive_letter>'Z')?' ':drive_letter; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Return the drive letter and volume label |  * Return the drive letter and volume label | ||||||
|  |  * If the drive doesn't have a volume assigned, space is returned for the letter | ||||||
|  */ |  */ | ||||||
| BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label) | BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label) | ||||||
| { | { | ||||||
| 	HANDLE hDrive, hPhysical; | 	HANDLE hPhysical; | ||||||
| 	DWORD size; | 	DWORD size; | ||||||
| 	char AutorunPath[] = "#:\\autorun.inf", *AutorunLabel = NULL; | 	char AutorunPath[] = "#:\\autorun.inf", *AutorunLabel = NULL; | ||||||
| 	wchar_t wDrivePath[] = L"#:\\"; | 	wchar_t wDrivePath[] = L"#:\\"; | ||||||
|  | @ -160,19 +328,19 @@ BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label) | ||||||
| 
 | 
 | ||||||
| 	*label = STR_NO_LABEL; | 	*label = STR_NO_LABEL; | ||||||
| 
 | 
 | ||||||
| 	hDrive = GetDriveHandle(DriveIndex, letter, FALSE, FALSE); | 	*letter = GetDriveLetter(DriveIndex); | ||||||
| 	if (hDrive == INVALID_HANDLE_VALUE) { | 	if (*letter == ' ') { | ||||||
| 		// Assume we have a raw drive without volume assigned if enable_fixed_disk is true
 | 		// Drive without volume assigned
 | ||||||
| 		return enable_fixed_disks;  | 		// TODO: only with fixed?
 | ||||||
|  | 		return TRUE;  | ||||||
| 	} | 	} | ||||||
| 	safe_closehandle(hDrive); |  | ||||||
| 	AutorunPath[0] = *letter; | 	AutorunPath[0] = *letter; | ||||||
| 	wDrivePath[0] = *letter; | 	wDrivePath[0] = *letter; | ||||||
| 
 | 
 | ||||||
| 	// Try to read an extended label from autorun first. Fallback to regular label if not found.
 | 	// Try to read an extended label from autorun first. Fallback to regular label if not found.
 | ||||||
| 	// In the case of card readers with no card, users can get an annoying popup asking them
 | 	// In the case of card readers with no card, users can get an annoying popup asking them
 | ||||||
| 	// to insert media. Use IOCTL_STORAGE_CHECK_VERIFY to prevent this
 | 	// to insert media. Use IOCTL_STORAGE_CHECK_VERIFY to prevent this
 | ||||||
| 	hPhysical = GetDriveHandle(DriveIndex, NULL, FALSE, FALSE); | 	hPhysical = GetPhysicalHandle(DriveIndex, FALSE, FALSE); | ||||||
| 	if (DeviceIoControl(hPhysical, IOCTL_STORAGE_CHECK_VERIFY, NULL, 0, NULL, 0, &size, NULL)) | 	if (DeviceIoControl(hPhysical, IOCTL_STORAGE_CHECK_VERIFY, NULL, 0, NULL, 0, &size, NULL)) | ||||||
| 		AutorunLabel = get_token_data_file("label", AutorunPath); | 		AutorunLabel = get_token_data_file("label", AutorunPath); | ||||||
| 	else if (GetLastError() == ERROR_NOT_READY) | 	else if (GetLastError() == ERROR_NOT_READY) | ||||||
|  | @ -196,28 +364,29 @@ BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label) | ||||||
| /*
 | /*
 | ||||||
|  * Fill the drive properties (size, FS, etc) |  * Fill the drive properties (size, FS, etc) | ||||||
|  */ |  */ | ||||||
| BOOL GetDrivePartitionData(DWORD DeviceNumber, char* FileSystemName, DWORD FileSystemNameSize) | BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSystemNameSize) | ||||||
| { | { | ||||||
| 	BOOL r; | 	BOOL r; | ||||||
| 	HANDLE hDrive; | 	HANDLE hPhysical; | ||||||
| 	DWORD size; | 	DWORD size; | ||||||
| 	BYTE geometry[128], layout[1024], part_type; | 	BYTE geometry[128], layout[1024], part_type; | ||||||
| 	void* disk_geometry = (void*)geometry; | 	void* disk_geometry = (void*)geometry; | ||||||
| 	void* drive_layout = (void*)layout; | 	void* drive_layout = (void*)layout; | ||||||
| 	PDISK_GEOMETRY_EX DiskGeometry = (PDISK_GEOMETRY_EX)disk_geometry; | 	PDISK_GEOMETRY_EX DiskGeometry = (PDISK_GEOMETRY_EX)disk_geometry; | ||||||
| 	PDRIVE_LAYOUT_INFORMATION_EX DriveLayout = (PDRIVE_LAYOUT_INFORMATION_EX)drive_layout; | 	PDRIVE_LAYOUT_INFORMATION_EX DriveLayout = (PDRIVE_LAYOUT_INFORMATION_EX)drive_layout; | ||||||
| 	char DrivePath[] = "#:\\", tmp[256]; | 	char* volume_name; | ||||||
|  | 	char tmp[256]; | ||||||
| 	DWORD i, nb_partitions = 0; | 	DWORD i, nb_partitions = 0; | ||||||
| 
 | 
 | ||||||
| 	hDrive = GetDriveHandle(DeviceNumber, NULL, FALSE, FALSE); | 	hPhysical = GetPhysicalHandle(DriveIndex, FALSE, FALSE); | ||||||
| 	if (hDrive == INVALID_HANDLE_VALUE) | 	if (hPhysical == INVALID_HANDLE_VALUE) | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| 
 | 
 | ||||||
| 	r = DeviceIoControl(hDrive, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,  | 	r = DeviceIoControl(hPhysical, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,  | ||||||
| 			NULL, 0, geometry, sizeof(geometry), &size, NULL); | 			NULL, 0, geometry, sizeof(geometry), &size, NULL); | ||||||
| 	if (!r || size <= 0) { | 	if (!r || size <= 0) { | ||||||
| 		uprintf("IOCTL_DISK_GET_DRIVE_GEOMETRY_EX failed for drive %c: %s\n", DrivePath[0], WindowsErrorString()); | 		uprintf("Could not get geometry for drive #%d: %s\n", DriveIndex, WindowsErrorString()); | ||||||
| 		safe_closehandle(hDrive); | 		safe_closehandle(hPhysical); | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| 	} | 	} | ||||||
| 	SelectedDrive.DiskSize = DiskGeometry->DiskSize.QuadPart; | 	SelectedDrive.DiskSize = DiskGeometry->DiskSize.QuadPart; | ||||||
|  | @ -226,10 +395,10 @@ BOOL GetDrivePartitionData(DWORD DeviceNumber, char* FileSystemName, DWORD FileS | ||||||
| 	uprintf("Cylinders: %lld, TracksPerCylinder: %d, SectorsPerTrack: %d\n", | 	uprintf("Cylinders: %lld, TracksPerCylinder: %d, SectorsPerTrack: %d\n", | ||||||
| 		DiskGeometry->Geometry.Cylinders, DiskGeometry->Geometry.TracksPerCylinder, DiskGeometry->Geometry.SectorsPerTrack); | 		DiskGeometry->Geometry.Cylinders, DiskGeometry->Geometry.TracksPerCylinder, DiskGeometry->Geometry.SectorsPerTrack); | ||||||
| 
 | 
 | ||||||
| 	r = DeviceIoControl(hDrive, IOCTL_DISK_GET_DRIVE_LAYOUT_EX,  | 	r = DeviceIoControl(hPhysical, IOCTL_DISK_GET_DRIVE_LAYOUT_EX,  | ||||||
| 			NULL, 0, layout, sizeof(layout), &size, NULL ); | 			NULL, 0, layout, sizeof(layout), &size, NULL ); | ||||||
| 	if (!r || size <= 0) { | 	if (!r || size <= 0) { | ||||||
| 		uprintf("IOCTL_DISK_GET_DRIVE_LAYOUT_EX failed for drive %c: %s\n", DrivePath[0], WindowsErrorString()); | 		uprintf("Could not get layout for drive #d: %s\n", DriveIndex, WindowsErrorString()); | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -281,17 +450,23 @@ BOOL GetDrivePartitionData(DWORD DeviceNumber, char* FileSystemName, DWORD FileS | ||||||
| 		uprintf("Partition type: RAW\n"); | 		uprintf("Partition type: RAW\n"); | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 	safe_closehandle(hDrive); | 	safe_closehandle(hPhysical); | ||||||
| 
 | 
 | ||||||
| 	// Populate the filesystem data
 | 	// Populate the filesystem data
 | ||||||
| 	if (!GetVolumeInformationA(DrivePath, NULL, 0, NULL, NULL, NULL, FileSystemName, FileSystemNameSize)) { | 	volume_name = GetLogicalName(DriveIndex, TRUE); | ||||||
|  | 	if ((volume_name == NULL) || (!GetVolumeInformationA(volume_name, NULL, 0, NULL, NULL, NULL, FileSystemName, FileSystemNameSize))) { | ||||||
|  | 		uprintf("Did not get volume information for disk 0x%02x\n", DriveIndex); | ||||||
| 		FileSystemName[0] = 0; | 		FileSystemName[0] = 0; | ||||||
| 	} | 	} | ||||||
|  | 	safe_free(volume_name); | ||||||
| 
 | 
 | ||||||
| 	return TRUE; | 	return TRUE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOL UnmountDrive(HANDLE hDrive) | /*
 | ||||||
|  |  * Unmount of volume using the DISMOUNT_VOLUME ioctl | ||||||
|  |  */ | ||||||
|  | BOOL UnmountVolume(HANDLE hDrive) | ||||||
| { | { | ||||||
| 	DWORD size; | 	DWORD size; | ||||||
| 
 | 
 | ||||||
|  | @ -439,7 +614,7 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m | ||||||
| 	r = DeviceIoControl(hDrive, IOCTL_DISK_CREATE_DISK, | 	r = DeviceIoControl(hDrive, IOCTL_DISK_CREATE_DISK, | ||||||
| 			(BYTE*)&CreateDisk, size, NULL, 0, &size, NULL ); | 			(BYTE*)&CreateDisk, size, NULL, 0, &size, NULL ); | ||||||
| 	if (!r) { | 	if (!r) { | ||||||
| 		uprintf("IOCTL_DISK_CREATE_DISK failed: %s\n", WindowsErrorString()); | 		uprintf("Could not reset disk: %s\n", WindowsErrorString()); | ||||||
| 		safe_closehandle(hDrive); | 		safe_closehandle(hDrive); | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| 	} | 	} | ||||||
|  | @ -448,7 +623,7 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m | ||||||
| 	r = DeviceIoControl(hDrive, IOCTL_DISK_SET_DRIVE_LAYOUT_EX, | 	r = DeviceIoControl(hDrive, IOCTL_DISK_SET_DRIVE_LAYOUT_EX, | ||||||
| 			(BYTE*)&DriveLayoutEx, size, NULL, 0, &size, NULL ); | 			(BYTE*)&DriveLayoutEx, size, NULL, 0, &size, NULL ); | ||||||
| 	if (!r) { | 	if (!r) { | ||||||
| 		uprintf("IOCTL_DISK_SET_DRIVE_LAYOUT_EX failed: %s\n", WindowsErrorString()); | 		uprintf("Could not set drive layout: %s\n", WindowsErrorString()); | ||||||
| 		safe_closehandle(hDrive); | 		safe_closehandle(hDrive); | ||||||
| 		return FALSE; | 		return FALSE; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
							
								
								
									
										164
									
								
								src/format.c
									
										
									
									
									
								
							
							
						
						
									
										164
									
								
								src/format.c
									
										
									
									
									
								
							|  | @ -54,6 +54,7 @@ static int task_number = 0; | ||||||
| /* Number of steps for each FS for FCC_STRUCTURE_PROGRESS */ | /* Number of steps for each FS for FCC_STRUCTURE_PROGRESS */ | ||||||
| const int nb_steps[FS_MAX] = { 5, 5, 12, 10 }; | const int nb_steps[FS_MAX] = { 5, 5, 12, 10 }; | ||||||
| static int fs_index = 0; | static int fs_index = 0; | ||||||
|  | BOOL force_large_fat32 = FALSE; | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * FormatEx callback. Return FALSE to halt operations |  * FormatEx callback. Return FALSE to halt operations | ||||||
|  | @ -274,6 +275,7 @@ static void ToValidLabel(WCHAR* name, BOOL bFAT) | ||||||
|  * ----- |  * ----- | ||||||
|  * 1d02h |  * 1d02h | ||||||
|  */ |  */ | ||||||
|  | // TODO: use that for Format "classic"
 | ||||||
| static DWORD GetVolumeID(void) | static DWORD GetVolumeID(void) | ||||||
| { | { | ||||||
| 	SYSTEMTIME s; | 	SYSTEMTIME s; | ||||||
|  | @ -331,7 +333,6 @@ static DWORD GetFATSizeSectors(DWORD DskSize, DWORD ReservedSecCnt, DWORD SecPer | ||||||
| static BOOL FormatFAT32(DWORD DriveIndex) | static BOOL FormatFAT32(DWORD DriveIndex) | ||||||
| { | { | ||||||
| 	BOOL r = FALSE; | 	BOOL r = FALSE; | ||||||
| 	char DriveLetter; |  | ||||||
| 	DWORD i; | 	DWORD i; | ||||||
| 	HANDLE hLogicalVolume; | 	HANDLE hLogicalVolume; | ||||||
| 	DWORD cbRet; | 	DWORD cbRet; | ||||||
|  | @ -342,7 +343,8 @@ static BOOL FormatFAT32(DWORD DriveIndex) | ||||||
| 	DWORD NumFATs = 2; | 	DWORD NumFATs = 2; | ||||||
| 	DWORD BackupBootSect = 6; | 	DWORD BackupBootSect = 6; | ||||||
| 	DWORD VolumeId = 0; // calculated before format
 | 	DWORD VolumeId = 0; // calculated before format
 | ||||||
| 	WCHAR wLabel[64], wDriveName[] = L"#:\\"; | 	char* VolumeName = NULL; | ||||||
|  | 	WCHAR wLabel[64], *wVolumeName = NULL; | ||||||
| 	DWORD BurstSize = 128; // Zero in blocks of 64K typically
 | 	DWORD BurstSize = 128; // Zero in blocks of 64K typically
 | ||||||
| 
 | 
 | ||||||
| 	// Calculated later
 | 	// Calculated later
 | ||||||
|  | @ -365,18 +367,17 @@ static BOOL FormatFAT32(DWORD DriveIndex) | ||||||
| 	// Debug temp vars
 | 	// Debug temp vars
 | ||||||
| 	ULONGLONG FatNeeded, ClusterCount; | 	ULONGLONG FatNeeded, ClusterCount; | ||||||
| 
 | 
 | ||||||
| 	PrintStatus(0, TRUE, "Formatting..."); | 	PrintStatus(0, TRUE, "Formatting (Large FAT32)..."); | ||||||
| 	uprintf("Using large FAT32 format method\n"); |  | ||||||
| 	VolumeId = GetVolumeID(); | 	VolumeId = GetVolumeID(); | ||||||
| 
 | 
 | ||||||
| 	// Open the drive (volume should already be locked)
 | 	// Open the drive (volume should already be locked)
 | ||||||
| 	hLogicalVolume = GetDriveHandle(DriveIndex, &DriveLetter, TRUE, FALSE); | 	hLogicalVolume = GetLogicalHandle(DriveIndex, TRUE, FALSE); | ||||||
| 	if (IS_ERROR(FormatStatus)) goto out; | 	if (IS_ERROR(FormatStatus)) goto out; | ||||||
| 	if (hLogicalVolume == INVALID_HANDLE_VALUE) | 	if (hLogicalVolume == INVALID_HANDLE_VALUE) | ||||||
| 		die("Could not access logical volume\n", ERROR_OPEN_FAILED); | 		die("Could not access logical volume\n", ERROR_OPEN_FAILED); | ||||||
| 
 | 
 | ||||||
| 	// Make sure we get exclusive access
 | 	// Make sure we get exclusive access
 | ||||||
| 	if (!UnmountDrive(hLogicalVolume)) | 	if (!UnmountVolume(hLogicalVolume)) | ||||||
| 		return r; | 		return r; | ||||||
| 
 | 
 | ||||||
| 	// Work out drive params
 | 	// Work out drive params
 | ||||||
|  | @ -526,7 +527,7 @@ static BOOL FormatFAT32(DWORD DriveIndex) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Now we're commited - print some info first
 | 	// Now we're commited - print some info first
 | ||||||
| 	uprintf("Size : %gGB %u sectors\n", (double) (piDrive.PartitionLength.QuadPart / (1000*1000*1000)), TotalSectors); | 	uprintf("Size : %s %u sectors\n", SizeToHumanReadable(piDrive.PartitionLength), TotalSectors); | ||||||
| 	uprintf("Cluster size %d bytes, %d Bytes Per Sector\n", SectorsPerCluster*BytesPerSect, BytesPerSect); | 	uprintf("Cluster size %d bytes, %d Bytes Per Sector\n", SectorsPerCluster*BytesPerSect, BytesPerSect); | ||||||
| 	uprintf("Volume ID is %x:%x\n", VolumeId>>16, VolumeId&0xffff); | 	uprintf("Volume ID is %x:%x\n", VolumeId>>16, VolumeId&0xffff); | ||||||
| 	uprintf("%d Reserved Sectors, %d Sectors per FAT, %d FATs\n", ReservedSectCount, FatSize, NumFATs); | 	uprintf("%d Reserved Sectors, %d Sectors per FAT, %d FATs\n", ReservedSectCount, FatSize, NumFATs); | ||||||
|  | @ -578,18 +579,22 @@ static BOOL FormatFAT32(DWORD DriveIndex) | ||||||
| 	// Set the FAT32 volume label
 | 	// Set the FAT32 volume label
 | ||||||
| 	GetWindowTextW(hLabel, wLabel, ARRAYSIZE(wLabel)); | 	GetWindowTextW(hLabel, wLabel, ARRAYSIZE(wLabel)); | ||||||
| 	ToValidLabel(wLabel, TRUE); | 	ToValidLabel(wLabel, TRUE); | ||||||
| 	wDriveName[0] = DriveLetter; |  | ||||||
| 	// Handle must be closed for SetVolumeLabel to work
 | 	// Handle must be closed for SetVolumeLabel to work
 | ||||||
| 	safe_closehandle(hLogicalVolume); | 	safe_closehandle(hLogicalVolume); | ||||||
| 
 | 	PrintStatus(0, TRUE, "Setting Label (This may take while)..."); | ||||||
| 	PrintStatus(0, TRUE, "Setting Label (This can take while)..."); | 	VolumeName = GetLogicalName(DriveIndex, TRUE); | ||||||
| 	if (!SetVolumeLabelW(wDriveName, wLabel)) { | 	wVolumeName = utf8_to_wchar(VolumeName); | ||||||
|  | 	if ((wVolumeName == NULL) || (!SetVolumeLabelW(wVolumeName, wLabel))) { | ||||||
| 		uprintf("Could not set label: %s\n", WindowsErrorString()); | 		uprintf("Could not set label: %s\n", WindowsErrorString()); | ||||||
|  | 		// Non fatal error
 | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
| 	uprintf("Format completed.\n"); | 	uprintf("Format completed.\n"); | ||||||
| 	r = TRUE; | 	r = TRUE; | ||||||
| 
 | 
 | ||||||
| out: | out: | ||||||
|  | 	safe_free(VolumeName); | ||||||
|  | 	safe_free(wVolumeName); | ||||||
| 	safe_closehandle(hLogicalVolume); | 	safe_closehandle(hLogicalVolume); | ||||||
| 	safe_free(pFAT32BootSect); | 	safe_free(pFAT32BootSect); | ||||||
| 	safe_free(pFAT32FsInfo); | 	safe_free(pFAT32FsInfo); | ||||||
|  | @ -601,18 +606,28 @@ out: | ||||||
| /*
 | /*
 | ||||||
|  * Call on fmifs.dll's FormatEx() to format the drive |  * Call on fmifs.dll's FormatEx() to format the drive | ||||||
|  */ |  */ | ||||||
| static BOOL FormatDrive(char DriveLetter) | static BOOL FormatDrive(DWORD DriveIndex) | ||||||
| { | { | ||||||
| 	BOOL r = FALSE; | 	BOOL r = FALSE; | ||||||
| 	PF_DECL(FormatEx); | 	PF_DECL(FormatEx); | ||||||
| 	WCHAR wDriveRoot[] = L"?:\\"; | 	char* VolumeName = NULL; | ||||||
|  | 	WCHAR* wVolumeName = NULL; | ||||||
|  | 	char FSType[32], format_status[64]; | ||||||
| 	WCHAR wFSType[32]; | 	WCHAR wFSType[32]; | ||||||
| 	WCHAR wLabel[64]; | 	WCHAR wLabel[64]; | ||||||
| 	size_t i; | 	size_t i; | ||||||
| 	char* locale; | 	char* locale; | ||||||
| 
 | 
 | ||||||
| 	wDriveRoot[0] = (WCHAR)DriveLetter; | 	GetWindowTextA(hFileSystem, FSType, ARRAYSIZE(FSType)); | ||||||
| 	PrintStatus(0, TRUE, "Formatting..."); | 	safe_sprintf(format_status, ARRAYSIZE(format_status), "Formatting (%s)...", FSType); | ||||||
|  | 	PrintStatus(0, TRUE, format_status); | ||||||
|  | 	VolumeName = GetLogicalName(DriveIndex, FALSE); | ||||||
|  | 	wVolumeName = utf8_to_wchar(VolumeName); | ||||||
|  | 	if (wVolumeName == NULL) { | ||||||
|  | 		uprintf("Could not read volume name\n"); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	// LoadLibrary("fmifs.dll") appears to changes the locale, which can lead to
 | 	// LoadLibrary("fmifs.dll") appears to changes the locale, which can lead to
 | ||||||
| 	// problems with tolower(). Make sure we restore the locale. For more details,
 | 	// problems with tolower(). Make sure we restore the locale. For more details,
 | ||||||
| 	// see http://comments.gmane.org/gmane.comp.gnu.mingw.user/39300
 | 	// see http://comments.gmane.org/gmane.comp.gnu.mingw.user/39300
 | ||||||
|  | @ -635,7 +650,7 @@ static BOOL FormatDrive(char DriveLetter) | ||||||
| 	format_percent = 0.0f; | 	format_percent = 0.0f; | ||||||
| 	task_number = 0; | 	task_number = 0; | ||||||
| 	fs_index = (int)ComboBox_GetItemData(hFileSystem, ComboBox_GetCurSel(hFileSystem)); | 	fs_index = (int)ComboBox_GetItemData(hFileSystem, ComboBox_GetCurSel(hFileSystem)); | ||||||
| 	pfFormatEx(wDriveRoot, SelectedDrive.Geometry.MediaType, wFSType, wLabel, | 	pfFormatEx(wVolumeName, SelectedDrive.Geometry.MediaType, wFSType, wLabel, | ||||||
| 		IsChecked(IDC_QUICKFORMAT), (ULONG)ComboBox_GetItemData(hClusterSize, ComboBox_GetCurSel(hClusterSize)), | 		IsChecked(IDC_QUICKFORMAT), (ULONG)ComboBox_GetItemData(hClusterSize, ComboBox_GetCurSel(hClusterSize)), | ||||||
| 		FormatExCallback); | 		FormatExCallback); | ||||||
| 	if (!IS_ERROR(FormatStatus)) { | 	if (!IS_ERROR(FormatStatus)) { | ||||||
|  | @ -644,6 +659,8 @@ static BOOL FormatDrive(char DriveLetter) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| out: | out: | ||||||
|  | 	safe_free(VolumeName); | ||||||
|  | 	safe_free(wVolumeName); | ||||||
| 	return r; | 	return r; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -737,12 +754,14 @@ static BOOL AnalyzePBR(HANDLE hLogicalVolume) | ||||||
| 		} else if (entire_fat_32_fd_br_matches(&fake_fd)) { | 		} else if (entire_fat_32_fd_br_matches(&fake_fd)) { | ||||||
| 			uprintf("Drive has a FAT32 FreeDOS partition boot record\n"); | 			uprintf("Drive has a FAT32 FreeDOS partition boot record\n"); | ||||||
| 		} else { | 		} else { | ||||||
| 			uprintf("Drive has a unknown FAT16 or FAT32 partition boot record\n"); | 			uprintf("Drive has an unknown FAT16 or FAT32 partition boot record\n"); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return TRUE; | 	return TRUE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // TODO: We may have to clear a few more sectors past the MBR buffer zone
 | ||||||
|  | // so that Windows relinquishes access
 | ||||||
| static BOOL ClearMBRGPT(HANDLE hPhysicalDrive, LONGLONG DiskSize, DWORD SectorSize) | static BOOL ClearMBRGPT(HANDLE hPhysicalDrive, LONGLONG DiskSize, DWORD SectorSize) | ||||||
| { | { | ||||||
| 	BOOL r = FALSE; | 	BOOL r = FALSE; | ||||||
|  | @ -1138,15 +1157,24 @@ DWORD WINAPI CloseFormatPromptThread(LPVOID param) { | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Standalone thread for the formatting operation |  * Standalone thread for the formatting operation | ||||||
|  |  * According to http://msdn.microsoft.com/en-us/library/windows/desktop/aa364562.aspx
 | ||||||
|  |  * To change a volume file system | ||||||
|  |  *   Open a volume. | ||||||
|  |  *   Lock the volume. | ||||||
|  |  *   Format the volume. | ||||||
|  |  *   Dismount the volume. | ||||||
|  |  *   Unlock the volume. | ||||||
|  |  *   Close the volume handle. | ||||||
|  */ |  */ | ||||||
| DWORD WINAPI FormatThread(LPVOID param) | DWORD WINAPI FormatThread(LPVOID param) | ||||||
| { | { | ||||||
| 	int r, pt, bt, fs, dt; | 	int r, pt, bt, fs, dt; | ||||||
| 	BOOL ret, no_volume = FALSE; | 	BOOL ret; | ||||||
| 	DWORD num = (DWORD)(uintptr_t)param; | 	DWORD DriveIndex = (DWORD)(uintptr_t)param; | ||||||
| 	HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE; | 	HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE; | ||||||
| 	HANDLE hLogicalVolume = INVALID_HANDLE_VALUE; | 	HANDLE hLogicalVolume = INVALID_HANDLE_VALUE; | ||||||
| 	SYSTEMTIME lt; | 	SYSTEMTIME lt; | ||||||
|  | 	char* guid_volume = NULL; | ||||||
| 	char drive_name[] = "?:\\"; | 	char drive_name[] = "?:\\"; | ||||||
| 	char bb_msg[512]; | 	char bb_msg[512]; | ||||||
| 	char logfile[MAX_PATH], *userdir; | 	char logfile[MAX_PATH], *userdir; | ||||||
|  | @ -1159,34 +1187,41 @@ DWORD WINAPI FormatThread(LPVOID param) | ||||||
| 	pt = GETPARTTYPE((int)ComboBox_GetItemData(hPartitionScheme, ComboBox_GetCurSel(hPartitionScheme))); | 	pt = GETPARTTYPE((int)ComboBox_GetItemData(hPartitionScheme, ComboBox_GetCurSel(hPartitionScheme))); | ||||||
| 	bt = GETBIOSTYPE((int)ComboBox_GetItemData(hPartitionScheme, ComboBox_GetCurSel(hPartitionScheme))); | 	bt = GETBIOSTYPE((int)ComboBox_GetItemData(hPartitionScheme, ComboBox_GetCurSel(hPartitionScheme))); | ||||||
| 
 | 
 | ||||||
| 	if (num & DRIVE_INDEX_RAW_DRIVE) { | 	PrintStatus(0, TRUE, "Requesting disk access...\n"); | ||||||
| 		no_volume = TRUE; | 	hPhysicalDrive = GetPhysicalHandle(DriveIndex, TRUE, TRUE); | ||||||
| 		uprintf("Using raw drive mode\n"); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	hPhysicalDrive = GetDriveHandle(num, NULL, TRUE, TRUE); |  | ||||||
| 	if (hPhysicalDrive == INVALID_HANDLE_VALUE) { | 	if (hPhysicalDrive == INVALID_HANDLE_VALUE) { | ||||||
| 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; | 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 	// At this stage with have both a handle and a lock to the physical drive...
 |  | ||||||
| 
 | 
 | ||||||
| 	// ... but we can't write sectors that are part of a volume, even if we have 
 | 	// At this stage with have both a handle and a lock to the physical drive...
 | ||||||
| 	// access to physical, unless we have a lock (which doesn't have to be write)
 | 	drive_name[0] = GetDriveLetter(DriveIndex); | ||||||
| 	// Also, having a volume handle allows us to unmount the volume
 | 	if (drive_name[0] == ' ') { | ||||||
| 	if (!no_volume) { | 		uprintf("No drive letter was assigned...\n"); | ||||||
| 		hLogicalVolume = GetDriveHandle(num, drive_name, FALSE, TRUE); | 		drive_name[0] =  GetUnusedDriveLetter(); | ||||||
| 		if (hLogicalVolume == INVALID_HANDLE_VALUE) { | 		if (drive_name[0] == ' ') { | ||||||
| 			uprintf("Could not lock volume\n"); | 			uprintf("Could not find a suitable drive letter\n"); | ||||||
| 			FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; | 			FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_ASSIGN_LETTER); | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
| 		UnmountDrive(hLogicalVolume); | 	} else if (!DeleteVolumeMountPointA(drive_name)) { | ||||||
|  | 		uprintf("Failed to delete mountpoint %s: %s\n", drive_name, WindowsErrorString()); | ||||||
|  | 		// TODO: generate an error?
 | ||||||
| 	} | 	} | ||||||
|  | 	uprintf("Will use '%c': as volume mountpoint\n", drive_name[0]); | ||||||
| 
 | 
 | ||||||
|  | 	hLogicalVolume = GetLogicalHandle(DriveIndex, FALSE, TRUE); | ||||||
|  | 	if (hLogicalVolume == INVALID_HANDLE_VALUE) { | ||||||
|  | 		uprintf("Could not lock volume\n"); | ||||||
|  | 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 	UnmountVolume(hLogicalVolume); | ||||||
|  | 
 | ||||||
|  | 	PrintStatus(0, TRUE, "Analyzing existing boot records...\n"); | ||||||
| 	AnalyzeMBR(hPhysicalDrive); | 	AnalyzeMBR(hPhysicalDrive); | ||||||
| 	if (!no_volume) | 	AnalyzePBR(hLogicalVolume); | ||||||
| 		AnalyzePBR(hLogicalVolume); | 	UpdateProgress(OP_ANALYZE_MBR, -1.0f); | ||||||
| 
 | 
 | ||||||
| 	if (IsChecked(IDC_BADBLOCKS)) { | 	if (IsChecked(IDC_BADBLOCKS)) { | ||||||
| 		do { | 		do { | ||||||
|  | @ -1249,8 +1284,17 @@ DWORD WINAPI FormatThread(LPVOID param) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	// Close the (unmounted) volume before formatting, but keep the lock
 | 	// Close the (unmounted) volume before formatting, but keep the lock
 | ||||||
| 	if (!no_volume) | 	// According to MS this relinquishes the lock, so...
 | ||||||
| 		safe_closehandle(hLogicalVolume); | 	PrintStatus(0, TRUE, "Closing existing volume...\n"); | ||||||
|  | 	if (!CloseHandle(hLogicalVolume)) { | ||||||
|  | 		uprintf("Could not close volume: %s\n", WindowsErrorString()); | ||||||
|  | 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_ACCESS_DENIED; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 	hLogicalVolume = INVALID_HANDLE_VALUE; | ||||||
|  | 
 | ||||||
|  | 	// TODO: check for cancel once in a while!
 | ||||||
|  | 	// TODO: our start button should become cancel instead of close
 | ||||||
| 
 | 
 | ||||||
| 	// Especially after destructive badblocks test, you must zero the MBR/GPT completely
 | 	// Especially after destructive badblocks test, you must zero the MBR/GPT completely
 | ||||||
| 	// before repartitioning. Else, all kind of bad things can happen.
 | 	// before repartitioning. Else, all kind of bad things can happen.
 | ||||||
|  | @ -1272,28 +1316,24 @@ DWORD WINAPI FormatThread(LPVOID param) | ||||||
| 	// Add a small delay after partitioning to be safe
 | 	// Add a small delay after partitioning to be safe
 | ||||||
| 	Sleep(200); | 	Sleep(200); | ||||||
| 
 | 
 | ||||||
| 	if (no_volume) { |  | ||||||
| 		hLogicalVolume = GetDriveHandle(num, drive_name, FALSE, TRUE); |  | ||||||
| 		if (hLogicalVolume == INVALID_HANDLE_VALUE) { |  | ||||||
| 			uprintf("Could not lock volume\n"); |  | ||||||
| 			FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; |  | ||||||
| 			goto out; |  | ||||||
| 		} |  | ||||||
| 		UnmountDrive(hLogicalVolume); |  | ||||||
| 		safe_closehandle(hLogicalVolume); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 	// If FAT32 is requested and we have a large drive (>32 GB) use 
 | 	// If FAT32 is requested and we have a large drive (>32 GB) use 
 | ||||||
| 	// large FAT32 format, else use MS's FormatEx.
 | 	// large FAT32 format, else use MS's FormatEx.
 | ||||||
| 	ret = ((fs == FS_FAT32) && (SelectedDrive.DiskSize > LARGE_FAT32_SIZE))? | 	ret = ((fs == FS_FAT32) && ((SelectedDrive.DiskSize > LARGE_FAT32_SIZE) || (force_large_fat32)))? | ||||||
| 		FormatFAT32(num):FormatDrive(drive_name[0]); | 		FormatFAT32(DriveIndex):FormatDrive(DriveIndex); | ||||||
| 	if (!ret) { | 	if (!ret) { | ||||||
| 		// Error will be set by FormatDrive() in FormatStatus
 | 		// Error will be set by FormatDrive() in FormatStatus
 | ||||||
| 		uprintf("Format error: %s\n", StrError(FormatStatus)); | 		uprintf("Format error: %s\n", StrError(FormatStatus)); | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	guid_volume = GetLogicalName(DriveIndex, TRUE); | ||||||
|  | 	if (guid_volume == NULL) { | ||||||
|  | 		uprintf("Could not get GUID volume name\n"); | ||||||
|  | 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NO_VOLUME_ID; | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 	uprintf("Found volume GUID %s\n", guid_volume); | ||||||
|  | 
 | ||||||
| 	if (pt == PARTITION_STYLE_MBR) { | 	if (pt == PARTITION_STYLE_MBR) { | ||||||
| 		PrintStatus(0, TRUE, "Writing master boot record..."); | 		PrintStatus(0, TRUE, "Writing master boot record..."); | ||||||
| 		if (!WriteMBR(hPhysicalDrive)) { | 		if (!WriteMBR(hPhysicalDrive)) { | ||||||
|  | @ -1304,6 +1344,12 @@ DWORD WINAPI FormatThread(LPVOID param) | ||||||
| 		UpdateProgress(OP_FIX_MBR, -1.0f); | 		UpdateProgress(OP_FIX_MBR, -1.0f); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if (!SetVolumeMountPointA(drive_name, guid_volume)) { | ||||||
|  | 		uprintf("Could not remount %s on %s: %s\n", guid_volume, drive_name, WindowsErrorString()); | ||||||
|  | 		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_MOUNT_VOLUME); | ||||||
|  | 		goto out; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	if (IsChecked(IDC_BOOT)) { | 	if (IsChecked(IDC_BOOT)) { | ||||||
| 		if (bt == BT_UEFI) { | 		if (bt == BT_UEFI) { | ||||||
| 			// For once, no need to do anything - just check our sanity
 | 			// For once, no need to do anything - just check our sanity
 | ||||||
|  | @ -1315,7 +1361,7 @@ DWORD WINAPI FormatThread(LPVOID param) | ||||||
| 		} else if ((dt == DT_WINME) || (dt == DT_FREEDOS) || ((dt == DT_ISO) && (fs == FS_NTFS))) { | 		} else if ((dt == DT_WINME) || (dt == DT_FREEDOS) || ((dt == DT_ISO) && (fs == FS_NTFS))) { | ||||||
| 			// We still have a lock, which we need to modify the volume boot record 
 | 			// We still have a lock, which we need to modify the volume boot record 
 | ||||||
| 			// => no need to reacquire the lock...
 | 			// => no need to reacquire the lock...
 | ||||||
| 			hLogicalVolume = GetDriveHandle(num, drive_name, TRUE, FALSE); | 			hLogicalVolume = GetLogicalHandle(DriveIndex, TRUE, FALSE); | ||||||
| 			if (hLogicalVolume == INVALID_HANDLE_VALUE) { | 			if (hLogicalVolume == INVALID_HANDLE_VALUE) { | ||||||
| 				uprintf("Could not re-mount volume for partition boot record access\n"); | 				uprintf("Could not re-mount volume for partition boot record access\n"); | ||||||
| 				FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; | 				FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; | ||||||
|  | @ -1333,7 +1379,7 @@ DWORD WINAPI FormatThread(LPVOID param) | ||||||
| 			safe_unlockclose(hLogicalVolume); | 			safe_unlockclose(hLogicalVolume); | ||||||
| 		} else if ( (dt == DT_SYSLINUX) || ((dt == DT_ISO) && ((fs == FS_FAT16) || (fs == FS_FAT32))) ) { | 		} else if ( (dt == DT_SYSLINUX) || ((dt == DT_ISO) && ((fs == FS_FAT16) || (fs == FS_FAT32))) ) { | ||||||
| 			PrintStatus(0, TRUE, "Installing Syslinux..."); | 			PrintStatus(0, TRUE, "Installing Syslinux..."); | ||||||
| 			if (!InstallSyslinux(num, drive_name)) { | 			if (!InstallSyslinux(DriveIndex, drive_name[0])) { | ||||||
| 				FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INSTALL_FAILURE; | 				FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INSTALL_FAILURE; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -1368,7 +1414,8 @@ DWORD WINAPI FormatThread(LPVOID param) | ||||||
| 					goto out; | 					goto out; | ||||||
| 				} | 				} | ||||||
| 				if ((bt == BT_UEFI) && (!iso_report.has_efi) && (iso_report.has_win7_efi)) { | 				if ((bt == BT_UEFI) && (!iso_report.has_efi) && (iso_report.has_win7_efi)) { | ||||||
| 					// TODO: progress
 | 					// TODO: better progress
 | ||||||
|  | 					// TODO: check ISO with EFI only
 | ||||||
| 					PrintStatus(0, TRUE, "Win7 EFI boot setup (this may take a while)..."); | 					PrintStatus(0, TRUE, "Win7 EFI boot setup (this may take a while)..."); | ||||||
| 					wim_image[0] = drive_name[0]; | 					wim_image[0] = drive_name[0]; | ||||||
| 					efi_dst[0] = drive_name[0]; | 					efi_dst[0] = drive_name[0]; | ||||||
|  | @ -1392,7 +1439,7 @@ DWORD WINAPI FormatThread(LPVOID param) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		UpdateProgress(OP_FINALIZE, -1.0f); | 		UpdateProgress(OP_FINALIZE, -1.0f); | ||||||
| 		PrintStatus(0, TRUE, "Finalizing..."); | 		PrintStatus(0, TRUE, "Finalizing, please wait..."); | ||||||
| 		if (IsChecked(IDC_SET_ICON)) | 		if (IsChecked(IDC_SET_ICON)) | ||||||
| 			SetAutorun(drive_name); | 			SetAutorun(drive_name); | ||||||
| 		// Issue another complete remount before we exit, to ensure we're clean
 | 		// Issue another complete remount before we exit, to ensure we're clean
 | ||||||
|  | @ -1405,9 +1452,10 @@ DWORD WINAPI FormatThread(LPVOID param) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| out: | out: | ||||||
|  | 	safe_free(guid_volume); | ||||||
| 	SendMessage(hISOProgressDlg, UM_ISO_EXIT, 0, 0); | 	SendMessage(hISOProgressDlg, UM_ISO_EXIT, 0, 0); | ||||||
| 	safe_unlockclose(hLogicalVolume); | 	safe_unlockclose(hLogicalVolume); | ||||||
| 	safe_unlockclose(hPhysicalDrive); | 	safe_unlockclose(hPhysicalDrive);	// This can take a while
 | ||||||
| 	PostMessage(hMainDialog, UM_FORMAT_COMPLETED, 0, 0); | 	PostMessage(hMainDialog, UM_FORMAT_COMPLETED, 0, 0); | ||||||
| 	ExitThread(0); | 	ExitThread(0); | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										20
									
								
								src/rufus.c
									
										
									
									
									
								
							
							
						
						
									
										20
									
								
								src/rufus.c
									
										
									
									
									
								
							|  | @ -93,6 +93,7 @@ static BOOL existing_key = FALSE;	// For LGP set/restore | ||||||
| static BOOL iso_size_check = TRUE; | static BOOL iso_size_check = TRUE; | ||||||
| static BOOL log_displayed = FALSE; | static BOOL log_displayed = FALSE; | ||||||
| static BOOL iso_provided = FALSE; | static BOOL iso_provided = FALSE; | ||||||
|  | extern BOOL force_large_fat32; | ||||||
| static int selection_default; | static int selection_default; | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  | @ -605,7 +606,7 @@ static BOOL GetUSBDevices(DWORD devnum) | ||||||
| 			// We can afford a failure on this call - just replace the name
 | 			// We can afford a failure on this call - just replace the name
 | ||||||
| 			safe_strcpy(buffer, sizeof(buffer), generic_friendly_name); | 			safe_strcpy(buffer, sizeof(buffer), generic_friendly_name); | ||||||
| 		} | 		} | ||||||
| 		uprintf("Found drive '%s'\n", buffer); | 		uprintf("Found device '%s'\n", buffer); | ||||||
| 
 | 
 | ||||||
| 		devint_data.cbSize = sizeof(devint_data); | 		devint_data.cbSize = sizeof(devint_data); | ||||||
| 		hDrive = INVALID_HANDLE_VALUE; | 		hDrive = INVALID_HANDLE_VALUE; | ||||||
|  | @ -617,6 +618,8 @@ static BOOL GetUSBDevices(DWORD devnum) | ||||||
| 			if (!SetupDiEnumDeviceInterfaces(dev_info, &dev_info_data, &_GUID_DEVINTERFACE_DISK, j, &devint_data)) { | 			if (!SetupDiEnumDeviceInterfaces(dev_info, &dev_info_data, &_GUID_DEVINTERFACE_DISK, j, &devint_data)) { | ||||||
| 				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 { | ||||||
|  | 					uprintf("Device was eliminated because it doesn't report itself as a disk\n"); | ||||||
| 				} | 				} | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
|  | @ -669,7 +672,6 @@ static BOOL GetUSBDevices(DWORD devnum) | ||||||
| 				// 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 == ' ') { | ||||||
| 					safe_sprintf(entry, sizeof(entry), "%s (Disk %d)", label, device_number.DeviceNumber); | 					safe_sprintf(entry, sizeof(entry), "%s (Disk %d)", label, device_number.DeviceNumber); | ||||||
| 					device_number.DeviceNumber |= DRIVE_INDEX_RAW_DRIVE; |  | ||||||
| 				} else { | 				} else { | ||||||
| 					safe_sprintf(entry, sizeof(entry), "%s (%c:)", label, drive_letter); | 					safe_sprintf(entry, sizeof(entry), "%s (%c:)", label, drive_letter); | ||||||
| 				} | 				} | ||||||
|  | @ -722,6 +724,7 @@ static void InitProgress(void) | ||||||
| 	memset(slot_end, 0, sizeof(slot_end)); | 	memset(slot_end, 0, sizeof(slot_end)); | ||||||
| 	previous_end = 0.0f; | 	previous_end = 0.0f; | ||||||
| 
 | 
 | ||||||
|  | 	nb_slots[OP_ANALYZE_MBR] = 1; | ||||||
| 	nb_slots[OP_ZERO_MBR] = 1; | 	nb_slots[OP_ZERO_MBR] = 1; | ||||||
| 	if (IsChecked(IDC_BADBLOCKS)) { | 	if (IsChecked(IDC_BADBLOCKS)) { | ||||||
| 		nb_slots[OP_BADBLOCKS] = -1; | 		nb_slots[OP_BADBLOCKS] = -1; | ||||||
|  | @ -751,7 +754,7 @@ static void InitProgress(void) | ||||||
| 	  || ((fs == FS_FAT32) && (SelectedDrive.DiskSize >= LARGE_FAT32_SIZE)) ) { | 	  || ((fs == FS_FAT32) && (SelectedDrive.DiskSize >= LARGE_FAT32_SIZE)) ) { | ||||||
| 		nb_slots[OP_FORMAT] = -1; | 		nb_slots[OP_FORMAT] = -1; | ||||||
| 	} | 	} | ||||||
| 	nb_slots[OP_FINALIZE] = ((dt == DT_ISO) && (fs == FS_NTFS))?2:1; | 	nb_slots[OP_FINALIZE] = ((dt == DT_ISO) && (fs == FS_NTFS))?3:2; | ||||||
| 
 | 
 | ||||||
| 	for (i=0; i<OP_MAX; i++) { | 	for (i=0; i<OP_MAX; i++) { | ||||||
| 		if (nb_slots[i] > 0) { | 		if (nb_slots[i] > 0) { | ||||||
|  | @ -1015,7 +1018,6 @@ DWORD WINAPI ISOScanThread(LPVOID param) | ||||||
| 		safe_free(iso_path); | 		safe_free(iso_path); | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 	// TODO: 4GB and UEFI = BAD!!!
 |  | ||||||
| 	uprintf("ISO label: '%s'\r\n  Size: %lld bytes\r\n  Has a >4GB file: %s\r\n  Uses EFI: %s%s\r\n  Uses Bootmgr: %s\r\n  Uses WinPE: %s%s\r\n  Uses isolinux: %s\n", | 	uprintf("ISO label: '%s'\r\n  Size: %lld bytes\r\n  Has a >4GB file: %s\r\n  Uses EFI: %s%s\r\n  Uses Bootmgr: %s\r\n  Uses WinPE: %s%s\r\n  Uses isolinux: %s\n", | ||||||
| 		iso_report.label, iso_report.projected_size, iso_report.has_4GB_file?"Yes":"No", (iso_report.has_efi || iso_report.has_win7_efi)?"Yes":"No",  | 		iso_report.label, iso_report.projected_size, iso_report.has_4GB_file?"Yes":"No", (iso_report.has_efi || iso_report.has_win7_efi)?"Yes":"No",  | ||||||
| 		(iso_report.has_win7_efi && (!iso_report.has_efi))?" (win7_x64)":"", iso_report.has_bootmgr?"Yes":"No", | 		(iso_report.has_win7_efi && (!iso_report.has_efi))?" (win7_x64)":"", iso_report.has_bootmgr?"Yes":"No", | ||||||
|  | @ -1391,6 +1393,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | ||||||
| 				user_changed_label = FALSE; | 				user_changed_label = FALSE; | ||||||
| 				return (INT_PTR)TRUE; | 				return (INT_PTR)TRUE; | ||||||
| 			case DBT_DEVNODES_CHANGED: | 			case DBT_DEVNODES_CHANGED: | ||||||
|  | 				// TODO: figure out what the deal is with extra events when FILE_SHARE_WRITE is not enabled
 | ||||||
| 				// If it's been more than a second since last device refresh, arm a refresh timer
 | 				// If it's been more than a second since last device refresh, arm a refresh timer
 | ||||||
| 				if (GetTickCount() > LastRefresh + 1000) { | 				if (GetTickCount() > LastRefresh + 1000) { | ||||||
| 					LastRefresh = GetTickCount(); | 					LastRefresh = GetTickCount(); | ||||||
|  | @ -1673,6 +1676,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | ||||||
| 						FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_START_THREAD); | 						FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_START_THREAD); | ||||||
| 						PostMessage(hMainDialog, UM_FORMAT_COMPLETED, 0, 0); | 						PostMessage(hMainDialog, UM_FORMAT_COMPLETED, 0, 0); | ||||||
| 					} | 					} | ||||||
|  | 					PrintStatus(0, FALSE, ""); | ||||||
| 					timer = 0; | 					timer = 0; | ||||||
| 					safe_sprintf(szTimer, sizeof(szTimer), "00:00:00"); | 					safe_sprintf(szTimer, sizeof(szTimer), "00:00:00"); | ||||||
| 					SendMessageA(GetDlgItem(hMainDialog, IDC_STATUS), SB_SETTEXTA, | 					SendMessageA(GetDlgItem(hMainDialog, IDC_STATUS), SB_SETTEXTA, | ||||||
|  | @ -1906,6 +1910,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine | ||||||
| 	UpdateWindow(hDlg); | 	UpdateWindow(hDlg); | ||||||
| 
 | 
 | ||||||
| 	// Do our own event processing and process "magic" commands
 | 	// Do our own event processing and process "magic" commands
 | ||||||
|  | 	// TODO: Cheat modes are not handled when the log is at the front - this sucks
 | ||||||
| 	while(GetMessage(&msg, NULL, 0, 0)) { | 	while(GetMessage(&msg, NULL, 0, 0)) { | ||||||
| 		// The following ensures the processing of the ISO progress window messages
 | 		// The following ensures the processing of the ISO progress window messages
 | ||||||
| 		if (!IsWindow(hISOProgressDlg) || !IsDialogMessage(hISOProgressDlg, &msg)) { | 		if (!IsWindow(hISOProgressDlg) || !IsDialogMessage(hISOProgressDlg, &msg)) { | ||||||
|  | @ -1917,6 +1922,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine | ||||||
| 				PrintStatus2000("ISO size check", iso_size_check); | 				PrintStatus2000("ISO size check", iso_size_check); | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  | 			// TODO: move this option to advanced mode
 | ||||||
| 			// Alt-F => Toggle detection of fixed disks
 | 			// Alt-F => Toggle detection of fixed disks
 | ||||||
| 			// By default Rufus does not allow formatting USB fixed disk drives, such as USB HDDs
 | 			// By default Rufus does not allow formatting USB fixed disk drives, such as USB HDDs
 | ||||||
| 			// This is a safety feature, to avoid someone unintentionally formatting a backup 
 | 			// This is a safety feature, to avoid someone unintentionally formatting a backup 
 | ||||||
|  | @ -1927,6 +1933,12 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine | ||||||
| 				GetUSBDevices(0); | 				GetUSBDevices(0); | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  | 			// Alt-L => Force Large FAT32 format to be used on < 32 GB drives
 | ||||||
|  | 			if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'L')) { | ||||||
|  | 				force_large_fat32 = !force_large_fat32; | ||||||
|  | 				PrintStatus2000("Force large FAT32 usage", force_large_fat32); | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
| 			// Alt-D => Delete the NoDriveTypeAutorun key on exit (useful if the app crashed)
 | 			// Alt-D => Delete the NoDriveTypeAutorun key on exit (useful if the app crashed)
 | ||||||
| 			// This key is used to disable Windows popup messages when an USB drive is plugged in.
 | 			// This key is used to disable Windows popup messages when an USB drive is plugged in.
 | ||||||
| 			if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'D')) { | 			if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'D')) { | ||||||
|  |  | ||||||
							
								
								
									
										20
									
								
								src/rufus.h
									
										
									
									
									
								
							
							
						
						
									
										20
									
								
								src/rufus.h
									
										
									
									
									
								
							|  | @ -38,8 +38,6 @@ | ||||||
| #define RUFUS_BLOCKING_IO_TITLE     APPLICATION_NAME " - Flushing buffers" | #define RUFUS_BLOCKING_IO_TITLE     APPLICATION_NAME " - Flushing buffers" | ||||||
| #define DRIVE_INDEX_MIN             0x00000080 | #define DRIVE_INDEX_MIN             0x00000080 | ||||||
| #define DRIVE_INDEX_MAX             0x000000C0 | #define DRIVE_INDEX_MAX             0x000000C0 | ||||||
| #define DRIVE_INDEX_MASK            0x0000FFFF |  | ||||||
| #define DRIVE_INDEX_RAW_DRIVE       0x00010000	// Additional drive properties stored in the drive index
 |  | ||||||
| #define MAX_DRIVES                  (DRIVE_INDEX_MAX - DRIVE_INDEX_MIN) | #define MAX_DRIVES                  (DRIVE_INDEX_MAX - DRIVE_INDEX_MIN) | ||||||
| #define MAX_TOOLTIPS                32 | #define MAX_TOOLTIPS                32 | ||||||
| #define MAX_PROGRESS                (0xFFFF-1)	// leave room for 1 more for insta-progress workaround
 | #define MAX_PROGRESS                (0xFFFF-1)	// leave room for 1 more for insta-progress workaround
 | ||||||
|  | @ -135,6 +133,7 @@ enum timer_type { | ||||||
| 
 | 
 | ||||||
| /* Action type, for progress bar breakdown */ | /* Action type, for progress bar breakdown */ | ||||||
| enum action_type { | enum action_type { | ||||||
|  | 	OP_ANALYZE_MBR, | ||||||
| 	OP_BADBLOCKS, | 	OP_BADBLOCKS, | ||||||
| 	OP_ZERO_MBR, | 	OP_ZERO_MBR, | ||||||
| 	OP_PARTITION, | 	OP_PARTITION, | ||||||
|  | @ -296,14 +295,19 @@ extern BOOL Question(char* title, char* format, ...); | ||||||
| extern BOOL ExtractDOS(const char* path); | extern BOOL ExtractDOS(const char* path); | ||||||
| extern BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan); | extern BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan); | ||||||
| extern BOOL ExtractISOFile(const char* iso, const char* iso_file, const char* dest_file); | extern BOOL ExtractISOFile(const char* iso, const char* iso_file, const char* dest_file); | ||||||
| extern BOOL InstallSyslinux(DWORD num, const char* drive_name); | extern BOOL InstallSyslinux(DWORD drive_index, char drive_letter); | ||||||
| DWORD WINAPI FormatThread(void* param); | DWORD WINAPI FormatThread(void* param); | ||||||
|  | extern char* GetPhysicalName(DWORD DriveIndex); | ||||||
|  | extern HANDLE GetPhysicalHandle(DWORD DriveIndex, BOOL bWriteAccess, BOOL bLockDrive); | ||||||
|  | extern char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash); | ||||||
|  | extern HANDLE GetLogicalHandle(DWORD DriveIndex, BOOL bWriteAccess, BOOL bLockDrive); | ||||||
|  | extern char GetDriveLetter(DWORD DriveIndex); | ||||||
|  | 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 const char* GetPartitionType(BYTE Type); | extern const char* GetPartitionType(BYTE Type); | ||||||
| extern BOOL GetDrivePartitionData(DWORD DeviceNumber, char* FileSystemName, DWORD FileSystemNameSize); | extern BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSystemNameSize); | ||||||
| extern HANDLE GetDriveHandle(DWORD DriveIndex, char* DriveLetter, BOOL bWriteAccess, BOOL bLockDrive); |  | ||||||
| extern BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label); | extern BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label); | ||||||
| extern BOOL UnmountDrive(HANDLE hDrive); | extern BOOL UnmountVolume(HANDLE hDrive); | ||||||
| extern BOOL CreateProgress(void); | extern BOOL CreateProgress(void); | ||||||
| extern BOOL SetAutorun(const char* path); | extern BOOL SetAutorun(const char* path); | ||||||
| extern char* FileDialog(BOOL save, char* path, char* filename, char* ext, char* ext_desc); | extern char* FileDialog(BOOL save, char* path, char* filename, char* ext, char* ext_desc); | ||||||
|  | @ -397,7 +401,9 @@ typedef struct { | ||||||
| #define ERROR_ISO_SCAN                 0x1207 | #define ERROR_ISO_SCAN                 0x1207 | ||||||
| #define ERROR_ISO_EXTRACT              0x1208 | #define ERROR_ISO_EXTRACT              0x1208 | ||||||
| #define ERROR_CANT_REMOUNT_VOLUME      0x1209 | #define ERROR_CANT_REMOUNT_VOLUME      0x1209 | ||||||
| #define ERROR_CANT_PATCH               0x1210 | #define ERROR_CANT_PATCH               0x120A | ||||||
|  | #define ERROR_CANT_ASSIGN_LETTER       0x120B | ||||||
|  | #define ERROR_CANT_MOUNT_VOLUME        0x120C | ||||||
| 
 | 
 | ||||||
| /* More niceties */ | /* More niceties */ | ||||||
| #ifndef MIN | #ifndef MIN | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							|  | @ -30,7 +30,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL | ||||||
| IDD_DIALOG DIALOGEX 12, 12, 206, 316 | IDD_DIALOG DIALOGEX 12, 12, 206, 316 | ||||||
| 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.3.3.239" | CAPTION "Rufus v1.3.3.240" | ||||||
| FONT 8, "MS Shell Dlg", 400, 0, 0x1 | FONT 8, "MS Shell Dlg", 400, 0, 0x1 | ||||||
| BEGIN | BEGIN | ||||||
|     DEFPUSHBUTTON   "Start",IDC_START,94,278,50,14 |     DEFPUSHBUTTON   "Start",IDC_START,94,278,50,14 | ||||||
|  | @ -274,8 +274,8 @@ END | ||||||
| // | // | ||||||
| 
 | 
 | ||||||
| VS_VERSION_INFO VERSIONINFO | VS_VERSION_INFO VERSIONINFO | ||||||
|  FILEVERSION 1,3,3,239 |  FILEVERSION 1,3,3,240 | ||||||
|  PRODUCTVERSION 1,3,3,239 |  PRODUCTVERSION 1,3,3,240 | ||||||
|  FILEFLAGSMASK 0x3fL |  FILEFLAGSMASK 0x3fL | ||||||
| #ifdef _DEBUG | #ifdef _DEBUG | ||||||
|  FILEFLAGS 0x1L |  FILEFLAGS 0x1L | ||||||
|  | @ -292,13 +292,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.3.3.239" |             VALUE "FileVersion", "1.3.3.240" | ||||||
|             VALUE "InternalName", "Rufus" |             VALUE "InternalName", "Rufus" | ||||||
|             VALUE "LegalCopyright", "(c) 2011-2013 Pete Batard (GPL v3)" |             VALUE "LegalCopyright", "(c) 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.3.3.239" |             VALUE "ProductVersion", "1.3.3.240" | ||||||
|         END |         END | ||||||
|     END |     END | ||||||
|     BLOCK "VarFileInfo" |     BLOCK "VarFileInfo" | ||||||
|  |  | ||||||
|  | @ -269,6 +269,10 @@ const char* StrError(DWORD error_code) | ||||||
| 			"mountvol.exe command to make your device accessible again"; | 			"mountvol.exe command to make your device accessible again"; | ||||||
| 	case ERROR_CANT_PATCH: | 	case ERROR_CANT_PATCH: | ||||||
| 		return "Unable to patch/setup files for boot"; | 		return "Unable to patch/setup files for boot"; | ||||||
|  | 	case ERROR_CANT_ASSIGN_LETTER: | ||||||
|  | 		return "Unable to assign a drive letter"; | ||||||
|  | 	case ERROR_CANT_MOUNT_VOLUME: | ||||||
|  | 		return "Can't mount GUID volume"; | ||||||
| 	default: | 	default: | ||||||
| 		uprintf("Unknown error: %08X\n", error_code); | 		uprintf("Unknown error: %08X\n", error_code); | ||||||
| 		SetLastError(error_code); | 		SetLastError(error_code); | ||||||
|  |  | ||||||
|  | @ -66,7 +66,7 @@ int libfat_readfile(intptr_t pp, void *buf, size_t secsize, | ||||||
|  * Extract the ldlinux.sys and ldlinux.bss from resources, |  * Extract the ldlinux.sys and ldlinux.bss from resources, | ||||||
|  * then patch and install them |  * then patch and install them | ||||||
|  */ |  */ | ||||||
| BOOL InstallSyslinux(DWORD num, const char* drive_name) | BOOL InstallSyslinux(DWORD drive_index, char drive_letter) | ||||||
| { | { | ||||||
| 	HANDLE f_handle = INVALID_HANDLE_VALUE; | 	HANDLE f_handle = INVALID_HANDLE_VALUE; | ||||||
| 	HANDLE d_handle = INVALID_HANDLE_VALUE; | 	HANDLE d_handle = INVALID_HANDLE_VALUE; | ||||||
|  | @ -84,7 +84,7 @@ BOOL InstallSyslinux(DWORD num, const char* drive_name) | ||||||
| 	int nsectors; | 	int nsectors; | ||||||
| 	int dt = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType)); | 	int dt = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType)); | ||||||
| 
 | 
 | ||||||
| 	ldlinux_name[0] = drive_name[0]; | 	ldlinux_name[0] = drive_letter; | ||||||
| 
 | 
 | ||||||
| 	/* Initialize the ADV -- this should be smarter */ | 	/* Initialize the ADV -- this should be smarter */ | ||||||
| 	syslinux_reset_adv(syslinux_adv); | 	syslinux_reset_adv(syslinux_adv); | ||||||
|  | @ -135,7 +135,7 @@ BOOL InstallSyslinux(DWORD num, const char* drive_name) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Reopen the volume (we already have a lock) */ | 	/* Reopen the volume (we already have a lock) */ | ||||||
| 	d_handle = GetDriveHandle(num, (char*)drive_name, TRUE, FALSE); | 	d_handle = GetLogicalHandle(drive_index, TRUE, FALSE); | ||||||
| 	if (d_handle == INVALID_HANDLE_VALUE) { | 	if (d_handle == INVALID_HANDLE_VALUE) { | ||||||
| 		uprintf("Could open volume for syslinux operation\n"); | 		uprintf("Could open volume for syslinux operation\n"); | ||||||
| 		goto out; | 		goto out; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue