mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[ext2fs] fix creation of persistent partitions for pre-1703 platforms
* Windows platforms prior to Windows 10 1703 cannot access any logical partition besides the first one (we don't even get a volume for those). * This fix enables the use of physical + offset for ext# formatting to work around this, which is file since we don't actually need to mount the partition. * Also fix ext2fs_open2() not handling normalized versions of Windows drive paths ("\\?\...") * Also fix an issue where we would make the drive letter unavailable after formatting a standalone partition to ext#. * Also ensure that we return an error if the drive we attempt to locate a partition on through an offset does not match the currently selected one. * Also remove some unused calls in drive.c. * Closes #1374
This commit is contained in:
parent
0a24940c85
commit
bf8d888b21
7 changed files with 89 additions and 83 deletions
81
src/drive.c
81
src/drive.c
|
@ -242,23 +242,6 @@ out:
|
||||||
return (success)?safe_strdup(physical_name):NULL;
|
return (success)?safe_strdup(physical_name):NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* 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, uint64_t PartitionOffset)
|
|
||||||
{
|
|
||||||
char partition_name[32];
|
|
||||||
DWORD i = MAX_PARTITIONS + 1;
|
|
||||||
|
|
||||||
CheckDriveIndex(DriveIndex);
|
|
||||||
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 (i <= MAX_PARTITIONS) ? safe_strdup(partition_name) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return a handle to the physical drive identified by DriveIndex
|
* Return a handle to the physical drive identified by DriveIndex
|
||||||
*/
|
*/
|
||||||
|
@ -387,11 +370,14 @@ char* GetLogicalName(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bKeepTrail
|
||||||
// Now process all the volumes we found, and try to match one with our partition offset
|
// 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++);
|
for (i = 0; (i < found_name.Index) && (PartitionOffset != 0) && (PartitionOffset != found_offset[i]); i++);
|
||||||
|
|
||||||
if (i < found_name.Index)
|
if (i < found_name.Index) {
|
||||||
ret = safe_strdup(found_name.String[i]);
|
ret = safe_strdup(found_name.String[i]);
|
||||||
else
|
} else {
|
||||||
// NB: We need to re-add DRIVE_INDEX_MIN for this call since CheckDriveIndex() substracted it
|
// 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);
|
ret = AltGetLogicalName(DriveIndex + DRIVE_INDEX_MIN, PartitionOffset, bKeepTrailingBackslash, bSilent);
|
||||||
|
if ((ret != NULL) && (strchr(ret, ' ') != NULL))
|
||||||
|
uprintf("Warning: Using physical device to access partition data");
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (hVolume != INVALID_HANDLE_VALUE)
|
if (hVolume != INVALID_HANDLE_VALUE)
|
||||||
|
@ -409,26 +395,38 @@ out:
|
||||||
*/
|
*/
|
||||||
char* AltGetLogicalName(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bKeepTrailingBackslash, BOOL bSilent)
|
char* AltGetLogicalName(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bKeepTrailingBackslash, BOOL bSilent)
|
||||||
{
|
{
|
||||||
|
BOOL matching_drive = (DriveIndex == SelectedDrive.DeviceNumber);
|
||||||
DWORD i;
|
DWORD i;
|
||||||
char *ret = NULL, volume_name[MAX_PATH], path[MAX_PATH];
|
char *ret = NULL, volume_name[MAX_PATH], path[64];
|
||||||
|
|
||||||
CheckDriveIndex(DriveIndex);
|
CheckDriveIndex(DriveIndex);
|
||||||
|
|
||||||
// Match the offset to a partition index
|
// Match the offset to a partition index
|
||||||
for (i = 0; (i < MAX_PARTITIONS) && (PartitionOffset != 0) && (PartitionOffset != SelectedDrive.PartitionOffset[i]); i++);
|
if (PartitionOffset == 0) {
|
||||||
|
i = 0;
|
||||||
|
} else if (matching_drive) {
|
||||||
|
for (i = 0; (i < MAX_PARTITIONS) && (PartitionOffset != SelectedDrive.PartitionOffset[i]); i++);
|
||||||
if (i >= MAX_PARTITIONS) {
|
if (i >= MAX_PARTITIONS) {
|
||||||
suprintf("Error: Could not find a partition at offset %lld on this disk", PartitionOffset);
|
suprintf("Error: Could not find a partition at offset %lld on this disk", PartitionOffset);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
suprintf("Error: Searching for a partition on a non matching disk");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
static_sprintf(path, "Harddisk%luPartition%lu", DriveIndex, i + 1);
|
static_sprintf(path, "Harddisk%luPartition%lu", DriveIndex, i + 1);
|
||||||
static_strcpy(volume_name, groot_name);
|
static_strcpy(volume_name, groot_name);
|
||||||
if (!QueryDosDeviceA(path, &volume_name[groot_len], (DWORD)(MAX_PATH - groot_len)) || (strlen(volume_name) < 20)) {
|
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());
|
suprintf("Could not find a DOS volume name for '%s': %s", path, WindowsErrorString());
|
||||||
} else {
|
// If we are on the right drive, we enable a custom access mode through physical + offset
|
||||||
if (bKeepTrailingBackslash)
|
if (!matching_drive)
|
||||||
|
goto out;
|
||||||
|
static_sprintf(volume_name, "\\\\.\\PhysicalDrive%lu%s %I64u %I64u", DriveIndex, bKeepTrailingBackslash ? "\\" : "",
|
||||||
|
SelectedDrive.PartitionOffset[i], SelectedDrive.PartitionSize[i]);
|
||||||
|
} else if (bKeepTrailingBackslash) {
|
||||||
static_strcat(volume_name, "\\");
|
static_strcat(volume_name, "\\");
|
||||||
ret = safe_strdup(volume_name);
|
|
||||||
}
|
}
|
||||||
|
ret = safe_strdup(volume_name);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -772,24 +770,6 @@ HANDLE GetLogicalHandle(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bLockDr
|
||||||
return hLogical;
|
return hLogical;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Similar to the above, but use the partition name instead
|
|
||||||
*/
|
|
||||||
HANDLE GetPartitionHandle(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare)
|
|
||||||
{
|
|
||||||
HANDLE handle = INVALID_HANDLE_VALUE;
|
|
||||||
char* volume_name = GetPartitionName(DriveIndex, PartitionOffset);
|
|
||||||
|
|
||||||
if (volume_name == NULL) {
|
|
||||||
uprintf("Could not get partition volume name");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
handle = GetHandle(volume_name, bLockDrive, bWriteAccess, bWriteShare);
|
|
||||||
free(volume_name);
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Who would have thought that Microsoft would make it so unbelievably hard to
|
* Who would have thought that Microsoft would make it so unbelievably hard to
|
||||||
* get the frickin' device number for a drive? You have to use TWO different
|
* get the frickin' device number for a drive? You have to use TWO different
|
||||||
|
@ -984,7 +964,7 @@ BOOL GetDriveLabel(DWORD DriveIndex, char* letters, char** label)
|
||||||
if (GetVolumeInformationByHandleW(h, VolumeName, 64, &VolumeSerialNumber,
|
if (GetVolumeInformationByHandleW(h, VolumeName, 64, &VolumeSerialNumber,
|
||||||
&MaximumComponentLength, &FileSystemFlags, FileSystemName, 64)) {
|
&MaximumComponentLength, &FileSystemFlags, FileSystemName, 64)) {
|
||||||
wchar_to_utf8_no_alloc(VolumeName, VolumeLabel, sizeof(VolumeLabel));
|
wchar_to_utf8_no_alloc(VolumeName, VolumeLabel, sizeof(VolumeLabel));
|
||||||
*label = VolumeLabel;
|
*label = (VolumeLabel[0] != 0) ? VolumeLabel : STR_NO_LABEL;
|
||||||
}
|
}
|
||||||
// Drive without volume assigned - always enabled
|
// Drive without volume assigned - always enabled
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -1167,6 +1147,7 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys
|
||||||
|
|
||||||
SelectedDrive.nPartitions = 0;
|
SelectedDrive.nPartitions = 0;
|
||||||
memset(SelectedDrive.PartitionOffset, 0, sizeof(SelectedDrive.PartitionOffset));
|
memset(SelectedDrive.PartitionOffset, 0, sizeof(SelectedDrive.PartitionOffset));
|
||||||
|
memset(SelectedDrive.PartitionSize, 0, sizeof(SelectedDrive.PartitionSize));
|
||||||
// Populate the filesystem data
|
// Populate the filesystem data
|
||||||
FileSystemName[0] = 0;
|
FileSystemName[0] = 0;
|
||||||
volume_name = GetLogicalName(DriveIndex, 0, TRUE, FALSE);
|
volume_name = GetLogicalName(DriveIndex, 0, TRUE, FALSE);
|
||||||
|
@ -1255,8 +1236,10 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i < MAX_PARTITIONS)
|
if (i < MAX_PARTITIONS) {
|
||||||
SelectedDrive.PartitionOffset[i] = DriveLayout->PartitionEntry[i].StartingOffset.QuadPart;
|
SelectedDrive.PartitionOffset[i] = DriveLayout->PartitionEntry[i].StartingOffset.QuadPart;
|
||||||
|
SelectedDrive.PartitionSize[i] = DriveLayout->PartitionEntry[i].PartitionLength.QuadPart;
|
||||||
|
}
|
||||||
// NB: MinGW's gcc 4.9.2 broke "%lld" printout on XP so we use the inttypes.h "PRI##" qualifiers
|
// 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",
|
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,
|
((part_type==0x07||super_floppy_disk)&&(FileSystemName[0]!=0))?FileSystemName:GetPartitionType(part_type), super_floppy_disk?0:part_type,
|
||||||
|
@ -1282,8 +1265,10 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys
|
||||||
suprintf("Max parts: %d, Start Offset: %" PRIi64 ", Usable = %" PRIi64 " bytes",
|
suprintf("Max parts: %d, Start Offset: %" PRIi64 ", Usable = %" PRIi64 " bytes",
|
||||||
DriveLayout->Gpt.MaxPartitionCount, DriveLayout->Gpt.StartingUsableOffset.QuadPart, DriveLayout->Gpt.UsableLength.QuadPart);
|
DriveLayout->Gpt.MaxPartitionCount, DriveLayout->Gpt.StartingUsableOffset.QuadPart, DriveLayout->Gpt.UsableLength.QuadPart);
|
||||||
for (i=0; i<DriveLayout->PartitionCount; i++) {
|
for (i=0; i<DriveLayout->PartitionCount; i++) {
|
||||||
if (i < MAX_PARTITIONS)
|
if (i < MAX_PARTITIONS) {
|
||||||
SelectedDrive.PartitionOffset[i] = DriveLayout->PartitionEntry[i].StartingOffset.QuadPart;
|
SelectedDrive.PartitionOffset[i] = DriveLayout->PartitionEntry[i].StartingOffset.QuadPart;
|
||||||
|
SelectedDrive.PartitionSize[i] = DriveLayout->PartitionEntry[i].PartitionLength.QuadPart;
|
||||||
|
}
|
||||||
SelectedDrive.nPartitions++;
|
SelectedDrive.nPartitions++;
|
||||||
isUefiNtfs = (wcscmp(DriveLayout->PartitionEntry[i].Gpt.Name, L"UEFI:NTFS") == 0);
|
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)" : "",
|
suprintf("Partition %d%s:\r\n Type: %s\r\n Name: '%S'", i+1, isUefiNtfs ? " (UEFI:NTFS)" : "",
|
||||||
|
@ -1551,6 +1536,7 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
|
||||||
}
|
}
|
||||||
memset(partition_offset, 0, sizeof(partition_offset));
|
memset(partition_offset, 0, sizeof(partition_offset));
|
||||||
memset(SelectedDrive.PartitionOffset, 0, sizeof(SelectedDrive.PartitionOffset));
|
memset(SelectedDrive.PartitionOffset, 0, sizeof(SelectedDrive.PartitionOffset));
|
||||||
|
memset(SelectedDrive.PartitionSize, 0, sizeof(SelectedDrive.PartitionSize));
|
||||||
|
|
||||||
// Compute the start offset of our first partition
|
// Compute the start offset of our first partition
|
||||||
if ((partition_style == PARTITION_STYLE_GPT) || (!IsChecked(IDC_OLD_BIOS_FIXES))) {
|
if ((partition_style == PARTITION_STYLE_GPT) || (!IsChecked(IDC_OLD_BIOS_FIXES))) {
|
||||||
|
@ -1575,6 +1561,7 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
|
||||||
if (!ClearPartition(hDrive, DriveLayoutEx.PartitionEntry[pn].StartingOffset, size_to_clear))
|
if (!ClearPartition(hDrive, DriveLayoutEx.PartitionEntry[pn].StartingOffset, size_to_clear))
|
||||||
uprintf("Could not zero %S: %s", extra_part_name, WindowsErrorString());
|
uprintf("Could not zero %S: %s", extra_part_name, WindowsErrorString());
|
||||||
SelectedDrive.PartitionOffset[pn] = DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart;
|
SelectedDrive.PartitionOffset[pn] = DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart;
|
||||||
|
SelectedDrive.PartitionSize[pn] = DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart;
|
||||||
pn++;
|
pn++;
|
||||||
DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = DriveLayoutEx.PartitionEntry[pn-1].StartingOffset.QuadPart +
|
DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = DriveLayoutEx.PartitionEntry[pn-1].StartingOffset.QuadPart +
|
||||||
DriveLayoutEx.PartitionEntry[pn-1].PartitionLength.QuadPart;
|
DriveLayoutEx.PartitionEntry[pn-1].PartitionLength.QuadPart;
|
||||||
|
@ -1657,6 +1644,7 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
|
||||||
wcsncpy(DriveLayoutEx.PartitionEntry[pn].Gpt.Name, main_part_name, ARRAYSIZE(DriveLayoutEx.PartitionEntry[pn].Gpt.Name));
|
wcsncpy(DriveLayoutEx.PartitionEntry[pn].Gpt.Name, main_part_name, ARRAYSIZE(DriveLayoutEx.PartitionEntry[pn].Gpt.Name));
|
||||||
}
|
}
|
||||||
SelectedDrive.PartitionOffset[pn] = DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart;
|
SelectedDrive.PartitionOffset[pn] = DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart;
|
||||||
|
SelectedDrive.PartitionSize[pn] = DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart;
|
||||||
partition_offset[PI_MAIN] = SelectedDrive.PartitionOffset[pn];
|
partition_offset[PI_MAIN] = SelectedDrive.PartitionOffset[pn];
|
||||||
pn++;
|
pn++;
|
||||||
|
|
||||||
|
@ -1670,6 +1658,7 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
|
||||||
uprintf("● Creating %S Partition (offset: %lld, size: %s)", extra_part_name, DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart,
|
uprintf("● Creating %S Partition (offset: %lld, size: %s)", extra_part_name, DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart,
|
||||||
SizeToHumanReadable(DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart, TRUE, FALSE));
|
SizeToHumanReadable(DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart, TRUE, FALSE));
|
||||||
SelectedDrive.PartitionOffset[pn] = DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart;
|
SelectedDrive.PartitionOffset[pn] = DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart;
|
||||||
|
SelectedDrive.PartitionSize[pn] = DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart;
|
||||||
if (extra_partitions & XP_CASPER)
|
if (extra_partitions & XP_CASPER)
|
||||||
partition_offset[PI_CASPER] = SelectedDrive.PartitionOffset[pn];
|
partition_offset[PI_CASPER] = SelectedDrive.PartitionOffset[pn];
|
||||||
else if (extra_partitions & XP_ESP)
|
else if (extra_partitions & XP_ESP)
|
||||||
|
|
|
@ -351,6 +351,7 @@ typedef struct {
|
||||||
int PartitionStyle;
|
int PartitionStyle;
|
||||||
int nPartitions; // number of partitions we actually care about
|
int nPartitions; // number of partitions we actually care about
|
||||||
uint64_t PartitionOffset[MAX_PARTITIONS];
|
uint64_t PartitionOffset[MAX_PARTITIONS];
|
||||||
|
uint64_t PartitionSize[MAX_PARTITIONS];
|
||||||
int FSType;
|
int FSType;
|
||||||
char proposed_label[16];
|
char proposed_label[16];
|
||||||
BOOL has_protective_mbr;
|
BOOL has_protective_mbr;
|
||||||
|
@ -366,14 +367,12 @@ extern uint64_t partition_offset[3];
|
||||||
BOOL SetAutoMount(BOOL enable);
|
BOOL SetAutoMount(BOOL enable);
|
||||||
BOOL GetAutoMount(BOOL* enabled);
|
BOOL GetAutoMount(BOOL* enabled);
|
||||||
char* GetPhysicalName(DWORD DriveIndex);
|
char* GetPhysicalName(DWORD DriveIndex);
|
||||||
char* GetPartitionName(DWORD DriveIndex, uint64_t PartitionOffset);
|
|
||||||
BOOL DeletePartitions(DWORD DriveIndex);
|
BOOL DeletePartitions(DWORD DriveIndex);
|
||||||
HANDLE GetPhysicalHandle(DWORD DriveIndex, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare);
|
HANDLE GetPhysicalHandle(DWORD DriveIndex, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare);
|
||||||
char* GetLogicalName(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bKeepTrailingBackslash, BOOL bSilent);
|
char* GetLogicalName(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bKeepTrailingBackslash, BOOL bSilent);
|
||||||
char* AltGetLogicalName(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);
|
BOOL WaitForLogical(DWORD DriveIndex, uint64_t PartitionOffset);
|
||||||
HANDLE GetLogicalHandle(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bLockDrive, BOOL bWriteAccess, BOOL bWriteShare);
|
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);
|
int GetDriveNumber(HANDLE hDrive, char* path);
|
||||||
BOOL GetDriveLetters(DWORD DriveIndex, char* drive_letters);
|
BOOL GetDriveLetters(DWORD DriveIndex, char* drive_letters);
|
||||||
UINT GetDriveTypeFromIndex(DWORD DriveIndex);
|
UINT GetDriveTypeFromIndex(DWORD DriveIndex);
|
||||||
|
|
|
@ -63,6 +63,9 @@ typedef struct _NT_PRIVATE_DATA {
|
||||||
ULONG buffer_size;
|
ULONG buffer_size;
|
||||||
BOOLEAN read_only;
|
BOOLEAN read_only;
|
||||||
BOOLEAN written;
|
BOOLEAN written;
|
||||||
|
// Used by Rufus
|
||||||
|
__u64 offset;
|
||||||
|
__u64 size;
|
||||||
} NT_PRIVATE_DATA, *PNT_PRIVATE_DATA;
|
} NT_PRIVATE_DATA, *PNT_PRIVATE_DATA;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -286,13 +289,17 @@ static __inline NTSTATUS _CloseDisk(IN HANDLE Handle)
|
||||||
return (pfNtClose == NULL) ? STATUS_DLL_NOT_FOUND : pfNtClose(Handle);
|
return (pfNtClose == NULL) ? STATUS_DLL_NOT_FOUND : pfNtClose(Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PCSTR _NormalizeDeviceName(IN PCSTR Device, IN PSTR NormalizedDeviceNameBuffer)
|
static PCSTR _NormalizeDeviceName(IN PCSTR Device, IN PSTR NormalizedDeviceNameBuffer, OUT __u64 *Offset, OUT __u64 *Size)
|
||||||
{
|
{
|
||||||
|
*Offset = *Size = 0ULL;
|
||||||
// Convert non NT paths to NT
|
// Convert non NT paths to NT
|
||||||
if (Device[0] == '\\') {
|
if (Device[0] == '\\') {
|
||||||
if ((strlen(Device) < 4) || (Device[3] != '\\'))
|
if ((strlen(Device) < 4) || (Device[3] != '\\'))
|
||||||
return Device;
|
return Device;
|
||||||
strcpy(NormalizedDeviceNameBuffer, Device);
|
// Handle custom paths of the form "<Physical> <Offset> <Size>" used by Rufus to
|
||||||
|
// enable multi-partition access on removable devices, for pre 1703 platforms.
|
||||||
|
if (sscanf(Device, "%s %I64u %I64u", NormalizedDeviceNameBuffer, Offset, Size) < 1)
|
||||||
|
return NULL;
|
||||||
if ((NormalizedDeviceNameBuffer[1] == '\\') || (NormalizedDeviceNameBuffer[1] == '.'))
|
if ((NormalizedDeviceNameBuffer[1] == '\\') || (NormalizedDeviceNameBuffer[1] == '.'))
|
||||||
NormalizedDeviceNameBuffer[1] = '?';
|
NormalizedDeviceNameBuffer[1] = '?';
|
||||||
if (NormalizedDeviceNameBuffer[2] == '.')
|
if (NormalizedDeviceNameBuffer[2] == '.')
|
||||||
|
@ -341,7 +348,8 @@ static VOID _GetDeviceSize(IN HANDLE h, OUT unsigned __int64 *FsSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOLEAN _Ext2OpenDevice(IN PCSTR Name, IN BOOLEAN ReadOnly, OUT PHANDLE Handle, OUT PBOOLEAN OpenedReadonly OPTIONAL, OUT errcode_t *Errno OPTIONAL)
|
static BOOLEAN _Ext2OpenDevice(IN PCSTR Name, IN BOOLEAN ReadOnly, OUT PHANDLE Handle,
|
||||||
|
OUT __u64 *Offset, OUT __u64 *Size, OUT PBOOLEAN OpenedReadonly OPTIONAL, OUT errcode_t *Errno OPTIONAL)
|
||||||
{
|
{
|
||||||
CHAR NormalizedDeviceName[512];
|
CHAR NormalizedDeviceName[512];
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
@ -358,7 +366,7 @@ static BOOLEAN _Ext2OpenDevice(IN PCSTR Name, IN BOOLEAN ReadOnly, OUT PHANDLE H
|
||||||
(':' == *(Name + 1)) && ('\0' == *(Name + 2))) {
|
(':' == *(Name + 1)) && ('\0' == *(Name + 2))) {
|
||||||
Status = _OpenDriveLetter(*Name, ReadOnly, Handle, OpenedReadonly);
|
Status = _OpenDriveLetter(*Name, ReadOnly, Handle, OpenedReadonly);
|
||||||
} else {
|
} else {
|
||||||
Name = _NormalizeDeviceName(Name, NormalizedDeviceName);
|
Name = _NormalizeDeviceName(Name, NormalizedDeviceName, Offset, Size);
|
||||||
if (Name == NULL) {
|
if (Name == NULL) {
|
||||||
LastWinError = ERROR_INVALID_PARAMETER;
|
LastWinError = ERROR_INVALID_PARAMETER;
|
||||||
if (ARGUMENT_PRESENT(Errno))
|
if (ARGUMENT_PRESENT(Errno))
|
||||||
|
@ -438,12 +446,13 @@ static BOOLEAN _SetPartType(IN HANDLE Handle, IN UCHAR Type)
|
||||||
errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags)
|
errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags)
|
||||||
{
|
{
|
||||||
errcode_t errcode = 0;
|
errcode_t errcode = 0;
|
||||||
|
__u64 Offset, Size;
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
BOOLEAN Readonly;
|
BOOLEAN Readonly;
|
||||||
|
|
||||||
*mount_flags = 0;
|
*mount_flags = 0;
|
||||||
|
|
||||||
if (!_Ext2OpenDevice(file, TRUE, &h, &Readonly, &errcode))
|
if (!_Ext2OpenDevice(file, TRUE, &h, &Offset, &Size, &Readonly, &errcode))
|
||||||
return errcode;
|
return errcode;
|
||||||
|
|
||||||
*mount_flags &= _IsMounted(h) ? EXT2_MF_MOUNTED : 0;
|
*mount_flags &= _IsMounted(h) ? EXT2_MF_MOUNTED : 0;
|
||||||
|
@ -463,18 +472,19 @@ errcode_t ext2fs_check_mount_point(const char *file, int *mount_flags, char *mtp
|
||||||
// different removable devices (e.g. UFD) may be remounted under the same path.
|
// different removable devices (e.g. UFD) may be remounted under the same path.
|
||||||
errcode_t ext2fs_get_device_size2(const char *file, int blocksize, blk64_t *retblocks)
|
errcode_t ext2fs_get_device_size2(const char *file, int blocksize, blk64_t *retblocks)
|
||||||
{
|
{
|
||||||
errcode_t errcode;
|
errcode_t errcode = 0;
|
||||||
__int64 fs_size = 0;
|
__u64 Offset, Size = 0;
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
BOOLEAN Readonly;
|
BOOLEAN Readonly;
|
||||||
|
|
||||||
if (!_Ext2OpenDevice(file, TRUE, &h, &Readonly, &errcode))
|
if (!_Ext2OpenDevice(file, TRUE, &h, &Offset, &Size, &Readonly, &errcode))
|
||||||
return errcode;
|
return errcode;
|
||||||
|
|
||||||
_GetDeviceSize(h, &fs_size);
|
if (Size == 0LL)
|
||||||
|
_GetDeviceSize(h, &Size);
|
||||||
_CloseDisk(h);
|
_CloseDisk(h);
|
||||||
|
|
||||||
*retblocks = (blk64_t)(fs_size / blocksize);
|
*retblocks = (blk64_t)(Size / blocksize);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,7 +539,8 @@ static errcode_t nt_open(const char *name, int flags, io_channel *channel)
|
||||||
io->private_data = nt_data;
|
io->private_data = nt_data;
|
||||||
|
|
||||||
// Open the device
|
// Open the device
|
||||||
if (!_Ext2OpenDevice(name, (BOOLEAN)!BooleanFlagOn(flags, EXT2_FLAG_RW), &nt_data->handle, &nt_data->read_only, &errcode)) {
|
if (!_Ext2OpenDevice(name, (BOOLEAN)!BooleanFlagOn(flags, EXT2_FLAG_RW), &nt_data->handle,
|
||||||
|
&nt_data->offset, &nt_data->size, &nt_data->read_only, &errcode)) {
|
||||||
if (!errcode)
|
if (!errcode)
|
||||||
errcode = EIO;
|
errcode = EIO;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -631,7 +642,7 @@ static errcode_t nt_read_blk(io_channel channel, unsigned long block, int count,
|
||||||
|
|
||||||
size = (count < 0) ? (ULONG)(-count) : (ULONG)(count * channel->block_size);
|
size = (count < 0) ? (ULONG)(-count) : (ULONG)(count * channel->block_size);
|
||||||
|
|
||||||
offset.QuadPart = block * channel->block_size;
|
offset.QuadPart = block * channel->block_size + nt_data->offset;
|
||||||
|
|
||||||
// If not fit to the block
|
// If not fit to the block
|
||||||
if (size <= nt_data->buffer_size) {
|
if (size <= nt_data->buffer_size) {
|
||||||
|
@ -686,7 +697,7 @@ static errcode_t nt_write_blk(io_channel channel, unsigned long block, int count
|
||||||
|
|
||||||
|
|
||||||
assert((write_size % 512) == 0);
|
assert((write_size % 512) == 0);
|
||||||
offset.QuadPart = block * channel->block_size;
|
offset.QuadPart = block * channel->block_size + nt_data->offset;
|
||||||
|
|
||||||
if (!_RawWrite(nt_data->handle, offset, write_size, buf, &errcode)) {
|
if (!_RawWrite(nt_data->handle, offset, write_size, buf, &errcode)) {
|
||||||
if (channel->write_error)
|
if (channel->write_error)
|
||||||
|
|
|
@ -158,7 +158,8 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
strcpy(fs->device_name, name);
|
strcpy(fs->device_name, name);
|
||||||
cp = strchr(fs->device_name, '?');
|
cp = strchr(fs->device_name, '?');
|
||||||
if (!io_options && cp) {
|
// Don't process "?\" as an option since some Windows device paths use "\\?\..."
|
||||||
|
if (!io_options && cp && cp[1] != '\\') {
|
||||||
*cp++ = 0;
|
*cp++ = 0;
|
||||||
io_options = cp;
|
io_options = cp;
|
||||||
}
|
}
|
||||||
|
|
28
src/format.c
28
src/format.c
|
@ -825,18 +825,18 @@ const char* GetExtFsLabel(DWORD DriveIndex, uint64_t PartitionOffset)
|
||||||
errcode_t r;
|
errcode_t r;
|
||||||
ext2_filsys ext2fs = NULL;
|
ext2_filsys ext2fs = NULL;
|
||||||
io_manager manager = nt_io_manager();
|
io_manager manager = nt_io_manager();
|
||||||
char* volume_name = AltMountVolume(DriveIndex, PartitionOffset, TRUE);
|
char* volume_name = AltGetLogicalName(DriveIndex, PartitionOffset, FALSE, TRUE);
|
||||||
|
|
||||||
if (volume_name == NULL)
|
if (volume_name == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
r = ext2fs_open(volume_name, EXT2_FLAG_SKIP_MMP, 0, 0, manager, &ext2fs);
|
r = ext2fs_open(volume_name, EXT2_FLAG_SKIP_MMP, 0, 0, manager, &ext2fs);
|
||||||
|
free(volume_name);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
strncpy(label, ext2fs->super->s_volume_name, EXT2_LABEL_LEN);
|
strncpy(label, ext2fs->super->s_volume_name, EXT2_LABEL_LEN);
|
||||||
label[EXT2_LABEL_LEN] = 0;
|
label[EXT2_LABEL_LEN] = 0;
|
||||||
}
|
}
|
||||||
if (ext2fs != NULL)
|
if (ext2fs != NULL)
|
||||||
ext2fs_close(ext2fs);
|
ext2fs_close(ext2fs);
|
||||||
AltUnmountVolume(volume_name, TRUE);
|
|
||||||
return (r == 0) ? label : NULL;
|
return (r == 0) ? label : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -879,18 +879,20 @@ BOOL FormatExtFs(DWORD DriveIndex, uint64_t PartitionOffset, DWORD BlockSize, LP
|
||||||
}
|
}
|
||||||
CloseHandle(h);
|
CloseHandle(h);
|
||||||
#else
|
#else
|
||||||
volume_name = AltMountVolume(DriveIndex, PartitionOffset, FALSE);
|
volume_name = AltGetLogicalName(DriveIndex, PartitionOffset, FALSE, TRUE);
|
||||||
#endif
|
#endif
|
||||||
if ((volume_name == NULL) | (strlen(FSName) != 4) || (strncmp(FSName, "ext", 3) != 0)) {
|
if ((volume_name == NULL) | (strlen(FSName) != 4) || (strncmp(FSName, "ext", 3) != 0)) {
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_INVALID_PARAMETER;
|
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_INVALID_PARAMETER;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
if (strchr(volume_name, ' ') != NULL)
|
||||||
|
uprintf("Notice: Using physical device to access partition data");
|
||||||
|
|
||||||
if ((strcmp(FSName, FileSystemLabel[FS_EXT2]) != 0) && (strcmp(FSName, FileSystemLabel[FS_EXT3]) != 0)) {
|
if ((strcmp(FSName, FileSystemLabel[FS_EXT2]) != 0) && (strcmp(FSName, FileSystemLabel[FS_EXT3]) != 0)) {
|
||||||
if (strcmp(FSName, FileSystemLabel[FS_EXT4]) == 0)
|
if (strcmp(FSName, FileSystemLabel[FS_EXT4]) == 0)
|
||||||
uprintf("ext4 file system is not supported, will use ext3 instead");
|
uprintf("ext4 file system is not supported, defaulting to ext3");
|
||||||
else
|
else
|
||||||
uprintf("invalid ext file system version requested, will use ext3");
|
uprintf("Invalid ext file system version requested, defaulting to ext3");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((strcmp(FSName, FileSystemLabel[FS_EXT2]) != 0) && (strcmp(FSName, FileSystemLabel[FS_EXT3]) != 0))
|
if ((strcmp(FSName, FileSystemLabel[FS_EXT2]) != 0) && (strcmp(FSName, FileSystemLabel[FS_EXT3]) != 0))
|
||||||
|
@ -1097,9 +1099,9 @@ BOOL FormatExtFs(DWORD DriveIndex, uint64_t PartitionOffset, DWORD BlockSize, LP
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
free(volume_name);
|
||||||
ext2fs_free(ext2fs);
|
ext2fs_free(ext2fs);
|
||||||
free(buf);
|
free(buf);
|
||||||
AltUnmountVolume(volume_name, FALSE);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2411,7 +2413,7 @@ out:
|
||||||
DWORD WINAPI FormatThread(void* param)
|
DWORD WINAPI FormatThread(void* param)
|
||||||
{
|
{
|
||||||
int i, r;
|
int i, r;
|
||||||
BOOL ret, use_large_fat32, windows_to_go;
|
BOOL ret, use_large_fat32, windows_to_go, actual_lock_drive = lock_drive;
|
||||||
DWORD DriveIndex = (DWORD)(uintptr_t)param, ClusterSize, Flags;
|
DWORD DriveIndex = (DWORD)(uintptr_t)param, ClusterSize, Flags;
|
||||||
HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE;
|
HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE;
|
||||||
HANDLE hLogicalVolume = INVALID_HANDLE_VALUE;
|
HANDLE hLogicalVolume = INVALID_HANDLE_VALUE;
|
||||||
|
@ -2445,9 +2447,13 @@ DWORD WINAPI FormatThread(void* param)
|
||||||
extra_partitions = XP_CASPER;
|
extra_partitions = XP_CASPER;
|
||||||
else if (IsChecked(IDC_OLD_BIOS_FIXES))
|
else if (IsChecked(IDC_OLD_BIOS_FIXES))
|
||||||
extra_partitions = XP_COMPAT;
|
extra_partitions = XP_COMPAT;
|
||||||
|
// On pre 1703 platforms (and even on later ones), anything with ext2/ext3 doesn't sit
|
||||||
|
// too well with Windows. Relaxing our locking rules seems to help...
|
||||||
|
if ((extra_partitions == XP_CASPER) || (fs_type >= FS_EXT2))
|
||||||
|
actual_lock_drive = FALSE;
|
||||||
|
|
||||||
PrintInfoDebug(0, MSG_225);
|
PrintInfoDebug(0, MSG_225);
|
||||||
hPhysicalDrive = GetPhysicalHandle(DriveIndex, lock_drive, FALSE, !lock_drive);
|
hPhysicalDrive = GetPhysicalHandle(DriveIndex, actual_lock_drive, FALSE, !actual_lock_drive);
|
||||||
if (hPhysicalDrive == INVALID_HANDLE_VALUE) {
|
if (hPhysicalDrive == INVALID_HANDLE_VALUE) {
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -2499,7 +2505,7 @@ DWORD WINAPI FormatThread(void* param)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now get RW access to the physical drive...
|
// Now get RW access to the physical drive...
|
||||||
hPhysicalDrive = GetPhysicalHandle(DriveIndex, lock_drive, TRUE, !lock_drive);
|
hPhysicalDrive = GetPhysicalHandle(DriveIndex, actual_lock_drive, TRUE, !actual_lock_drive);
|
||||||
if (hPhysicalDrive == INVALID_HANDLE_VALUE) {
|
if (hPhysicalDrive == INVALID_HANDLE_VALUE) {
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_OPEN_FAILED;
|
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_OPEN_FAILED;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -2507,7 +2513,7 @@ DWORD WINAPI FormatThread(void* param)
|
||||||
RefreshDriveLayout(hPhysicalDrive);
|
RefreshDriveLayout(hPhysicalDrive);
|
||||||
|
|
||||||
// ...and get a lock to the logical drive so that we can actually write something
|
// ...and get a lock to the logical drive so that we can actually write something
|
||||||
hLogicalVolume = GetLogicalHandle(DriveIndex, 0, TRUE, FALSE, !lock_drive);
|
hLogicalVolume = GetLogicalHandle(DriveIndex, 0, TRUE, FALSE, !actual_lock_drive);
|
||||||
if (hLogicalVolume == INVALID_HANDLE_VALUE) {
|
if (hLogicalVolume == INVALID_HANDLE_VALUE) {
|
||||||
uprintf("Could not lock volume");
|
uprintf("Could not lock volume");
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
|
||||||
|
@ -2724,7 +2730,7 @@ DWORD WINAPI FormatThread(void* param)
|
||||||
|
|
||||||
if (use_vds) {
|
if (use_vds) {
|
||||||
// Get RW access back to the physical drive...
|
// Get RW access back to the physical drive...
|
||||||
hPhysicalDrive = GetPhysicalHandle(DriveIndex, lock_drive, TRUE, !lock_drive);
|
hPhysicalDrive = GetPhysicalHandle(DriveIndex, actual_lock_drive, TRUE, !actual_lock_drive);
|
||||||
if (hPhysicalDrive == INVALID_HANDLE_VALUE) {
|
if (hPhysicalDrive == INVALID_HANDLE_VALUE) {
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_OPEN_FAILED;
|
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_OPEN_FAILED;
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
@ -1227,7 +1227,7 @@ static DWORD WINAPI BootCheckThread(LPVOID param)
|
||||||
}
|
}
|
||||||
if (SelectedDrive.MediaType != FixedMedia) {
|
if (SelectedDrive.MediaType != FixedMedia) {
|
||||||
if ((target_type == TT_UEFI) && (partition_type == PARTITION_STYLE_GPT) && (nWindowsBuildNumber < 15000)) {
|
if ((target_type == TT_UEFI) && (partition_type == PARTITION_STYLE_GPT) && (nWindowsBuildNumber < 15000)) {
|
||||||
// Up to Windows 10 Creators Update, we were screwed, since we need access to 2 partitions at the same time.
|
// Up to Windows 10 Creators Update (1703), we were screwed, since we need access to 2 partitions at the same time.
|
||||||
// Thankfully, the newer Windows allow mounting multiple partitions on the same REMOVABLE drive.
|
// Thankfully, the newer Windows allow mounting multiple partitions on the same REMOVABLE drive.
|
||||||
MessageBoxExU(hMainDialog, lmprintf(MSG_198), lmprintf(MSG_190), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid);
|
MessageBoxExU(hMainDialog, lmprintf(MSG_198), lmprintf(MSG_190), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid);
|
||||||
goto out;
|
goto out;
|
||||||
|
|
10
src/rufus.rc
10
src/rufus.rc
|
@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||||
IDD_DIALOG DIALOGEX 12, 12, 232, 326
|
IDD_DIALOG DIALOGEX 12, 12, 232, 326
|
||||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
EXSTYLE WS_EX_ACCEPTFILES
|
EXSTYLE WS_EX_ACCEPTFILES
|
||||||
CAPTION "Rufus 3.8.1578"
|
CAPTION "Rufus 3.8.1579"
|
||||||
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
||||||
BEGIN
|
BEGIN
|
||||||
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
||||||
|
@ -394,8 +394,8 @@ END
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 3,8,1578,0
|
FILEVERSION 3,8,1579,0
|
||||||
PRODUCTVERSION 3,8,1578,0
|
PRODUCTVERSION 3,8,1579,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -413,13 +413,13 @@ BEGIN
|
||||||
VALUE "Comments", "https://rufus.ie"
|
VALUE "Comments", "https://rufus.ie"
|
||||||
VALUE "CompanyName", "Akeo Consulting"
|
VALUE "CompanyName", "Akeo Consulting"
|
||||||
VALUE "FileDescription", "Rufus"
|
VALUE "FileDescription", "Rufus"
|
||||||
VALUE "FileVersion", "3.8.1578"
|
VALUE "FileVersion", "3.8.1579"
|
||||||
VALUE "InternalName", "Rufus"
|
VALUE "InternalName", "Rufus"
|
||||||
VALUE "LegalCopyright", "© 2011-2019 Pete Batard (GPL v3)"
|
VALUE "LegalCopyright", "© 2011-2019 Pete Batard (GPL v3)"
|
||||||
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
|
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
|
||||||
VALUE "OriginalFilename", "rufus-3.8.exe"
|
VALUE "OriginalFilename", "rufus-3.8.exe"
|
||||||
VALUE "ProductName", "Rufus"
|
VALUE "ProductName", "Rufus"
|
||||||
VALUE "ProductVersion", "3.8.1578"
|
VALUE "ProductVersion", "3.8.1579"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
Loading…
Reference in a new issue