diff --git a/res/localization/ChangeLog.txt b/res/localization/ChangeLog.txt index d432b8aa..4aef5f69 100644 --- a/res/localization/ChangeLog.txt +++ b/res/localization/ChangeLog.txt @@ -18,6 +18,7 @@ For instance, MSG_114, that was introduced in v1.0.8 is MORE than one line! o Version 1.0.24 (2018.??.??) - *NEW* MSG_087 - *NEW* MSG_172 + - *NEW* MSG_199 o Version 1.0.23 (2018.03.27) - All positioning ('m', 's') has now been removed as well as some controls, for the 3.0 UI redesign diff --git a/res/localization/casper_test.iso b/res/localization/casper_test.iso new file mode 100644 index 00000000..2d61f0c1 Binary files /dev/null and b/res/localization/casper_test.iso differ diff --git a/res/localization/rufus.loc b/res/localization/rufus.loc index 0f305765..04eaa95d 100644 --- a/res/localization/rufus.loc +++ b/res/localization/rufus.loc @@ -424,6 +424,7 @@ t MSG_196 "IMPORTANT: THIS DRIVE USES A NONSTANDARD SECTOR SIZE!\n\n" t MSG_197 "Nonstandard sector size detected" t MSG_198 "'Windows To Go' can only be installed on a GPT partitioned drive if it has " "the FIXED attribute set. The current drive was not detected as FIXED." +t MSG_199 "Persistent partition size" # Status messages - these messages will appear on the status bar t MSG_201 "Cancelling - Please wait..." diff --git a/src/iso.c b/src/iso.c index 5661f792..d247b7b0 100644 --- a/src/iso.c +++ b/src/iso.c @@ -89,6 +89,7 @@ static const char* pe_file[] = { "ntdetect.com", "setupldr.bin", "txtsetup.sif" static const char* reactos_name = "setupldr.sys"; // TODO: freeldr.sys doesn't seem to work static const char* kolibri_name = "kolibri.img"; static const char* autorun_name = "autorun.inf"; +static const char* casper_name = "CASPER"; static const char* stupid_antivirus = " NOTE: This is usually caused by a poorly designed security solution. " "See https://rufus.akeo.ie/compatibility.\r\n This file will be skipped for now, but you should really " "look into using a *SMARTER* antivirus solution."; @@ -193,6 +194,9 @@ static BOOL check_iso_props(const char* psz_dirname, int64_t file_length, const if (safe_stricmp(psz_basename, kolibri_name) == 0) { img_report.has_kolibrios = TRUE; } + if (safe_stricmp(psz_basename, casper_name) == 0) { + img_report.has_casper = TRUE; + } if (safe_stricmp(psz_basename, bootmgr_efi_name) == 0) { img_report.has_efi |= 1; } diff --git a/src/rufus.c b/src/rufus.c index 1b1a6b45..561bdb5d 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -105,7 +105,7 @@ BOOL advanced_mode_device, advanced_mode_format, allow_dual_uefi_bios, detect_fa BOOL use_fake_units, preserve_timestamps = FALSE; BOOL zero_drive = FALSE, list_non_usb_removable_drives = FALSE, enable_file_indexing, large_drive = FALSE, write_as_image = FALSE; float fScale = 1.0f; -int dialog_showing = 0, selection_default, windows_to_go_selection = 0; +int dialog_showing = 0, selection_default = BT_IMAGE, windows_to_go_selection = 0, persistence_unit_selection = 0; int default_fs, fs, bt, pt, tt; // file system, boot type, partition type, target type char szFolderPath[MAX_PATH], app_dir[MAX_PATH], system_dir[MAX_PATH], temp_dir[MAX_PATH], sysnative_dir[MAX_PATH]; char embedded_sl_version_str[2][12] = { "?.??", "?.??" }; @@ -1568,7 +1568,6 @@ static void InitDialog(HWND hDlg) uprintf("If you think you can help update this translation, please e-mail the author of this application"); } - selection_default = BT_IMAGE; CreateTaskbarList(); SetTaskbarProgressState(TASKBAR_NORMAL); @@ -1591,6 +1590,11 @@ static void InitDialog(HWND hDlg) IGNORE_RETVAL(ComboBox_SetItemData(hCtrl, ComboBox_AddStringU(hCtrl, lmprintf(MSG_117)), FALSE)); IGNORE_RETVAL(ComboBox_SetItemData(hCtrl, ComboBox_AddStringU(hCtrl, lmprintf(MSG_118)), TRUE)); + // Fill up the Persistence Units dropdown + hCtrl = GetDlgItem(hMainDialog, IDC_PERSISTENCE_UNITS); + for (i = 0; i < 3; i++) + IGNORE_RETVAL(ComboBox_SetItemData(hCtrl, ComboBox_AddStringU(hCtrl, lmprintf(MSG_022 + i)), i)); + // Fill up the MBR masqueraded disk IDs ("8 disks should be enough for anybody") IGNORE_RETVAL(ComboBox_SetItemData(hDiskID, ComboBox_AddStringU(hDiskID, lmprintf(MSG_030, LEFT_TO_RIGHT_EMBEDDING "0x80" POP_DIRECTIONAL_FORMATTING)), 0x80)); for (i=1; i<=7; i++) { @@ -1614,6 +1618,8 @@ static void InitDialog(HWND hDlg) AdjustForLowDPI(hDlg); // Because we created the log dialog before we computed our sizes, we need to send a custom message SendMessage(hLogDialog, UM_RESIZE_BUTTONS, 0, 0); + // Limit the amount of characters for the Persistence size field + SendMessage(GetDlgItem(hDlg, IDC_PERSISTENCE_SIZE), EM_LIMITTEXT, 7, 0); // Create the status line and initialize the taskbar icon for progress overlay CreateStatusBar(); @@ -1856,9 +1862,10 @@ out: static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { static DWORD DeviceNum = 0; - static uint64_t LastRefresh = 0; + static uint64_t LastRefresh = 0, pos; static BOOL first_log_display = TRUE, isMarquee = FALSE, queued_hotplug_event = FALSE; static ULONG ulRegister = 0; + static LONG lPos; static LPITEMIDLIST pidlDesktop = NULL; static SHChangeNotifyEntry NotifyEntry; static DWORD_PTR thread_affinity[4]; @@ -2039,6 +2046,19 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA SetFileSystemAndClusterSize(NULL); windows_to_go_selection = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_IMAGE_OPTION)); break; + case IDC_PERSISTENCE_UNITS: + if (HIWORD(wParam) != CBN_SELCHANGE) + break; + if (ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_PERSISTENCE_UNITS)) == persistence_unit_selection) + break; + GetWindowTextA(GetDlgItem(hMainDialog, IDC_PERSISTENCE_SIZE), tmp, sizeof(tmp)); + pos = atol(tmp) * MB; + for (i = 0; i < persistence_unit_selection; i++) + pos *= 1024; + persistence_unit_selection = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_PERSISTENCE_UNITS)); + // TODO: Use projected size. For now force the selected ISO to a 4 GB size + SetPersistenceSlider(pos, SelectedDrive.DiskSize - 4 * GB); + break; case IDC_NB_PASSES: if (HIWORD(wParam) != CBN_SELCHANGE) break; @@ -2379,6 +2399,12 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA } break; + case WM_HSCROLL: + lPos = (LONG)SendMessage(GetDlgItem(hMainDialog, IDC_PERSISTENCE_SLIDER), TBM_GETPOS, 0, 0); + sprintf(tmp, "%ld", lPos); + SetWindowTextA(GetDlgItem(hMainDialog, IDC_PERSISTENCE_SIZE), tmp); + break; + case WM_DROPFILES: droppedFileInfo = (HDROP)wParam; wbuffer = calloc(MAX_PATH, sizeof(wchar_t)); diff --git a/src/rufus.h b/src/rufus.h index d6eb8e4f..00fe0fa2 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -282,12 +282,7 @@ enum checksum_type { #define IS_EFI_BOOTABLE(r) (r.has_efi != 0) #define IS_BIOS_BOOTABLE(r) (HAS_BOOTMGR(r) || HAS_SYSLINUX(r) || HAS_WINPE(r) || HAS_GRUB(r) || HAS_REACTOS(r) || HAS_KOLIBRIOS(r)) #define HAS_WINTOGO(r) (HAS_BOOTMGR(r) && IS_EFI_BOOTABLE(r) && HAS_INSTALL_WIM(r) && (r.install_wim_version < MAX_WIM_VERSION)) -#ifdef RUFUS_TEST -// TODO: have a better test for persistence/Linux -#define HAS_PERSISTENCE(r) HAS_SYSLINUX(r) -#else -#define HAS_PERSISTENCE(r) FALSE -#endif +#define HAS_PERSISTENCE(r) (r.has_casper) #define IS_FAT(fs) ((fs == FS_FAT16) || (fs == FS_FAT32)) typedef struct { @@ -320,6 +315,7 @@ typedef struct { BOOLEAN uses_minint; BOOLEAN compression_type; BOOLEAN is_vhd; + BOOLEAN has_casper; uint16_t sl_version; // Syslinux/Isolinux version char sl_version_str[12]; char sl_version_ext[32]; diff --git a/src/rufus.rc b/src/rufus.rc index e09246f2..60853c9a 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.2.1330" +CAPTION "Rufus 3.2.1331" FONT 9, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP @@ -47,7 +47,7 @@ BEGIN LTEXT "Image option",IDS_IMAGE_OPTION_TXT,8,65,216,8 COMBOBOX IDC_IMAGE_OPTION,8,74,96,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL "",IDC_PERSISTENCE_SLIDER,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,125,76,34,8 - EDITTEXT IDC_PERSISTENCE_SIZE,160,74,36,12,ES_AUTOHSCROLL + EDITTEXT IDC_PERSISTENCE_SIZE,160,74,36,12,ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT COMBOBOX IDC_PERSISTENCE_UNITS,200,74,24,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Partition scheme",IDS_PARTITION_TYPE_TXT,8,87,96,8 COMBOBOX IDC_PARTITION_TYPE,8,96,96,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP @@ -392,8 +392,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 3,2,1330,0 - PRODUCTVERSION 3,2,1330,0 + FILEVERSION 3,2,1331,0 + PRODUCTVERSION 3,2,1331,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -410,13 +410,13 @@ BEGIN BEGIN VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "3.2.1330" + VALUE "FileVersion", "3.2.1331" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2018 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "3.2.1330" + VALUE "ProductVersion", "3.2.1331" END END BLOCK "VarFileInfo" diff --git a/src/ui.c b/src/ui.c index 5251f85f..70cfd59a 100644 --- a/src/ui.c +++ b/src/ui.c @@ -30,7 +30,6 @@ #include #include #include -#include #include "rufus.h" #include "drive.h" @@ -287,7 +286,7 @@ void PositionMainControls(HWND hDlg) // Don't forget to add the dialog border width, since we resize the whole dialog SetWindowPos(hDlg, NULL, -1, -1, fw + 2 * mw + dbw, rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER); - // Resize the height of the label and progress bar to the height of standard dropdowns + // Resize the height of the label, persistence size and progress bar to the height of standard dropdowns hCtrl = GetDlgItem(hDlg, IDC_DEVICE); GetWindowRect(hCtrl, &rc); MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); @@ -298,6 +297,10 @@ void PositionMainControls(HWND hDlg) GetWindowRect(hCtrl, &rc); MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); SetWindowPos(hCtrl, hAdvancedFormatToolbar, rc.left, rc.top, rc.right - rc.left, ddh, SWP_NOZORDER); + hCtrl = GetDlgItem(hDlg, IDC_PERSISTENCE_SIZE); + GetWindowRect(hCtrl, &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + SetWindowPos(hCtrl, GetDlgItem(hDlg, IDC_PERSISTENCE_SLIDER), rc.left, rc.top, rc.right - rc.left, ddh, SWP_NOZORDER); GetWindowRect(hProgress, &rc); MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); SetWindowPos(hProgress, hNBPasses, rc.left, rc.top, rc.right - rc.left, ddh, SWP_NOZORDER); @@ -392,6 +395,25 @@ void PositionMainControls(HWND hDlg) SendMessage(hHashToolbar, TB_SETPADDING, 0, MAKELPARAM(sz.cx + 3, sz.cy + 2)); SetWindowPos(hHashToolbar, hBootType, mw + bsw + ssw, rc.top, sbw, ddbh, 0); + // Reposition the Persistence slider and resize it to the boot selection width + hCtrl = GetDlgItem(hDlg, IDC_PERSISTENCE_SLIDER); + GetWindowRect(hCtrl, &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + SetWindowPos(hCtrl, hTargetSystem, mw, rc.top, bsw, rc.bottom - rc.top, 0); + + // Reposition the Persistence Units dropdown (no need to resize) + hCtrl = GetDlgItem(hDlg, IDC_PERSISTENCE_UNITS); + GetWindowRect(hCtrl, &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + sz.cx = fw - (rc.right - rc.left); + SetWindowPos(hCtrl, hTargetSystem, mw + sz.cx, rc.top, rc.right - rc.left, rc.bottom - rc.top, 0); + + // Reposition and resize the Persistence Size edit + hCtrl = GetDlgItem(hDlg, IDC_PERSISTENCE_SIZE); + GetWindowRect(hCtrl, &rc); + MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); + SetWindowPos(hCtrl, hTargetSystem, mw + bsw + ssw, rc.top, sz.cx - bsw - 2*ssw, rc.bottom - rc.top, 0); + // Reposition the CSM help tip hCtrl = GetDlgItem(hDlg, IDS_CSM_HELP_TXT); GetWindowRect(hCtrl, &rc); @@ -613,13 +635,45 @@ void ToggleAdvancedFormatOptions(BOOL enable) InvalidateRect(hMainDialog, NULL, TRUE); } +void SetPersistenceSlider(uint64_t pos, uint64_t max) +{ + char tmp[12]; + int i; + IGNORE_RETVAL(ComboBox_SetCurSel(GetDlgItem(hMainDialog, IDC_PERSISTENCE_UNITS), persistence_unit_selection)); + pos /= MB; + max /= MB; + for (i = 0; i < persistence_unit_selection; i++) { + pos /= 1024; + max /= 1024; + } + SendMessage(GetDlgItem(hMainDialog, IDC_PERSISTENCE_SLIDER), TBM_SETRANGEMIN, (WPARAM)FALSE, (LPARAM)0); + SendMessage(GetDlgItem(hMainDialog, IDC_PERSISTENCE_SLIDER), TBM_SETRANGEMAX, (WPARAM)FALSE, (LPARAM)max); + SendMessage(GetDlgItem(hMainDialog, IDC_PERSISTENCE_SLIDER), TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pos); + static_sprintf(tmp, "%ld", (LONG)pos); + SetWindowTextA(GetDlgItem(hMainDialog, IDC_PERSISTENCE_SIZE), tmp); +} + // Toggle the Image Option dropdown (Windows To Go or persistence settings) void ToggleImageOption(uint8_t mask) { + static BOOL relaunch = FALSE; + static char image_option_txt[128] = ""; int i, shift = (popcnt8(image_options) >= 2) ? 0 : rh; assert(popcnt8(mask) <= 1); + // mask is set to 0 when called during (re)init + if (mask == 0) { + if (relaunch) { + if ((selection_default == BT_IMAGE) && (image_path != NULL)) + goto skip; + } else { + relaunch = TRUE; + // Keep a copy of the original image option translation, as it'll be easier to toggle + GetWindowTextU(GetDlgItem(hMainDialog, IDS_IMAGE_OPTION_TXT), image_option_txt, sizeof(image_option_txt)); + } + } + if (mask & IMOP_WINTOGO) { if (nWindowsVersion < WINDOWS_8) return; @@ -649,12 +703,22 @@ void ToggleImageOption(uint8_t mask) } } +skip: // Hide or show the boot options for (i = 0; i < ARRAYSIZE(image_option_toggle_ids); i++) { ShowWindow(GetDlgItem(hMainDialog, image_option_toggle_ids[i][0]), (image_options & image_option_toggle_ids[i][1]) ? SW_SHOW : SW_HIDE); } - + // Set the dropdown default selection + if (image_options & IMOP_WINTOGO) { + SetWindowTextU(GetDlgItem(hMainDialog, IDS_IMAGE_OPTION_TXT), image_option_txt); + IGNORE_RETVAL(ComboBox_SetCurSel(GetDlgItem(hMainDialog, IDC_IMAGE_OPTION), windows_to_go_selection)); + } else if (image_options & IMOP_PERSISTENCE) { + SetWindowTextU(GetDlgItem(hMainDialog, IDS_IMAGE_OPTION_TXT), lmprintf(MSG_199)); + // TODO: Use projected size and reuse existing pos. For now force the selected ISO to a 4 GB size + uint64_t max_size = SelectedDrive.DiskSize - 4 * GB; + SetPersistenceSlider(max_size / 2, max_size); + } // If you don't force a redraw here, all kind of bad UI artifacts happen... InvalidateRect(hMainDialog, NULL, TRUE); } diff --git a/src/ui.h b/src/ui.h index 254ac604..9f80a598 100644 --- a/src/ui.h +++ b/src/ui.h @@ -50,7 +50,8 @@ extern BOOL advanced_mode_device, advanced_mode_format, force_large_fat32; extern loc_cmd* selected_locale; extern const char *sfd_name, *flash_type[BADLOCKS_PATTERN_TYPES]; extern char *short_image_path; -extern int advanced_device_section_height, advanced_format_section_height, windows_to_go_selection; +extern int advanced_device_section_height, advanced_format_section_height; +extern int windows_to_go_selection, persistence_unit_selection; extern int selection_default, cbw, ddw, ddbh, bh; extern void SetComboEntry(HWND hDlg, int data); @@ -61,6 +62,7 @@ extern void GetFullWidth(HWND hDlg); extern void PositionMainControls(HWND hDlg); extern void AdjustForLowDPI(HWND hDlg); extern void SetSectionHeaders(HWND hDlg); +extern void SetPersistenceSlider(uint64_t pos, uint64_t max); extern void ToggleAdvancedDeviceOptions(BOOL enable); extern void ToggleAdvancedFormatOptions(BOOL enable); extern void ToggleImageOption(uint8_t mask);