[core] use offset rather than index to identify a partition

* Also fix potential bcdboot invocation failure by introducing a new AltGetLogicalName() call.
* Also use the AltMount calls for ext# formatting
This commit is contained in:
Pete Batard 2019-08-18 14:13:09 +01:00
parent 1fa0aaf325
commit 94e2015edf
No known key found for this signature in database
GPG Key ID: 38E0CF5E69EDD671
4 changed files with 133 additions and 112 deletions

View File

@ -86,7 +86,7 @@ PF_TYPE_DECL(NTAPI, NTSTATUS, NtQueryVolumeInformationFile, (HANDLE, PIO_STATUS_
*/
RUFUS_DRIVE_INFO SelectedDrive;
BOOL installed_uefi_ntfs;
DWORD partition_index[3];
uint64_t partition_offset[3];
uint64_t persistence_size = 0;
/*
@ -245,22 +245,18 @@ out:
/*
* Return the path to access a partition on a specific disk, or NULL on error.
* The string is allocated and must be freed (to ensure concurrent access)
* If PartitionOffset is 0, the offset is ignored and the first partition found is returned.
*/
char* GetPartitionName(DWORD DriveIndex, DWORD PartitionIndex)
char* GetPartitionName(DWORD DriveIndex, uint64_t PartitionOffset)
{
BOOL success = FALSE;
char partition_name[32];
DWORD i = MAX_PARTITIONS + 1;
CheckDriveIndex(DriveIndex);
if (PartitionIndex >= MAX_PARTITIONS)
goto out;
if (PartitionIndex == 0)
PartitionIndex = 1;
static_sprintf(partition_name, "\\Device\\Harddisk%lu\\Partition%lu", DriveIndex, PartitionIndex);
success = TRUE;
for (i = 1; (i <= MAX_PARTITIONS) && (PartitionOffset != 0) && (SelectedDrive.PartitionOffset[i - 1] != PartitionOffset); i++);
static_sprintf(partition_name, "\\Device\\Harddisk%lu\\Partition%lu", DriveIndex, i);
out:
return (success) ? safe_strdup(partition_name) : NULL;
return (i <= MAX_PARTITIONS) ? safe_strdup(partition_name) : NULL;
}
/*
@ -278,11 +274,10 @@ HANDLE GetPhysicalHandle(DWORD DriveIndex, BOOL bLockDrive, BOOL bWriteAccess, B
/*
* Return the GUID volume name for the disk and partition specified, or NULL if not found.
* See http://msdn.microsoft.com/en-us/library/cc542456.aspx
* PartitionIndex starts at 1 (for the first partition). If PartitionIndex is zero, then
* the first partition found by this function (which *MAY NOT* be the actual first partition)
* is returned. The returned string is allocated and must be freed.
* If PartitionOffset is 0, the offset is ignored and the first partition found is returned.
* The returned string is allocated and must be freed.
*/
char* GetLogicalName(DWORD DriveIndex, DWORD PartitionIndex, BOOL bKeepTrailingBackslash, BOOL bSilent)
char* GetLogicalName(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bKeepTrailingBackslash, BOOL bSilent)
{
static const char* ignore_device[] = { "\\Device\\CdRom", "\\Device\\Floppy" };
static const char* volume_start = "\\\\?\\";
@ -294,13 +289,11 @@ char* GetLogicalName(DWORD DriveIndex, DWORD PartitionIndex, BOOL bKeepTrailingB
UINT drive_type;
StrArray found_name;
uint64_t found_offset[MAX_PARTITIONS] = { 0 };
uint32_t i, j, k;
uint32_t i, j;
size_t len;
StrArrayCreate(&found_name, MAX_PARTITIONS);
CheckDriveIndex(DriveIndex);
if (PartitionIndex > MAX_PARTITIONS)
goto out;
for (i = 0; hDrive == INVALID_HANDLE_VALUE; i++) {
if (i == 0) {
@ -391,33 +384,14 @@ char* GetLogicalName(DWORD DriveIndex, DWORD PartitionIndex, BOOL bKeepTrailingB
if (found_name.Index == 0)
goto out;
// Now process all the volumes we found, and find the one that matches our partition index
if (PartitionIndex == 0) {
i = 0;
} else for (i = 0, k = 0; i < found_name.Index; i++) {
for (j = 0; j < found_name.Index; j++) {
if (found_offset[i] > found_offset[j])
k++;
}
if (k == ((int)PartitionIndex) - 1)
break;
}
if (i < found_name.Index) {
// Now process all the volumes we found, and try to match one with our partition offset
for (i = 0; (i < found_name.Index) && (PartitionOffset != 0) && (PartitionOffset != found_offset[i]); i++);
if (i < found_name.Index)
ret = safe_strdup(found_name.String[i]);
} else {
// Some volumes, such as ESPs, are not listed by Windows, be it with VDS or other APIs.
// For these, we return the "\\?\GLOBALROOT\Device\HarddiskVolume#" identifier that
// matches our "Harddisk#Partition#", as reported by QueryDosDevice().
static_sprintf(path, "Harddisk%luPartition%lu", DriveIndex, PartitionIndex);
static_strcpy(volume_name, groot_name);
if (!QueryDosDeviceA(path, &volume_name[groot_len], (DWORD)(MAX_PATH - groot_len)) || (strlen(volume_name) < 20)) {
uprintf("Could not find the DOS volume name for '%s': %s", path, WindowsErrorString());
} else {
if (bKeepTrailingBackslash)
static_strcat(volume_name, "\\");
ret = safe_strdup(volume_name);
}
}
else
// NB: We need to re-add DRIVE_INDEX_MIN for this call since CheckDriveIndex() substracted it
ret = AltGetLogicalName(DriveIndex + DRIVE_INDEX_MIN, PartitionOffset, bKeepTrailingBackslash, bSilent);
out:
if (hVolume != INVALID_HANDLE_VALUE)
@ -426,6 +400,40 @@ out:
return ret;
}
/*
* Alternative version of the above, needed because some volumes, such as ESPs, are not listed
* by Windows, be it with VDS or other APIs.
* For these, we return the "\\?\GLOBALROOT\Device\HarddiskVolume#" identifier that matches
* our "Harddisk#Partition#", as reported by QueryDosDevice().
* The returned string is allocated and must be freed.
*/
char* AltGetLogicalName(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bKeepTrailingBackslash, BOOL bSilent)
{
DWORD i;
char *ret = NULL, volume_name[MAX_PATH], path[MAX_PATH];
CheckDriveIndex(DriveIndex);
// Match the offset to a partition index
for (i = 0; (i < MAX_PARTITIONS) && (PartitionOffset != 0) && (PartitionOffset != SelectedDrive.PartitionOffset[i]); i++);
if (i >= MAX_PARTITIONS) {
suprintf("Error: Could not find a partition at offset %lld on this disk", PartitionOffset);
goto out;
}
static_sprintf(path, "Harddisk%luPartition%lu", DriveIndex, i + 1);
static_strcpy(volume_name, groot_name);
if (!QueryDosDeviceA(path, &volume_name[groot_len], (DWORD)(MAX_PATH - groot_len)) || (strlen(volume_name) < 20)) {
suprintf("Could not find the DOS volume name for '%s': %s", path, WindowsErrorString());
} else {
if (bKeepTrailingBackslash)
static_strcat(volume_name, "\\");
ret = safe_strdup(volume_name);
}
out:
return ret;
}
/*
* Call on VDS to refresh the drive layout
*/
@ -720,7 +728,7 @@ out:
/* Wait for a logical drive to reappear - Used when a drive has just been repartitioned */
BOOL WaitForLogical(DWORD DriveIndex, DWORD PartitionIndex)
BOOL WaitForLogical(DWORD DriveIndex, uint64_t PartitionOffset)
{
uint64_t EndTime;
char* LogicalPath = NULL;
@ -729,7 +737,7 @@ BOOL WaitForLogical(DWORD DriveIndex, DWORD PartitionIndex)
// make sure we don't spend more than DRIVE_ACCESS_TIMEOUT in wait.
EndTime = GetTickCount64() + DRIVE_ACCESS_TIMEOUT;
do {
LogicalPath = GetLogicalName(DriveIndex, PartitionIndex, FALSE, TRUE);
LogicalPath = GetLogicalName(DriveIndex, PartitionOffset, FALSE, TRUE);
// Need to filter out GlobalRoot devices as we don't want to wait on those
if ((LogicalPath != NULL) && (strncmp(LogicalPath, groot_name, groot_len) != 0)) {
free(LogicalPath);
@ -749,10 +757,10 @@ BOOL WaitForLogical(DWORD DriveIndex, DWORD PartitionIndex)
* Returns INVALID_HANDLE_VALUE on error or NULL if no logical path exists (typical
* of unpartitioned drives)
*/
HANDLE GetLogicalHandle(DWORD DriveIndex, DWORD PartitionIndex, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare)
HANDLE GetLogicalHandle(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare)
{
HANDLE hLogical = INVALID_HANDLE_VALUE;
char* LogicalPath = GetLogicalName(DriveIndex, PartitionIndex, FALSE, FALSE);
char* LogicalPath = GetLogicalName(DriveIndex, PartitionOffset, FALSE, FALSE);
if (LogicalPath == NULL) {
uprintf("No logical drive found (unpartitioned?)");
@ -767,10 +775,10 @@ HANDLE GetLogicalHandle(DWORD DriveIndex, DWORD PartitionIndex, BOOL bLockDrive,
/*
* Similar to the above, but use the partition name instead
*/
HANDLE GetPartitionHandle(DWORD DriveIndex, DWORD PartitionIndex, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare)
HANDLE GetPartitionHandle(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare)
{
HANDLE handle = INVALID_HANDLE_VALUE;
char* volume_name = GetPartitionName(DriveIndex, PartitionIndex);
char* volume_name = GetPartitionName(DriveIndex, PartitionOffset);
if (volume_name == NULL) {
uprintf("Could not get partition volume name");
@ -1158,6 +1166,7 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys
return FALSE;
SelectedDrive.nPartitions = 0;
memset(SelectedDrive.PartitionOffset, 0, sizeof(SelectedDrive.PartitionOffset));
// Populate the filesystem data
FileSystemName[0] = 0;
volume_name = GetLogicalName(DriveIndex, 0, TRUE, FALSE);
@ -1246,6 +1255,8 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys
break;
}
}
if (i < MAX_PARTITIONS)
SelectedDrive.PartitionOffset[i] = DriveLayout->PartitionEntry[i].StartingOffset.QuadPart;
// NB: MinGW's gcc 4.9.2 broke "%lld" printout on XP so we use the inttypes.h "PRI##" qualifiers
suprintf(" Type: %s (0x%02x)\r\n Size: %s (%" PRIi64 " bytes)\r\n Start Sector: %" PRIi64 ", Boot: %s",
((part_type==0x07||super_floppy_disk)&&(FileSystemName[0]!=0))?FileSystemName:GetPartitionType(part_type), super_floppy_disk?0:part_type,
@ -1271,6 +1282,8 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys
suprintf("Max parts: %d, Start Offset: %" PRIi64 ", Usable = %" PRIi64 " bytes",
DriveLayout->Gpt.MaxPartitionCount, DriveLayout->Gpt.StartingUsableOffset.QuadPart, DriveLayout->Gpt.UsableLength.QuadPart);
for (i=0; i<DriveLayout->PartitionCount; i++) {
if (i < MAX_PARTITIONS)
SelectedDrive.PartitionOffset[i] = DriveLayout->PartitionEntry[i].StartingOffset.QuadPart;
SelectedDrive.nPartitions++;
isUefiNtfs = (wcscmp(DriveLayout->PartitionEntry[i].Gpt.Name, L"UEFI:NTFS") == 0);
suprintf("Partition %d%s:\r\n Type: %s\r\n Name: '%S'", i+1, isUefiNtfs ? " (UEFI:NTFS)" : "",
@ -1401,33 +1414,33 @@ BOOL MountVolume(char* drive_name, char *volume_name)
/*
* Alternate version of MountVolume required for ESP's, since Windows (including VDS) does
* *NOT* provide any means of mounting these volume but through DefineDosDevice(). Also
* note the bcdboot is very finicky about what it may or may not handle, even if the
* note that bcdboot is very finicky about what it may or may not handle, even if the
* mount was successful (e.g. '\Device\HarddiskVolume###' vs 'Device\HarddiskVolume###').
* Returned string is static (no concurrency) and should not be freed.
* Returned string is static (no concurrency) and must not be freed.
*/
char* AltMountVolume(DWORD DriveIndex, DWORD PartitionIndex)
char* AltMountVolume(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bSilent)
{
char* ret = NULL, *volume_name = NULL;
static char mounted_drive[] = "?:";
mounted_drive[0] = GetUnusedDriveLetter();
if (mounted_drive[0] == 0) {
uprintf("Could not find an unused drive letter");
suprintf("Could not find an unused drive letter");
goto out;
}
volume_name = GetLogicalName(DriveIndex, PartitionIndex, FALSE, TRUE);
// Can't use a regular volume GUID for ESPs...
volume_name = AltGetLogicalName(DriveIndex, PartitionOffset, FALSE, TRUE);
if ((volume_name == NULL) || (strncmp(volume_name, groot_name, groot_len) != 0)) {
uprintf("Unexpected volume name: '%s'", volume_name);
suprintf("Unexpected volume name: '%s'", volume_name);
goto out;
}
// bcdboot sure won't like it if you forget the starting '\'
suprintf("Mounting '%s' as '%s'", &volume_name[14], mounted_drive);
// bcdboot doesn't like it if you forget the starting '\'
if (!DefineDosDeviceA(DDD_RAW_TARGET_PATH | DDD_NO_BROADCAST_SYSTEM, mounted_drive, &volume_name[14])) {
uprintf("Could not mount '%s' to '%s': %s", &volume_name[14], mounted_drive, WindowsErrorString());
suprintf("Mount operation failed: %s", WindowsErrorString());
goto out;
}
uprintf("Successfully mounted '%s' (Partition %d) as '%s'", &volume_name[14], PartitionIndex, mounted_drive);
ret = mounted_drive;
out:
@ -1438,15 +1451,15 @@ out:
/*
* Unmount a volume that was mounted by AltmountVolume()
*/
BOOL AltUnmountVolume(const char* drive_name)
BOOL AltUnmountVolume(const char* drive_name, BOOL bSilent)
{
if (drive_name == NULL)
return FALSE;
if (!DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_NO_BROADCAST_SYSTEM, drive_name, NULL)) {
uprintf("Could not unmount '%s': %s", drive_name, WindowsErrorString());
suprintf("Could not unmount '%s': %s", drive_name, WindowsErrorString());
return FALSE;
}
uprintf("Successfully unmounted '%s'", drive_name);
suprintf("Successfully unmounted '%s'", drive_name);
return TRUE;
}
@ -1536,7 +1549,8 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
if (uefi_ntfs_size == 0)
return FALSE;
}
memset(partition_index, 0, sizeof(partition_index));
memset(partition_offset, 0, sizeof(partition_offset));
memset(SelectedDrive.PartitionOffset, 0, sizeof(SelectedDrive.PartitionOffset));
// Compute the start offset of our first partition
if ((partition_style == PARTITION_STYLE_GPT) || (!IsChecked(IDC_OLD_BIOS_FIXES))) {
@ -1560,6 +1574,7 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
// Zero the first sectors from this partition to avoid file system caching issues
if (!ClearPartition(hDrive, DriveLayoutEx.PartitionEntry[pn].StartingOffset, size_to_clear))
uprintf("Could not zero %S: %s", extra_part_name, WindowsErrorString());
SelectedDrive.PartitionOffset[pn] = DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart;
pn++;
DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = DriveLayoutEx.PartitionEntry[pn-1].StartingOffset.QuadPart +
DriveLayoutEx.PartitionEntry[pn-1].PartitionLength.QuadPart;
@ -1641,15 +1656,12 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
IGNORE_RETVAL(CoCreateGuid(&DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionId));
wcsncpy(DriveLayoutEx.PartitionEntry[pn].Gpt.Name, main_part_name, ARRAYSIZE(DriveLayoutEx.PartitionEntry[pn].Gpt.Name));
}
SelectedDrive.PartitionOffset[pn] = DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart;
partition_offset[PI_MAIN] = SelectedDrive.PartitionOffset[pn];
pn++;
partition_index[PI_MAIN] = pn;
// Set the optional extra partition
if (extra_partitions) {
if (extra_partitions & XP_CASPER)
partition_index[PI_CASPER] = pn + 1;
else if (extra_partitions & XP_ESP)
partition_index[PI_ESP] = pn + 1;
// Should end on a track boundary
DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = DriveLayoutEx.PartitionEntry[pn-1].StartingOffset.QuadPart +
DriveLayoutEx.PartitionEntry[pn-1].PartitionLength.QuadPart;
@ -1657,6 +1669,12 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
extra_part_size_in_tracks * bytes_per_track;
uprintf("● Creating %S Partition (offset: %lld, size: %s)", extra_part_name, DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart,
SizeToHumanReadable(DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart, TRUE, FALSE));
SelectedDrive.PartitionOffset[pn] = DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart;
if (extra_partitions & XP_CASPER)
partition_offset[PI_CASPER] = SelectedDrive.PartitionOffset[pn];
else if (extra_partitions & XP_ESP)
partition_offset[PI_ESP] = SelectedDrive.PartitionOffset[pn];
if (partition_style == PARTITION_STYLE_GPT) {
DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionType = (extra_partitions & XP_ESP) ? PARTITION_SYSTEM_GUID : PARTITION_BASIC_DATA_GUID;
IGNORE_RETVAL(CoCreateGuid(&DriveLayoutEx.PartitionEntry[pn].Gpt.PartitionId));

View File

@ -350,6 +350,7 @@ typedef struct {
MEDIA_TYPE MediaType;
int PartitionStyle;
int nPartitions; // number of partitions we actually care about
uint64_t PartitionOffset[MAX_PARTITIONS];
int FSType;
char proposed_label[16];
BOOL has_protective_mbr;
@ -360,18 +361,19 @@ typedef struct {
} ClusterSize[FS_MAX];
} RUFUS_DRIVE_INFO;
extern RUFUS_DRIVE_INFO SelectedDrive;
extern DWORD partition_index[3];
extern uint64_t partition_offset[3];
BOOL SetAutoMount(BOOL enable);
BOOL GetAutoMount(BOOL* enabled);
char* GetPhysicalName(DWORD DriveIndex);
char* GetPartitionName(DWORD DriveIndex, DWORD PartitionIndex);
char* GetPartitionName(DWORD DriveIndex, uint64_t PartitionOffset);
BOOL DeletePartitions(DWORD DriveIndex);
HANDLE GetPhysicalHandle(DWORD DriveIndex, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare);
char* GetLogicalName(DWORD DriveIndex, DWORD PartitionIndex, BOOL bKeepTrailingBackslash, BOOL bSilent);
BOOL WaitForLogical(DWORD DriveIndex, DWORD PartitionIndex);
HANDLE GetLogicalHandle(DWORD DriveIndex, DWORD PartitionIndex, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare);
HANDLE GetPartitionHandle(DWORD DriveIndex, DWORD PartitionIndex, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare);
char* GetLogicalName(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bKeepTrailingBackslash, BOOL bSilent);
char* AltGetLogicalName(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bKeepTrailingBackslash, BOOL bSilent);
BOOL WaitForLogical(DWORD DriveIndex, uint64_t PartitionOffset);
HANDLE GetLogicalHandle(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare);
HANDLE GetPartitionHandle(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare);
int GetDriveNumber(HANDLE hDrive, char* path);
BOOL GetDriveLetters(DWORD DriveIndex, char* drive_letters);
UINT GetDriveTypeFromIndex(DWORD DriveIndex);
@ -384,14 +386,14 @@ BOOL AnalyzePBR(HANDLE hLogicalVolume);
BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSystemNameSize, BOOL bSilent);
BOOL UnmountVolume(HANDLE hDrive);
BOOL MountVolume(char* drive_name, char *drive_guid);
BOOL AltUnmountVolume(const char* drive_name);
char* AltMountVolume(DWORD DriveIndex, DWORD PartitionIndex);
BOOL AltUnmountVolume(const char* drive_name, BOOL bSilent);
char* AltMountVolume(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bSilent);
BOOL RemountVolume(char* drive_name);
BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL mbr_uefi_marker, uint8_t extra_partitions);
BOOL InitializeDisk(HANDLE hDrive);
BOOL RefreshDriveLayout(HANDLE hDrive);
const char* GetPartitionType(BYTE Type);
const char* GetExtFsLabel(DWORD DriveIndex, DWORD PartitionIndex);
const char* GetExtFsLabel(DWORD DriveIndex, uint64_t PartitionOffset);
BOOL GetDevices(DWORD devnum);
BOOL CyclePort(int index);
int CycleDevice(int index);

View File

@ -373,7 +373,7 @@ static DWORD GetFATSizeSectors(DWORD DskSize, DWORD ReservedSecCnt, DWORD SecPer
* Large FAT32 volume formatting from fat32format by Tom Thornhill
* http://www.ridgecrop.demon.co.uk/index.htm?fat32format.htm
*/
static BOOL FormatFAT32(DWORD DriveIndex, DWORD PartitionIndex, DWORD ClusterSize, LPCSTR FSName, LPCSTR Label, DWORD Flags)
static BOOL FormatFAT32(DWORD DriveIndex, uint64_t PartitionOffset, DWORD ClusterSize, LPCSTR FSName, LPCSTR Label, DWORD Flags)
{
BOOL r = FALSE;
DWORD i;
@ -420,7 +420,7 @@ static BOOL FormatFAT32(DWORD DriveIndex, DWORD PartitionIndex, DWORD ClusterSiz
VolumeId = GetVolumeID();
// Open the drive and lock it
hLogicalVolume = GetLogicalHandle(DriveIndex, PartitionIndex, TRUE, TRUE, FALSE);
hLogicalVolume = GetLogicalHandle(DriveIndex, PartitionOffset, TRUE, TRUE, FALSE);
if (IS_ERROR(FormatStatus))
goto out;
if ((hLogicalVolume == INVALID_HANDLE_VALUE) || (hLogicalVolume == NULL))
@ -651,7 +651,7 @@ static BOOL FormatFAT32(DWORD DriveIndex, DWORD PartitionIndex, DWORD ClusterSiz
PrintInfoDebug(0, MSG_221);
// Handle must be closed for SetVolumeLabel to work
safe_closehandle(hLogicalVolume);
VolumeName = GetLogicalName(DriveIndex, PartitionIndex, TRUE, TRUE);
VolumeName = GetLogicalName(DriveIndex, PartitionOffset, TRUE, TRUE);
if ((VolumeName == NULL) || (!SetVolumeLabelA(VolumeName, Label))) {
uprintf("Could not set label: %s", WindowsErrorString());
// Non fatal error
@ -819,14 +819,16 @@ errcode_t ext2fs_print_progress(int64_t cur_value, int64_t max_value)
return IS_ERROR(FormatStatus) ? EXT2_ET_CANCEL_REQUESTED : 0;
}
const char* GetExtFsLabel(DWORD DriveIndex, DWORD PartitionIndex)
const char* GetExtFsLabel(DWORD DriveIndex, uint64_t PartitionOffset)
{
static char label[EXT2_LABEL_LEN + 1];
errcode_t r;
ext2_filsys ext2fs = NULL;
io_manager manager = nt_io_manager();
char* volume_name = GetPartitionName(DriveIndex, PartitionIndex);
char* volume_name = AltMountVolume(DriveIndex, PartitionOffset, TRUE);
if (volume_name == NULL)
return NULL;
r = ext2fs_open(volume_name, EXT2_FLAG_SKIP_MMP, 0, 0, manager, &ext2fs);
if (r == 0) {
strncpy(label, ext2fs->super->s_volume_name, EXT2_LABEL_LEN);
@ -834,11 +836,11 @@ const char* GetExtFsLabel(DWORD DriveIndex, DWORD PartitionIndex)
}
if (ext2fs != NULL)
ext2fs_close(ext2fs);
free(volume_name);
AltUnmountVolume(volume_name, TRUE);
return (r == 0) ? label : NULL;
}
BOOL FormatExtFs(DWORD DriveIndex, DWORD PartitionIndex, DWORD BlockSize, LPCSTR FSName, LPCSTR Label, DWORD Flags)
BOOL FormatExtFs(DWORD DriveIndex, uint64_t PartitionOffset, DWORD BlockSize, LPCSTR FSName, LPCSTR Label, DWORD Flags)
{
// Mostly taken from mke2fs.conf
const float reserve_ratio = 0.05f;
@ -877,7 +879,7 @@ BOOL FormatExtFs(DWORD DriveIndex, DWORD PartitionIndex, DWORD BlockSize, LPCSTR
}
CloseHandle(h);
#else
volume_name = GetPartitionName(DriveIndex, PartitionIndex);
volume_name = AltMountVolume(DriveIndex, PartitionOffset, FALSE);
#endif
if ((volume_name == NULL) | (strlen(FSName) != 4) || (strncmp(FSName, "ext", 3) != 0)) {
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_INVALID_PARAMETER;
@ -1097,14 +1099,14 @@ BOOL FormatExtFs(DWORD DriveIndex, DWORD PartitionIndex, DWORD BlockSize, LPCSTR
out:
ext2fs_free(ext2fs);
free(buf);
free(volume_name);
AltUnmountVolume(volume_name, FALSE);
return ret;
}
/*
* Call on VDS to format a partition
*/
static BOOL FormatDriveVds(DWORD DriveIndex, DWORD PartitionIndex, DWORD ClusterSize, LPCSTR FSName, LPCSTR Label, DWORD Flags)
static BOOL FormatDriveVds(DWORD DriveIndex, uint64_t PartitionOffset, DWORD ClusterSize, LPCSTR FSName, LPCSTR Label, DWORD Flags)
{
BOOL r = FALSE, bFoundVolume = FALSE;
HRESULT hr;
@ -1122,7 +1124,7 @@ static BOOL FormatDriveVds(DWORD DriveIndex, DWORD PartitionIndex, DWORD Cluster
PrintInfoDebug(0, MSG_222, FSName);
}
LastRefresh = 0;
VolumeName = GetLogicalName(DriveIndex, PartitionIndex, TRUE, TRUE);
VolumeName = GetLogicalName(DriveIndex, PartitionOffset, TRUE, TRUE);
wVolumeName = utf8_to_wchar(VolumeName);
if (wVolumeName == NULL) {
uprintf("Could not read volume name");
@ -1350,7 +1352,7 @@ out:
/*
* Call on fmifs.dll's FormatEx() to format the drive
*/
static BOOL FormatDrive(DWORD DriveIndex, DWORD PartitionIndex, DWORD ClusterSize, LPCSTR FSName, LPCSTR Label, DWORD Flags)
static BOOL FormatDrive(DWORD DriveIndex, uint64_t PartitionOffset, DWORD ClusterSize, LPCSTR FSName, LPCSTR Label, DWORD Flags)
{
BOOL r = FALSE;
PF_DECL(FormatEx);
@ -1364,10 +1366,10 @@ static BOOL FormatDrive(DWORD DriveIndex, DWORD PartitionIndex, DWORD ClusterSiz
} else {
PrintInfoDebug(0, MSG_222, FSName);
}
VolumeName = GetLogicalName(DriveIndex, PartitionIndex, TRUE, TRUE);
VolumeName = GetLogicalName(DriveIndex, PartitionOffset, TRUE, TRUE);
wVolumeName = utf8_to_wchar(VolumeName);
if (wVolumeName == NULL) {
uprintf("Could not read volume name\n");
uprintf("Could not read volume name");
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_GEN_FAILURE;
goto out;
}
@ -1429,9 +1431,9 @@ out:
return r;
}
static BOOL FormatPartition(DWORD DriveIndex, DWORD PartitionIndex, DWORD UnitAllocationSize, USHORT FSType, LPCSTR Label, DWORD Flags)
static BOOL FormatPartition(DWORD DriveIndex, uint64_t PartitionOffset, DWORD UnitAllocationSize, USHORT FSType, LPCSTR Label, DWORD Flags)
{
if ((DriveIndex < 0x80) || (DriveIndex > 0x100) || (PartitionIndex >= MAX_PARTITIONS) || (FSType >= FS_MAX) ||
if ((DriveIndex < 0x80) || (DriveIndex > 0x100) || (FSType >= FS_MAX) ||
// The following validates that UnitAllocationSize is a power of 2
((UnitAllocationSize != 0) && (UnitAllocationSize & (UnitAllocationSize - 1)))) {
ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_INVALID_PARAMETER;
@ -1439,13 +1441,13 @@ static BOOL FormatPartition(DWORD DriveIndex, DWORD PartitionIndex, DWORD UnitAl
}
actual_fs_type = FSType;
if ((FSType == FS_FAT32) && ((SelectedDrive.DiskSize > LARGE_FAT32_SIZE) || (force_large_fat32) || (Flags & FP_LARGE_FAT32)))
return FormatFAT32(DriveIndex, PartitionIndex, UnitAllocationSize, FileSystemLabel[FSType], Label, Flags);
return FormatFAT32(DriveIndex, PartitionOffset, UnitAllocationSize, FileSystemLabel[FSType], Label, Flags);
else if (FSType >= FS_EXT2)
return FormatExtFs(DriveIndex, PartitionIndex, UnitAllocationSize, FileSystemLabel[FSType], Label, Flags);
return FormatExtFs(DriveIndex, PartitionOffset, UnitAllocationSize, FileSystemLabel[FSType], Label, Flags);
else if (use_vds)
return FormatDriveVds(DriveIndex, PartitionIndex, UnitAllocationSize, FileSystemLabel[FSType], Label, Flags);
return FormatDriveVds(DriveIndex, PartitionOffset, UnitAllocationSize, FileSystemLabel[FSType], Label, Flags);
else
return FormatDrive(DriveIndex, PartitionIndex, UnitAllocationSize, FileSystemLabel[FSType], Label, Flags);
return FormatDrive(DriveIndex, PartitionOffset, UnitAllocationSize, FileSystemLabel[FSType], Label, Flags);
}
/*
@ -2159,7 +2161,7 @@ static BOOL SetupWinToGo(DWORD DriveIndex, const char* drive_name, BOOL use_esp)
// VDS cannot list ESP volumes (talk about allegedly improving on the old disk and volume APIs, only to
// completely neuter it) and IVdsDiskPartitionMF::FormatPartitionEx(), which is what you are supposed to
// use for ESPs, explicitly states: "This method cannot be used to format removable media."
if (!FormatPartition(DriveIndex, partition_index[PI_ESP], cluster_size, FS_FAT32, "",
if (!FormatPartition(DriveIndex, partition_offset[PI_ESP], cluster_size, FS_FAT32, "",
FP_QUICK | FP_FORCE | FP_LARGE_FAT32 | FP_NO_BOOT)) {
uprintf("Could not format EFI System Partition");
return FALSE;
@ -2169,7 +2171,7 @@ static BOOL SetupWinToGo(DWORD DriveIndex, const char* drive_name, BOOL use_esp)
if (use_esp) {
// Need to have the ESP mounted to invoke bcdboot
ms_efi = AltMountVolume(DriveIndex, partition_index[PI_ESP]);
ms_efi = AltMountVolume(DriveIndex, partition_offset[PI_ESP], FALSE);
if (ms_efi == NULL) {
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_CANT_ASSIGN_LETTER);
return FALSE;
@ -2192,7 +2194,7 @@ static BOOL SetupWinToGo(DWORD DriveIndex, const char* drive_name, BOOL use_esp)
if (use_esp) {
Sleep(200);
AltUnmountVolume(ms_efi);
AltUnmountVolume(ms_efi, FALSE);
}
PrintInfo(0, MSG_267, 99.9f);
UpdateProgress(OP_DOS, 99.9f);
@ -2679,7 +2681,7 @@ DWORD WINAPI FormatThread(void* param)
// Wait for the logical drive we just created to appear
uprintf("Waiting for logical drive to reappear...");
Sleep(200);
if (!WaitForLogical(DriveIndex, partition_index[PI_MAIN])) {
if (!WaitForLogical(DriveIndex, partition_offset[PI_MAIN])) {
uprintf("Logical drive was not found - aborting");
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_NO_VOLUME_ID;
goto out;
@ -2693,7 +2695,7 @@ DWORD WINAPI FormatThread(void* param)
if ((ext_version < 2) || (ext_version > 4))
ext_version = 3;
uprintf("Using %s-like method to enable persistence", img_report.uses_casper ? "Ubuntu" : "Debian");
if (!FormatPartition(DriveIndex, partition_index[PI_CASPER], 0, FS_EXT2 + (ext_version - 2),
if (!FormatPartition(DriveIndex, partition_offset[PI_CASPER], 0, FS_EXT2 + (ext_version - 2),
img_report.uses_casper ? "casper-rw" : "persistence",
(img_report.uses_casper ? 0 : FP_CREATE_PERSISTENCE_CONF) |
(IsChecked(IDC_QUICK_FORMAT) ? FP_QUICK : 0))) {
@ -2716,7 +2718,7 @@ DWORD WINAPI FormatThread(void* param)
if ((fs_type == FS_NTFS) && (enable_ntfs_compression))
Flags |= FP_COMPRESSION;
ret = FormatPartition(DriveIndex, partition_index[PI_MAIN], ClusterSize, fs_type, label, Flags);
ret = FormatPartition(DriveIndex, partition_offset[PI_MAIN], ClusterSize, fs_type, label, Flags);
if (!ret) {
// Error will be set by FormatPartition() in FormatStatus
uprintf("Format error: %s", StrError(FormatStatus, TRUE));
@ -2747,7 +2749,7 @@ DWORD WINAPI FormatThread(void* param)
// Try to continue
CHECK_FOR_USER_CANCEL;
volume_name = GetLogicalName(DriveIndex, partition_index[PI_MAIN], TRUE, TRUE);
volume_name = GetLogicalName(DriveIndex, partition_offset[PI_MAIN], TRUE, TRUE);
if (volume_name == NULL) {
uprintf("Could not get volume name");
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NO_VOLUME_ID;
@ -2800,8 +2802,7 @@ DWORD WINAPI FormatThread(void* param)
} else {
// We still have a lock, which we need to modify the volume boot record
// => no need to reacquire the lock...
// TODO: Shouldn't PI always be 1 here?
hLogicalVolume = GetLogicalHandle(DriveIndex, partition_index[PI_MAIN], FALSE, TRUE, FALSE);
hLogicalVolume = GetLogicalHandle(DriveIndex, partition_offset[PI_MAIN], FALSE, TRUE, FALSE);
if ((hLogicalVolume == INVALID_HANDLE_VALUE) || (hLogicalVolume == NULL)) {
uprintf("Could not re-mount volume for partition boot record access");
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;

View File

@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 232, 326
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_ACCEPTFILES
CAPTION "Rufus 3.7.1561"
CAPTION "Rufus 3.7.1562"
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
BEGIN
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
@ -394,8 +394,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,7,1561,0
PRODUCTVERSION 3,7,1561,0
FILEVERSION 3,7,1562,0
PRODUCTVERSION 3,7,1562,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -413,13 +413,13 @@ BEGIN
VALUE "Comments", "https://akeo.ie"
VALUE "CompanyName", "Akeo Consulting"
VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "3.7.1561"
VALUE "FileVersion", "3.7.1562"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2019 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "https://www.gnu.org/copyleft/gpl.html"
VALUE "OriginalFilename", "rufus-3.7.exe"
VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "3.7.1561"
VALUE "ProductVersion", "3.7.1562"
END
END
BLOCK "VarFileInfo"