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