diff --git a/src/drive.c b/src/drive.c index b7c0fa52..6d0db01c 100644 --- a/src/drive.c +++ b/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; iPartitionCount; 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)); diff --git a/src/drive.h b/src/drive.h index 231c4741..d2432744 100644 --- a/src/drive.h +++ b/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); diff --git a/src/format.c b/src/format.c index 8dba48af..3a39d034 100644 --- a/src/format.c +++ b/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; diff --git a/src/rufus.rc b/src/rufus.rc index 8649a7d3..8752c7b8 100644 --- a/src/rufus.rc +++ b/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"