diff --git a/res/loc/ChangeLog.txt b/res/loc/ChangeLog.txt index c89fc9f0..e9571a62 100644 --- a/res/loc/ChangeLog.txt +++ b/res/loc/ChangeLog.txt @@ -21,6 +21,7 @@ o v3.22 (2023.??.??) - *NEW* MSG_333 "Create a local account with username:" - *NEW* MSG_334 "Set regional options to the same values as this user's" - *NEW* MSG_335 "Disable BitLocker automatic device encryption" + - *NEW* MSG_336 "Persistent log" o v3.14 (2021.03.31) - *UPDATED* MSG_068 "Error while partitioning drive." -> "Could not partition drive." diff --git a/res/loc/rufus.loc b/res/loc/rufus.loc index 0df1320f..3c0cb318 100644 --- a/res/loc/rufus.loc +++ b/res/loc/rufus.loc @@ -593,6 +593,7 @@ t MSG_332 "Prevent Windows To Go from accessing internal disks" t MSG_333 "Create a local account with username:" t MSG_334 "Set regional options to the same values as this user's" t MSG_335 "Disable BitLocker automatic device encryption" +t MSG_336 "Persistent log" ######################################################################### l "ar-SA" "Arabic (العربية)" 0x0401, 0x0801, 0x0c01, 0x1001, 0x1401, 0x1801, 0x1c01, 0x2001, 0x2401, 0x2801, 0x2c01, 0x3001, 0x3401, 0x3801, 0x3c01, 0x4001 diff --git a/src/rufus.c b/src/rufus.c index 997f34ac..76ecbc07 100755 --- a/src/rufus.c +++ b/src/rufus.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -127,7 +128,7 @@ BOOL advanced_mode_device, advanced_mode_format, allow_dual_uefi_bios, detect_fa BOOL usb_debug, use_fake_units, preserve_timestamps = FALSE, fast_zeroing = FALSE, app_changed_size = FALSE; BOOL zero_drive = FALSE, list_non_usb_removable_drives = FALSE, enable_file_indexing, large_drive = FALSE; BOOL write_as_image = FALSE, write_as_esp = FALSE, use_vds = FALSE, ignore_boot_marker = FALSE; -BOOL appstore_version = FALSE, is_vds_available = TRUE; +BOOL appstore_version = FALSE, is_vds_available = TRUE, persistent_log = FALSE; float fScale = 1.0f; int dialog_showing = 0, selection_default = BT_IMAGE, persistence_unit_selection = -1, imop_win_sel = 0; int default_fs, fs_type, boot_type, partition_type, target_type; @@ -1019,7 +1020,7 @@ BOOL CALLBACK LogCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) log_size--; // remove NUL terminator filepath = FileDialog(TRUE, user_dir, &log_ext, 0); if (filepath != NULL) - FileIO(TRUE, filepath, &log_buffer, &log_size); + FileIO(FILE_IO_WRITE, filepath, &log_buffer, &log_size); safe_free(filepath); } safe_free(log_buffer); @@ -1973,6 +1974,17 @@ static void InitDialog(HWND hDlg) SetWindowTextU(hDlg, tmp); // Now that we have a title, we can find the handle of our Dialog dialog_handle = FindWindowA(NULL, tmp); + // Add a timestamp in persistent log mode + if (persistent_log) { + __time64_t ltime; + char timestamp[32] = "["; + _time64(<ime); + if (_ctime64_s(×tamp[1], sizeof(timestamp) - 2, <ime) == 0) { + // Windows' _ctime64_s adds a \n at the end - replace it + timestamp[strlen(timestamp) - 1] = ']'; + uprintf(timestamp); + } + } uprintf(APPLICATION_NAME " " APPLICATION_ARCH " v%d.%d.%d%s%s", rufus_version[0], rufus_version[1], rufus_version[2], IsAlphaOrBeta(), (ini_file != NULL)?"(Portable)": (appstore_version ? "(AppStore version)" : "")); for (i = 0; i < ARRAYSIZE(resource); i++) { @@ -2353,15 +2365,20 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA return (INT_PTR)TRUE; } - // Save the current log to %LocalAppData%\Rufus\rufus.log + // Save or append the current log to %LocalAppData%\Rufus\rufus.log log_size = GetWindowTextLengthU(hLog); - if ((!user_deleted_rufus_dir) && (log_size > 0) && ((log_buffer = (char*)malloc(log_size)) != NULL)) { + if ((!user_deleted_rufus_dir) && (log_size > 0) && ((log_buffer = (char*)malloc(log_size + 2)) != NULL)) { log_size = GetDlgItemTextU(hLogDialog, IDC_LOG_EDIT, log_buffer, log_size); if (log_size-- > 1) { + if (persistent_log) { + // Add an extra line for persistent logs + log_buffer[log_size - 1] = '\r'; + log_buffer[log_size] = '\n'; + } IGNORE_RETVAL(_chdirU(app_data_dir)); IGNORE_RETVAL(_mkdir(FILES_DIR)); IGNORE_RETVAL(_chdir(FILES_DIR)); - FileIO(TRUE, "rufus.log", &log_buffer, &log_size); + FileIO(persistent_log ? FILE_IO_APPEND : FILE_IO_WRITE, "rufus.log", &log_buffer, &log_size); } safe_free(log_buffer); } @@ -3554,6 +3571,7 @@ skip_args_processing: enable_VHDs = !ReadSettingBool(SETTING_DISABLE_VHDS); enable_extra_hashes = ReadSettingBool(SETTING_ENABLE_EXTRA_HASHES); ignore_boot_marker = ReadSettingBool(SETTING_IGNORE_BOOT_MARKER); + persistent_log = ReadSettingBool(SETTING_PERSISTENT_LOG); // This restores the Windows User Experience/unattend.xml mask from the saved user // settings, and is designed to work even if we add new options later. wue_options = ReadSetting32(SETTING_WUE_OPTIONS); @@ -3790,6 +3808,14 @@ extern int TestChecksum(void); continue; } #endif + // Ctrl-P => Persistent log + if ((ctrl_without_focus || ((GetKeyState(VK_CONTROL) & 0x8000) && (msg.message == WM_KEYDOWN))) + && (msg.wParam == 'P')) { + persistent_log = !persistent_log; + WriteSettingBool(SETTING_PERSISTENT_LOG, persistent_log); + PrintStatusTimeout(lmprintf(MSG_336), persistent_log); + continue; + } if (no_focus && (msg.wParam != VK_CONTROL)) ctrl_without_focus = FALSE; diff --git a/src/rufus.h b/src/rufus.h index 90d2de74..253c6e35 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -312,6 +312,12 @@ enum checksum_type { CHECKSUM_MAX }; +enum file_io_type { + FILE_IO_READ = 0, + FILE_IO_WRITE, + FILE_IO_APPEND +}; + /* Special handling for old .c32 files we need to replace */ #define NB_OLD_C32 2 #define OLD_C32_NAMES { "menu.c32", "vesamenu.c32" } @@ -460,7 +466,7 @@ typedef struct ext_t { EXT_D(var, descriptions); \ ext_t var = { ARRAYSIZE(_##var##_x), filename, _##var##_x, _##var##_d } -/* Duplication of the TBPFLAG enum for Windows 7 taskbar progress */ +/* Duplication of the TBPFLAG enum for Windows taskbar progress */ typedef enum TASKBAR_PROGRESS_FLAGS { TASKBAR_NOPROGRESS = 0, @@ -601,7 +607,7 @@ extern BOOL InstallSyslinux(DWORD drive_index, char drive_letter, int fs); extern uint16_t GetSyslinuxVersion(char* buf, size_t buf_size, char** ext); extern BOOL SetAutorun(const char* path); extern char* FileDialog(BOOL save, char* path, const ext_t* ext, DWORD options); -extern BOOL FileIO(BOOL save, char* path, char** buffer, DWORD* size); +extern BOOL FileIO(enum file_io_type io_type, char* path, char** buffer, DWORD* size); extern unsigned char* GetResource(HMODULE module, char* name, char* type, const char* desc, DWORD* len, BOOL duplicate); extern DWORD GetResourceSize(HMODULE module, char* name, char* type, const char* desc); extern DWORD RunCommand(const char* cmdline, const char* dir, BOOL log); diff --git a/src/rufus.rc b/src/rufus.rc index 6c882b8f..1845ccb9 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.22.1957" +CAPTION "Rufus 3.22.1958" FONT 9, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP @@ -396,8 +396,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 3,22,1957,0 - PRODUCTVERSION 3,22,1957,0 + FILEVERSION 3,22,1958,0 + PRODUCTVERSION 3,22,1958,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -415,13 +415,13 @@ BEGIN VALUE "Comments", "https://rufus.ie" VALUE "CompanyName", "Akeo Consulting" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "3.22.1957" + VALUE "FileVersion", "3.22.1958" 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-3.22.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "3.22.1957" + VALUE "ProductVersion", "3.22.1958" END END BLOCK "VarFileInfo" diff --git a/src/settings.h b/src/settings.h index 90f80e0d..20f0f5ea 100644 --- a/src/settings.h +++ b/src/settings.h @@ -51,6 +51,7 @@ extern char* ini_file; #define SETTING_USE_PROPER_SIZE_UNITS "UseProperSizeUnits" #define SETTING_USE_UDF_VERSION "UseUdfVersion" #define SETTING_USE_VDS "UseVds" +#define SETTING_PERSISTENT_LOG "PersistentLog" #define SETTING_PRESERVE_TIMESTAMPS "PreserveTimestamps" #define SETTING_VERBOSE_UPDATES "VerboseUpdateCheck" #define SETTING_WUE_OPTIONS "WindowsUserExperienceOptions" diff --git a/src/stdfn.c b/src/stdfn.c index bce30a16..15786b84 100644 --- a/src/stdfn.c +++ b/src/stdfn.c @@ -585,17 +585,15 @@ static PSID GetSID(void) { return ret; } -/* - * read or write I/O to a file - * buffer is allocated by the procedure. path is UTF-8 - */ -BOOL FileIO(BOOL save, char* path, char** buffer, DWORD* size) +BOOL FileIO(enum file_io_type io_type, char* path, char** buffer, DWORD* size) { SECURITY_ATTRIBUTES s_attr, *sa = NULL; SECURITY_DESCRIPTOR s_desc; + const LARGE_INTEGER liZero = { .QuadPart = 0ULL }; PSID sid = NULL; HANDLE handle; - BOOL r; + DWORD dwDesiredAccess = 0, dwCreationDisposition = 0; + BOOL r = FALSE; BOOL ret = FALSE; // Change the owner from admin to regular user @@ -611,20 +609,34 @@ BOOL FileIO(BOOL save, char* path, char** buffer, DWORD* size) uprintf("Could not set security descriptor: %s\n", WindowsErrorString()); } - if (!save) { + switch (io_type) { + case FILE_IO_READ: *buffer = NULL; + dwDesiredAccess = GENERIC_READ; + dwCreationDisposition = OPEN_EXISTING; + break; + case FILE_IO_WRITE: + dwDesiredAccess = GENERIC_WRITE; + dwCreationDisposition = CREATE_ALWAYS; + break; + case FILE_IO_APPEND: + dwDesiredAccess = FILE_APPEND_DATA; + dwCreationDisposition = OPEN_ALWAYS; + break; + default: + assert(FALSE); + break; } - handle = CreateFileU(path, save?GENERIC_WRITE:GENERIC_READ, FILE_SHARE_READ, - sa, save?CREATE_ALWAYS:OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + handle = CreateFileU(path, dwDesiredAccess, FILE_SHARE_READ, sa, + dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL); if (handle == INVALID_HANDLE_VALUE) { - uprintf("Could not %s file '%s'\n", save?"create":"open", path); + uprintf("Could not open '%s': %s", path, WindowsErrorString()); goto out; } - if (save) { - r = WriteFile(handle, *buffer, *size, size, NULL); - } else { + switch (io_type) { + case FILE_IO_READ: *size = GetFileSize(handle, NULL); *buffer = (char*)malloc(*size); if (*buffer == NULL) { @@ -632,24 +644,29 @@ BOOL FileIO(BOOL save, char* path, char** buffer, DWORD* size) goto out; } r = ReadFile(handle, *buffer, *size, size, NULL); + break; + case FILE_IO_APPEND: + SetFilePointerEx(handle, liZero, NULL, FILE_END); + // Fall through + case FILE_IO_WRITE: + r = WriteFile(handle, *buffer, *size, size, NULL); + break; } if (!r) { - uprintf("I/O Error: %s\n", WindowsErrorString()); + uprintf("I/O Error: %s", WindowsErrorString()); goto out; } - PrintInfoDebug(0, save?MSG_216:MSG_215, path); + PrintInfoDebug(0, (io_type == FILE_IO_READ) ? MSG_215 : MSG_216, path); ret = TRUE; out: CloseHandle(handle); - if (!ret) { - // Only leave a buffer allocated if successful + if (!ret && (io_type == FILE_IO_READ)) { + // Only leave the buffer allocated if we were able to read data + safe_free(*buffer); *size = 0; - if (!save) { - safe_free(*buffer); - } } return ret; }