mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[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:
parent
1fa0aaf325
commit
94e2015edf
4 changed files with 133 additions and 112 deletions
156
src/drive.c
156
src/drive.c
|
@ -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));
|
||||
|
|
20
src/drive.h
20
src/drive.h
|
@ -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);
|
||||
|
|
59
src/format.c
59
src/format.c
|
@ -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;
|
||||
|
|
10
src/rufus.rc
10
src/rufus.rc
|
@ -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"
|
||||
|
|
Loading…
Reference in a new issue