mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[core] work around Windows' moronic behaviour for mounted VHDs
* If you attempt to read past the end of a mounted VHD, not only will Windows happily return data that doesn't exist (instead of returning End of Disk), but it will also corrupt the existing data! * So, to appease the capricious Windows gods, we now make sure that we never attempt to read (or write) past the boundaries of the source or target when writing images. * This should address the last issue from #2468. * Also set version to rufus-next and make some small improvement in winio.h.
This commit is contained in:
parent
ae3c65e7f8
commit
bdff2dc45c
5 changed files with 39 additions and 33 deletions
20
configure
vendored
20
configure
vendored
|
@ -1,6 +1,6 @@
|
|||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.71 for rufus 4.5.
|
||||
# Generated by GNU Autoconf 2.71 for rufus 4.6.
|
||||
#
|
||||
# Report bugs to <https://github.com/pbatard/rufus/issues>.
|
||||
#
|
||||
|
@ -611,8 +611,8 @@ MAKEFLAGS=
|
|||
# Identity of this package.
|
||||
PACKAGE_NAME='rufus'
|
||||
PACKAGE_TARNAME='rufus'
|
||||
PACKAGE_VERSION='4.5'
|
||||
PACKAGE_STRING='rufus 4.5'
|
||||
PACKAGE_VERSION='4.6'
|
||||
PACKAGE_STRING='rufus 4.6'
|
||||
PACKAGE_BUGREPORT='https://github.com/pbatard/rufus/issues'
|
||||
PACKAGE_URL='https://rufus.ie'
|
||||
|
||||
|
@ -1269,7 +1269,7 @@ if test "$ac_init_help" = "long"; then
|
|||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures rufus 4.5 to adapt to many kinds of systems.
|
||||
\`configure' configures rufus 4.6 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
|
@ -1336,7 +1336,7 @@ fi
|
|||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of rufus 4.5:";;
|
||||
short | recursive ) echo "Configuration of rufus 4.6:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
|
@ -1428,7 +1428,7 @@ fi
|
|||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
rufus configure 4.5
|
||||
rufus configure 4.6
|
||||
generated by GNU Autoconf 2.71
|
||||
|
||||
Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
|
@ -1504,7 +1504,7 @@ cat >config.log <<_ACEOF
|
|||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by rufus $as_me 4.5, which was
|
||||
It was created by rufus $as_me 4.6, which was
|
||||
generated by GNU Autoconf 2.71. Invocation command line was
|
||||
|
||||
$ $0$ac_configure_args_raw
|
||||
|
@ -2767,7 +2767,7 @@ fi
|
|||
|
||||
# Define the identity of the package.
|
||||
PACKAGE='rufus'
|
||||
VERSION='4.5'
|
||||
VERSION='4.6'
|
||||
|
||||
|
||||
printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
|
||||
|
@ -5309,7 +5309,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
|||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by rufus $as_me 4.5, which was
|
||||
This file was extended by rufus $as_me 4.6, which was
|
||||
generated by GNU Autoconf 2.71. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
|
@ -5365,7 +5365,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
|
|||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config='$ac_cs_config_escaped'
|
||||
ac_cs_version="\\
|
||||
rufus config.status 4.5
|
||||
rufus config.status 4.6
|
||||
configured by $0, generated by GNU Autoconf 2.71,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
AC_INIT([rufus], [4.5], [https://github.com/pbatard/rufus/issues], [rufus], [https://rufus.ie])
|
||||
AC_INIT([rufus], [4.6], [https://github.com/pbatard/rufus/issues], [rufus], [https://rufus.ie])
|
||||
AM_INIT_AUTOMAKE([-Wno-portability foreign no-dist no-dependencies])
|
||||
AC_CONFIG_SRCDIR([src/rufus.c])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
|
28
src/format.c
28
src/format.c
|
@ -1150,8 +1150,8 @@ static BOOL WriteDrive(HANDLE hPhysicalDrive, BOOL bZeroDrive)
|
|||
BOOL s, ret = FALSE;
|
||||
LARGE_INTEGER li;
|
||||
HANDLE hSourceImage = INVALID_HANDLE_VALUE;
|
||||
DWORD i, read_size[NUM_BUFFERS], write_size, comp_size, buf_size;
|
||||
uint64_t wb, target_size = bZeroDrive ? SelectedDrive.DiskSize : img_report.image_size;
|
||||
DWORD i, read_size[NUM_BUFFERS] = { 0 }, write_size, comp_size, buf_size;
|
||||
uint64_t wb, target_size = bZeroDrive ? SelectedDrive.DiskSize : MIN((uint64_t)SelectedDrive.DiskSize, img_report.image_size);
|
||||
uint64_t cur_value, last_value = 0;
|
||||
int64_t bled_ret;
|
||||
uint8_t* buffer = NULL;
|
||||
|
@ -1341,7 +1341,7 @@ static BOOL WriteDrive(HANDLE hPhysicalDrive, BOOL bZeroDrive)
|
|||
assert((uintptr_t)buffer % SelectedDrive.SectorSize == 0);
|
||||
|
||||
// Start the initial read
|
||||
ReadFileAsync(hSourceImage, &buffer[read_bufnum * buf_size], buf_size);
|
||||
ReadFileAsync(hSourceImage, &buffer[read_bufnum * buf_size], (DWORD)MIN(buf_size, target_size));
|
||||
|
||||
read_size[proc_bufnum] = 1; // To avoid early loop exit
|
||||
for (wb = 0; read_size[proc_bufnum] != 0; wb += read_size[proc_bufnum]) {
|
||||
|
@ -1362,21 +1362,25 @@ static BOOL WriteDrive(HANDLE hPhysicalDrive, BOOL bZeroDrive)
|
|||
goto out;
|
||||
}
|
||||
|
||||
// 2. Update the read size
|
||||
// 2a) Don't overflow our projected size (mostly for VHDs)
|
||||
if (wb + read_size[read_bufnum] > target_size)
|
||||
read_size[read_bufnum] = (DWORD)(target_size - wb);
|
||||
// 2b) WriteFile fails unless the size is a multiple of sector size
|
||||
if (read_size[read_bufnum] % SelectedDrive.SectorSize != 0)
|
||||
read_size[read_bufnum] = ((read_size[read_bufnum] + SelectedDrive.SectorSize - 1) /
|
||||
SelectedDrive.SectorSize) * SelectedDrive.SectorSize;
|
||||
|
||||
// 2. WriteFile fails unless the size is a multiple of sector size
|
||||
if (read_size[read_bufnum] % SelectedDrive.SectorSize != 0) {
|
||||
assert(HI_ALIGN_X_TO_Y(read_size[read_bufnum], SelectedDrive.SectorSize) <= buf_size);
|
||||
read_size[read_bufnum] = HI_ALIGN_X_TO_Y(read_size[read_bufnum], SelectedDrive.SectorSize);
|
||||
}
|
||||
|
||||
// 3. Switch to the next reading buffer
|
||||
proc_bufnum = read_bufnum;
|
||||
read_bufnum = (read_bufnum + 1) % NUM_BUFFERS;
|
||||
|
||||
// 3. Launch the next asynchronous read operation
|
||||
ReadFileAsync(hSourceImage, &buffer[read_bufnum * buf_size], buf_size);
|
||||
// It is VERY IMPORTANT here that we don't attempt to read past the source
|
||||
// or target sizes, as mounted VHDs will SCREW YOU if you attempt to do so
|
||||
// and will even start returning ERRONEOUS DATA for sectors before the end
|
||||
// of the disk... So we make sure to adjust the size not to ever overflow.
|
||||
// Also we need to make sure we add read_size[proc_bufnum] to wb since we
|
||||
// have already read the data and are about to write it.
|
||||
ReadFileAsync(hSourceImage, &buffer[read_bufnum * buf_size], (DWORD)MIN(buf_size, target_size - (wb + read_size[proc_bufnum])));
|
||||
|
||||
// 4. Synchronously write the current data buffer
|
||||
for (i = 1; i <= WRITE_RETRIES; i++) {
|
||||
|
|
12
src/rufus.rc
12
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 4.5.2181"
|
||||
CAPTION "Rufus 4.6.2182"
|
||||
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
||||
|
@ -397,8 +397,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,5,2181,0
|
||||
PRODUCTVERSION 4,5,2181,0
|
||||
FILEVERSION 4,6,2182,0
|
||||
PRODUCTVERSION 4,6,2182,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -416,13 +416,13 @@ BEGIN
|
|||
VALUE "Comments", "https://rufus.ie"
|
||||
VALUE "CompanyName", "Akeo Consulting"
|
||||
VALUE "FileDescription", "Rufus"
|
||||
VALUE "FileVersion", "4.5.2181"
|
||||
VALUE "FileVersion", "4.6.2182"
|
||||
VALUE "InternalName", "Rufus"
|
||||
VALUE "LegalCopyright", "<22> 2011-2024 Pete Batard (GPL v3)"
|
||||
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
|
||||
VALUE "OriginalFilename", "rufus-4.5.exe"
|
||||
VALUE "OriginalFilename", "rufus-4.6.exe"
|
||||
VALUE "ProductName", "Rufus"
|
||||
VALUE "ProductVersion", "4.5.2181"
|
||||
VALUE "ProductVersion", "4.6.2182"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
10
src/winio.h
10
src/winio.h
|
@ -102,11 +102,13 @@ static __inline BOOL ReadFileAsync(HANDLE h, LPVOID lpBuffer, DWORD nNumberOfByt
|
|||
ASYNC_FD* fd = (ASYNC_FD*)h;
|
||||
fd->Overlapped.bOffsetUpdated = FALSE;
|
||||
if (!ReadFile(fd->hFile, lpBuffer, nNumberOfBytesToRead, NULL,
|
||||
(OVERLAPPED*)&fd->Overlapped))
|
||||
// TODO: Is it possible to get ERROR_HANDLE_EOF here?
|
||||
(OVERLAPPED*)&fd->Overlapped)) {
|
||||
// Is it possible to get ERROR_HANDLE_EOF here?
|
||||
assert(GetLastError() != ERROR_HANDLE_EOF);
|
||||
fd->iStatus = (GetLastError() == ERROR_IO_PENDING) ? -1 : 0;
|
||||
else
|
||||
} else {
|
||||
fd->iStatus = 1;
|
||||
}
|
||||
return (fd->iStatus != 0);
|
||||
}
|
||||
|
||||
|
@ -165,11 +167,11 @@ static __inline BOOL GetSizeAsync(HANDLE h, LPDWORD lpNumberOfBytes)
|
|||
SetLastError(ERROR_NO_MORE_ITEMS);
|
||||
return FALSE;
|
||||
}
|
||||
fd->Overlapped.bOffsetUpdated = TRUE;
|
||||
if (!GetOverlappedResultEx(fd->hFile, (OVERLAPPED*)&fd->Overlapped,
|
||||
lpNumberOfBytes, WRITE_TIMEOUT, (fd->iStatus < 0)))
|
||||
// When reading from VHD/VHDX we get SECTOR_NOT_FOUND rather than EOF for the end of the drive
|
||||
return (GetLastError() == ERROR_HANDLE_EOF || GetLastError() == ERROR_SECTOR_NOT_FOUND);
|
||||
fd->Overlapped.Offset += *lpNumberOfBytes;
|
||||
fd->Overlapped.bOffsetUpdated = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue