From bf8d888b212cde450afcabeba9b0c2845d523223 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Sat, 14 Sep 2019 23:33:46 +0100 Subject: [PATCH] [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 --- src/drive.c | 87 ++++++++++++++++++++------------------------- src/drive.h | 3 +- src/ext2fs/nt_io.c | 39 ++++++++++++-------- src/ext2fs/openfs.c | 3 +- src/format.c | 28 +++++++++------ src/rufus.c | 2 +- src/rufus.rc | 10 +++--- 7 files changed, 89 insertions(+), 83 deletions(-) diff --git a/src/drive.c b/src/drive.c index 99edafb8..0126066e 100644 --- a/src/drive.c +++ b/src/drive.c @@ -242,23 +242,6 @@ out: 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 */ @@ -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 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]); - else + } 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); + if ((ret != NULL) && (strchr(ret, ' ') != NULL)) + uprintf("Warning: Using physical device to access partition data"); + } out: if (hVolume != INVALID_HANDLE_VALUE) @@ -409,26 +395,38 @@ out: */ char* AltGetLogicalName(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bKeepTrailingBackslash, BOOL bSilent) { + BOOL matching_drive = (DriveIndex == SelectedDrive.DeviceNumber); DWORD i; - char *ret = NULL, volume_name[MAX_PATH], path[MAX_PATH]; + char *ret = NULL, volume_name[MAX_PATH], path[64]; 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); + if (PartitionOffset == 0) { + i = 0; + } else if (matching_drive) { + for (i = 0; (i < MAX_PARTITIONS) && (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; + } + } else { + suprintf("Error: Searching for a partition on a non matching disk"); 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); + suprintf("Could not find a DOS volume name for '%s': %s", path, WindowsErrorString()); + // If we are on the right drive, we enable a custom access mode through physical + offset + 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, "\\"); } + ret = safe_strdup(volume_name); out: return ret; @@ -772,24 +770,6 @@ HANDLE GetLogicalHandle(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bLockDr 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 * 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, &MaximumComponentLength, &FileSystemFlags, FileSystemName, 64)) { 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 return TRUE; @@ -1167,6 +1147,7 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys SelectedDrive.nPartitions = 0; memset(SelectedDrive.PartitionOffset, 0, sizeof(SelectedDrive.PartitionOffset)); + memset(SelectedDrive.PartitionSize, 0, sizeof(SelectedDrive.PartitionSize)); // Populate the filesystem data FileSystemName[0] = 0; volume_name = GetLogicalName(DriveIndex, 0, TRUE, FALSE); @@ -1255,8 +1236,10 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys break; } } - if (i < MAX_PARTITIONS) + if (i < MAX_PARTITIONS) { 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 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, @@ -1282,8 +1265,10 @@ 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) + if (i < MAX_PARTITIONS) { SelectedDrive.PartitionOffset[i] = DriveLayout->PartitionEntry[i].StartingOffset.QuadPart; + SelectedDrive.PartitionSize[i] = DriveLayout->PartitionEntry[i].PartitionLength.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)" : "", @@ -1551,6 +1536,7 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m } memset(partition_offset, 0, sizeof(partition_offset)); memset(SelectedDrive.PartitionOffset, 0, sizeof(SelectedDrive.PartitionOffset)); + memset(SelectedDrive.PartitionSize, 0, sizeof(SelectedDrive.PartitionSize)); // Compute the start offset of our first partition 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)) uprintf("Could not zero %S: %s", extra_part_name, WindowsErrorString()); SelectedDrive.PartitionOffset[pn] = DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart; + SelectedDrive.PartitionSize[pn] = DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart; pn++; DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = DriveLayoutEx.PartitionEntry[pn-1].StartingOffset.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)); } SelectedDrive.PartitionOffset[pn] = DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart; + SelectedDrive.PartitionSize[pn] = DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart; partition_offset[PI_MAIN] = SelectedDrive.PartitionOffset[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, SizeToHumanReadable(DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart, TRUE, FALSE)); SelectedDrive.PartitionOffset[pn] = DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart; + SelectedDrive.PartitionSize[pn] = DriveLayoutEx.PartitionEntry[pn].PartitionLength.QuadPart; if (extra_partitions & XP_CASPER) partition_offset[PI_CASPER] = SelectedDrive.PartitionOffset[pn]; else if (extra_partitions & XP_ESP) diff --git a/src/drive.h b/src/drive.h index d2432744..68162e2a 100644 --- a/src/drive.h +++ b/src/drive.h @@ -351,6 +351,7 @@ typedef struct { int PartitionStyle; int nPartitions; // number of partitions we actually care about uint64_t PartitionOffset[MAX_PARTITIONS]; + uint64_t PartitionSize[MAX_PARTITIONS]; int FSType; char proposed_label[16]; BOOL has_protective_mbr; @@ -366,14 +367,12 @@ extern uint64_t partition_offset[3]; BOOL SetAutoMount(BOOL enable); BOOL GetAutoMount(BOOL* enabled); char* GetPhysicalName(DWORD DriveIndex); -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, 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); diff --git a/src/ext2fs/nt_io.c b/src/ext2fs/nt_io.c index 7c34be17..9c78c0d7 100644 --- a/src/ext2fs/nt_io.c +++ b/src/ext2fs/nt_io.c @@ -63,6 +63,9 @@ typedef struct _NT_PRIVATE_DATA { ULONG buffer_size; BOOLEAN read_only; BOOLEAN written; + // Used by Rufus + __u64 offset; + __u64 size; } NT_PRIVATE_DATA, *PNT_PRIVATE_DATA; // @@ -199,7 +202,7 @@ static NTSTATUS _OpenNtName(IN PCSTR Name, IN BOOLEAN Readonly, OUT PHANDLE Hand UnicodeString.MaximumLength = sizeof(Buffer); // in bytes!!! // Initialize object - InitializeObjectAttributes(&ObjectAttributes, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL ); + InitializeObjectAttributes(&ObjectAttributes, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL); // Try to open it in initial mode if (ARGUMENT_PRESENT(OpenedReadonly)) @@ -286,13 +289,17 @@ static __inline NTSTATUS _CloseDisk(IN HANDLE 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 if (Device[0] == '\\') { if ((strlen(Device) < 4) || (Device[3] != '\\')) return Device; - strcpy(NormalizedDeviceNameBuffer, Device); + // Handle custom paths of the form " " 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] == '.')) NormalizedDeviceNameBuffer[1] = '?'; 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]; NTSTATUS Status; @@ -358,7 +366,7 @@ static BOOLEAN _Ext2OpenDevice(IN PCSTR Name, IN BOOLEAN ReadOnly, OUT PHANDLE H (':' == *(Name + 1)) && ('\0' == *(Name + 2))) { Status = _OpenDriveLetter(*Name, ReadOnly, Handle, OpenedReadonly); } else { - Name = _NormalizeDeviceName(Name, NormalizedDeviceName); + Name = _NormalizeDeviceName(Name, NormalizedDeviceName, Offset, Size); if (Name == NULL) { LastWinError = ERROR_INVALID_PARAMETER; 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 errcode = 0; + __u64 Offset, Size; HANDLE h; BOOLEAN Readonly; *mount_flags = 0; - if (!_Ext2OpenDevice(file, TRUE, &h, &Readonly, &errcode)) + if (!_Ext2OpenDevice(file, TRUE, &h, &Offset, &Size, &Readonly, &errcode)) return errcode; *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. errcode_t ext2fs_get_device_size2(const char *file, int blocksize, blk64_t *retblocks) { - errcode_t errcode; - __int64 fs_size = 0; + errcode_t errcode = 0; + __u64 Offset, Size = 0; HANDLE h; BOOLEAN Readonly; - if (!_Ext2OpenDevice(file, TRUE, &h, &Readonly, &errcode)) + if (!_Ext2OpenDevice(file, TRUE, &h, &Offset, &Size, &Readonly, &errcode)) return errcode; - _GetDeviceSize(h, &fs_size); + if (Size == 0LL) + _GetDeviceSize(h, &Size); _CloseDisk(h); - *retblocks = (blk64_t)(fs_size / blocksize); + *retblocks = (blk64_t)(Size / blocksize); return 0; } @@ -529,7 +539,8 @@ static errcode_t nt_open(const char *name, int flags, io_channel *channel) io->private_data = nt_data; // 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) errcode = EIO; 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); - offset.QuadPart = block * channel->block_size; + offset.QuadPart = block * channel->block_size + nt_data->offset; // If not fit to the block 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); - 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 (channel->write_error) diff --git a/src/ext2fs/openfs.c b/src/ext2fs/openfs.c index 85d73e2a..009df244 100644 --- a/src/ext2fs/openfs.c +++ b/src/ext2fs/openfs.c @@ -158,7 +158,8 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, goto cleanup; strcpy(fs->device_name, 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; io_options = cp; } diff --git a/src/format.c b/src/format.c index a696435b..149293b6 100644 --- a/src/format.c +++ b/src/format.c @@ -825,18 +825,18 @@ const char* GetExtFsLabel(DWORD DriveIndex, uint64_t PartitionOffset) errcode_t r; ext2_filsys ext2fs = NULL; 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) return NULL; r = ext2fs_open(volume_name, EXT2_FLAG_SKIP_MMP, 0, 0, manager, &ext2fs); + free(volume_name); if (r == 0) { strncpy(label, ext2fs->super->s_volume_name, EXT2_LABEL_LEN); label[EXT2_LABEL_LEN] = 0; } if (ext2fs != NULL) ext2fs_close(ext2fs); - AltUnmountVolume(volume_name, TRUE); return (r == 0) ? label : NULL; } @@ -879,18 +879,20 @@ BOOL FormatExtFs(DWORD DriveIndex, uint64_t PartitionOffset, DWORD BlockSize, LP } CloseHandle(h); #else - volume_name = AltMountVolume(DriveIndex, PartitionOffset, FALSE); + volume_name = AltGetLogicalName(DriveIndex, PartitionOffset, FALSE, TRUE); #endif if ((volume_name == NULL) | (strlen(FSName) != 4) || (strncmp(FSName, "ext", 3) != 0)) { FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_INVALID_PARAMETER; 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_EXT4]) == 0) - uprintf("ext4 file system is not supported, will use ext3 instead"); + uprintf("ext4 file system is not supported, defaulting to ext3"); 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)) @@ -1097,9 +1099,9 @@ BOOL FormatExtFs(DWORD DriveIndex, uint64_t PartitionOffset, DWORD BlockSize, LP ret = TRUE; out: + free(volume_name); ext2fs_free(ext2fs); free(buf); - AltUnmountVolume(volume_name, FALSE); return ret; } @@ -2411,7 +2413,7 @@ out: DWORD WINAPI FormatThread(void* param) { 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; HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE; HANDLE hLogicalVolume = INVALID_HANDLE_VALUE; @@ -2445,9 +2447,13 @@ DWORD WINAPI FormatThread(void* param) extra_partitions = XP_CASPER; else if (IsChecked(IDC_OLD_BIOS_FIXES)) 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); - hPhysicalDrive = GetPhysicalHandle(DriveIndex, lock_drive, FALSE, !lock_drive); + hPhysicalDrive = GetPhysicalHandle(DriveIndex, actual_lock_drive, FALSE, !actual_lock_drive); if (hPhysicalDrive == INVALID_HANDLE_VALUE) { FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; goto out; @@ -2499,7 +2505,7 @@ DWORD WINAPI FormatThread(void* param) } // 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) { FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_OPEN_FAILED; goto out; @@ -2507,7 +2513,7 @@ DWORD WINAPI FormatThread(void* param) RefreshDriveLayout(hPhysicalDrive); // ...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) { uprintf("Could not lock volume"); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; @@ -2724,7 +2730,7 @@ DWORD WINAPI FormatThread(void* param) if (use_vds) { // 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) { FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_OPEN_FAILED; goto out; diff --git a/src/rufus.c b/src/rufus.c index d8c7aa27..51af1e69 100755 --- a/src/rufus.c +++ b/src/rufus.c @@ -1227,7 +1227,7 @@ static DWORD WINAPI BootCheckThread(LPVOID param) } if (SelectedDrive.MediaType != FixedMedia) { 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. MessageBoxExU(hMainDialog, lmprintf(MSG_198), lmprintf(MSG_190), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid); goto out; diff --git a/src/rufus.rc b/src/rufus.rc index 83ef0526..8ab83262 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.8.1578" +CAPTION "Rufus 3.8.1579" 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,8,1578,0 - PRODUCTVERSION 3,8,1578,0 + FILEVERSION 3,8,1579,0 + PRODUCTVERSION 3,8,1579,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -413,13 +413,13 @@ BEGIN VALUE "Comments", "https://rufus.ie" VALUE "CompanyName", "Akeo Consulting" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "3.8.1578" + VALUE "FileVersion", "3.8.1579" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", " 2011-2019 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" VALUE "OriginalFilename", "rufus-3.8.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "3.8.1578" + VALUE "ProductVersion", "3.8.1579" END END BLOCK "VarFileInfo"