From 10dbfdd7e110c1b7f1a6d5e4eea35159293c5383 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Tue, 4 Jul 2023 13:26:04 +0100 Subject: [PATCH] [core] make sure the main partition size is aligned to the cluster size * Having NTFS partitions properly aligned to the cluster size can drastically improve the speed of capturing a disk to an FFU image, as, when the size is aligned, the FFU capture uses the actual NTFS allocation map to only read and capture the clusters that are actually in use, whereas, if no aligned, FFU capture falls back to a sector by sector copy that is both much slower and also includes unwanted leftover garbage. * Also only enable FFU when we detect FFUProvider.dll as a system library. --- src/drive.c | 21 ++++++++++++++++----- src/rufus.rc | 10 +++++----- src/vhd.c | 7 +++---- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/drive.c b/src/drive.c index f9f20bb0..d51fb4d3 100644 --- a/src/drive.c +++ b/src/drive.c @@ -2269,8 +2269,8 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m const DWORD size_to_clear = MAX_SECTORS_TO_CLEAR * SelectedDrive.SectorSize; uint8_t* buffer; size_t uefi_ntfs_size = 0; - CREATE_DISK CreateDisk = {PARTITION_STYLE_RAW, {{0}}}; - DRIVE_LAYOUT_INFORMATION_EX4 DriveLayoutEx = {0}; + CREATE_DISK CreateDisk = { PARTITION_STYLE_RAW, { { 0 } } }; + DRIVE_LAYOUT_INFORMATION_EX4 DriveLayoutEx = { 0 }; BOOL r; DWORD i, size, bufsize, pn = 0; LONGLONG main_part_size_in_sectors, extra_part_size_in_tracks = 0; @@ -2278,9 +2278,13 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m // https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/configure-uefigpt-based-hard-drive-partitions // and folks using MacOS: https://github.com/pbatard/rufus/issues/979 LONGLONG esp_size = 260 * MB; + LONGLONG ClusterSize = (LONGLONG)ComboBox_GetCurItemData(hClusterSize); PrintInfoDebug(0, MSG_238, PartitionTypeName[partition_style]); + if (ClusterSize == 0) + ClusterSize = 0x200; + if (partition_style == PARTITION_STYLE_SFD) // Nothing to do return TRUE; @@ -2307,9 +2311,6 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m // CHS sizes that IBM imparted upon us. Long story short, we now align to a // cylinder size that is itself aligned to the cluster size. // If this actually breaks old systems, please send your complaints to IBM. - LONGLONG ClusterSize = (LONGLONG)ComboBox_GetCurItemData(hClusterSize); - if (ClusterSize == 0) - ClusterSize = 0x200; DriveLayoutEx.PartitionEntry[pn].StartingOffset.QuadPart = ((bytes_per_track + (ClusterSize - 1)) / ClusterSize) * ClusterSize; // GRUB2 no longer fits in the usual 31½ KB that the above computation provides @@ -2399,6 +2400,16 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m main_part_size_in_sectors = ((main_part_size_in_sectors / SelectedDrive.SectorsPerTrack) - extra_part_size_in_tracks) * SelectedDrive.SectorsPerTrack; } + // Try to make sure that the main partition size is a multiple of the cluster size + // This can be especially important when trying to capture an NTFS partition as FFU, as, when + // the NTFS partition is aligned to cluster size, the FFU capture parses the NTFS allocated + // map to only record clusters that are in use, whereas, if not aligned, the FFU capture uses + // a full sector by sector scan of the NTFS partition and records any non-zero garbage, which + // may include garbage leftover data from a previous reformat... + if (ClusterSize % SelectedDrive.SectorSize == 0) { + main_part_size_in_sectors = (((main_part_size_in_sectors * SelectedDrive.SectorSize) / + ClusterSize) * ClusterSize) / SelectedDrive.SectorSize; + } if (main_part_size_in_sectors <= 0) { uprintf("Error: Invalid %S size", main_part_name); return FALSE; diff --git a/src/rufus.rc b/src/rufus.rc index 4cb53e3c..43b44be4 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 4.2.2062" +CAPTION "Rufus 4.2.2063" FONT 9, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP @@ -392,8 +392,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 4,2,2062,0 - PRODUCTVERSION 4,2,2062,0 + FILEVERSION 4,2,2063,0 + PRODUCTVERSION 4,2,2063,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -411,13 +411,13 @@ BEGIN VALUE "Comments", "https://rufus.ie" VALUE "CompanyName", "Akeo Consulting" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "4.2.2062" + VALUE "FileVersion", "4.2.2063" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2023 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" VALUE "OriginalFilename", "rufus-4.2.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "4.2.2062" + VALUE "ProductVersion", "4.2.2063" END END BLOCK "VarFileInfo" diff --git a/src/vhd.c b/src/vhd.c index 844f8e92..6c6abfc0 100644 --- a/src/vhd.c +++ b/src/vhd.c @@ -1023,10 +1023,9 @@ void SaveVHD(void) static_sprintf(filename, "%s.vhdx", rufus_drive[DriveIndex].label); img_save.DeviceNum = (DWORD)ComboBox_GetItemData(hDeviceList, DriveIndex); img_save.DevicePath = GetPhysicalName(img_save.DeviceNum); - // FFU support started with Windows 10 1709 (build 16299) and requires GPT - // TODO: Better check for FFU compatibility - if (WindowsVersion.Major < 10 || WindowsVersion.BuildNumber < 16299 || - SelectedDrive.PartitionStyle != PARTITION_STYLE_GPT) + // FFU support started with Windows 10 1709 (through FfuProvider.dll) and requires GPT + static_sprintf(path, "%s\\dism\\FfuProvider.dll", sysnative_dir); + if ((_accessU(path, 0) != 0) || SelectedDrive.PartitionStyle != PARTITION_STYLE_GPT) img_ext.count = 2; img_save.ImagePath = FileDialog(TRUE, NULL, &img_ext, 0); img_save.Type = VIRTUAL_STORAGE_TYPE_DEVICE_VHD;