diff --git a/src/.msvc/rufus.vcxproj b/src/.msvc/rufus.vcxproj index bffa495e..f4b4a400 100644 --- a/src/.msvc/rufus.vcxproj +++ b/src/.msvc/rufus.vcxproj @@ -203,6 +203,7 @@ + diff --git a/src/.msvc/rufus.vcxproj.filters b/src/.msvc/rufus.vcxproj.filters index ca115177..04be5abb 100644 --- a/src/.msvc/rufus.vcxproj.filters +++ b/src/.msvc/rufus.vcxproj.filters @@ -128,6 +128,9 @@ Header Files + + Header Files + diff --git a/src/iso.c b/src/iso.c index 562e1cd2..ec58d930 100644 --- a/src/iso.c +++ b/src/iso.c @@ -120,7 +120,7 @@ static void log_handler (cdio_log_level_t level, const char *message) { switch(level) { case CDIO_LOG_DEBUG: - // TODO: use a registry key to enable libcdio debug? + // TODO: use a setting to enable libcdio debug? return; default: uprintf("libcdio: %s\n", message); diff --git a/src/net.c b/src/net.c index 774ddbb6..7168b9b1 100644 --- a/src/net.c +++ b/src/net.c @@ -32,7 +32,7 @@ #include "msapi_utf8.h" #include "rufus.h" -#include "registry.h" +#include "settings.h" #include "resource.h" #include "localization.h" @@ -441,7 +441,7 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) int64_t local_time = 0, reg_time, server_time, update_interval; update_check_in_progress = TRUE; - verbose = ReadRegistryKey32(REGKEY_HKCU, REGKEY_VERBOSE_UPDATES); + verbose = ReadSetting32(SETTING_VERBOSE_UPDATES); // Without this the FileDialog will produce error 0x8001010E when compiled for Vista or later IGNORE_RETVAL(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)); // Unless the update was forced, wait a while before performing the update check @@ -453,14 +453,14 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) Sleep(500); } while ((!force_update_check) && ((iso_op_in_progress || format_op_in_progress || (dialog_showing>0)))); if (!force_update_check) { - if ((ReadRegistryKey32(REGKEY_HKCU, REGKEY_UPDATE_INTERVAL) == -1)) { - vuprintf("Check for updates disabled, as per registry settings.\n"); + if ((ReadSetting32(SETTING_UPDATE_INTERVAL) == -1)) { + vuprintf("Check for updates disabled, as per settings.\n"); goto out; } - reg_time = ReadRegistryKey64(REGKEY_HKCU, REGKEY_LAST_UPDATE); - update_interval = (int64_t)ReadRegistryKey32(REGKEY_HKCU, REGKEY_UPDATE_INTERVAL); + reg_time = ReadSetting64(SETTING_LAST_UPDATE); + update_interval = (int64_t)ReadSetting32(SETTING_UPDATE_INTERVAL); if (update_interval == 0) { - WriteRegistryKey32(REGKEY_HKCU, REGKEY_UPDATE_INTERVAL, DEFAULT_UPDATE_INTERVAL); + WriteSetting32(SETTING_UPDATE_INTERVAL, DEFAULT_UPDATE_INTERVAL); update_interval = DEFAULT_UPDATE_INTERVAL; } GetSystemTime(&LocalTime); @@ -496,7 +496,7 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) goto out; status++; // 2 - releases_only = !GetRegistryKeyBool(REGKEY_HKCU, REGKEY_INCLUDE_BETAS); + releases_only = !ReadSettingBool(SETTING_INCLUDE_BETAS); for (k=0; (k<(releases_only?1:(int)ARRAYSIZE(channel))) && (!found_new_version); k++) { uprintf("Checking %s channel...\n", channel[k]); @@ -562,7 +562,7 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) server_time = ((((int64_t)FileTime.dwHighDateTime)<<32) + FileTime.dwLowDateTime) / 10000000; vvuprintf("Server time: %" PRId64 "\n", server_time); // Always store the server response time - the only clock we trust! - WriteRegistryKey64(REGKEY_HKCU, REGKEY_LAST_UPDATE, server_time); + WriteSetting64(SETTING_LAST_UPDATE, server_time); // Might as well let the user know if (!force_update_check) { if ((local_time > server_time + 600) || (local_time < server_time - 600)) { diff --git a/src/parser.c b/src/parser.c index 570e7eb1..1f1ad6d1 100644 --- a/src/parser.c +++ b/src/parser.c @@ -37,6 +37,7 @@ static const char space[] = " \t"; static const wchar_t wspace[] = L" \t"; +static const char* conversion_error = "Could not convert '%s' to UTF-16"; const struct {char c; int flag;} attr_parse[] = { { 'r', LOC_RIGHT_TO_LEFT }, @@ -215,7 +216,7 @@ FILE* open_loc_file(const char* filename) } wfilename = utf8_to_wchar(filename); if (wfilename == NULL) { - uprintf("localization: could not convert '%s' filename to UTF-16\n", filename); + uprintf(conversion_error, filename); goto out; } fd = _wfopen(wfilename, L"rb"); @@ -638,12 +639,12 @@ char* get_token_data_file(const char* token, const char* filename) wfilename = utf8_to_wchar(filename); if (wfilename == NULL) { - uprintf("Could not convert '%s' to UTF-16\n", filename); + uprintf(conversion_error, filename); goto out; } wtoken = utf8_to_wchar(token); if (wfilename == NULL) { - uprintf("Could not convert '%s' to UTF-16\n", token); + uprintf(conversion_error, token); goto out; } fd = _wfopen(wfilename, L"r, ccs=UNICODE"); @@ -667,6 +668,159 @@ out: return ret; } +/* + * replace or add 'data' for token 'token' in config file 'filename' + */ +char* set_token_data_file(const char* token, const char* data, const char* filename) +{ + const wchar_t* outmode[] = { L"w", L"w, ccs=UTF-8", L"w, ccs=UTF-16LE" }; + wchar_t *wtoken = NULL, *wfilename = NULL, *wtmpname = NULL, *wdata = NULL, bom = 0; + wchar_t buf[1024]; + FILE *fd_in = NULL, *fd_out = NULL; + size_t i, size; + int mode = 0; + char *ret = NULL, tmp[2]; + + if ((filename == NULL) || (token == NULL) || (data == NULL)) + return NULL; + if ((filename[0] == 0) || (token[0] == 0) || (data[0] == 0)) + return NULL; + + wfilename = utf8_to_wchar(filename); + if (wfilename == NULL) { + uprintf(conversion_error, filename); + goto out; + } + wtoken = utf8_to_wchar(token); + if (wfilename == NULL) { + uprintf(conversion_error, token); + goto out; + } + wdata = utf8_to_wchar(data); + if (wdata == NULL) { + uprintf(conversion_error, data); + goto out; + } + + fd_in = _wfopen(wfilename, L"r, ccs=UNICODE"); + if (fd_in == NULL) { + uprintf("Could not open file '%s'\n", filename); + goto out; + } + // Check the input file's BOM and create an output file with the same + if (fread(&bom, sizeof(bom), 1, fd_in) == 1) { + switch(bom) { + case 0xFEFF: + mode = 2; // UTF-16 (LE) + break; + case 0xBBEF: // Yeah, the UTF-8 BOM is really 0xEF,0xBB,0xBF, but + mode = 1; // find me a non UTF-8 file that actually begins with "ï»" + break; + default: + mode = 0; // ANSI + break; + } + fseek(fd_in, 0, SEEK_SET); + } + + wtmpname = (wchar_t*)calloc(wcslen(wfilename)+2, sizeof(wchar_t)); + if (wtmpname == NULL) { + uprintf("Could not allocate space for temporary output name\n"); + goto out; + } + wcscpy(wtmpname, wfilename); + wtmpname[wcslen(wtmpname)] = '~'; + + fd_out = _wfopen(wtmpname, outmode[mode]); + if (fd_out == NULL) { + uprintf("Could not open temporary output file '%s~'\n", filename); + goto out; + } + + // Process individual lines. NUL is always appended. + while (fgetws(buf, ARRAYSIZE(buf), fd_in) != NULL) { + + i = 0; + + // Skip leading spaces + i += wcsspn(&buf[i], wspace); + + // Ignore comments or section headers + if ((buf[i] == ';') || (buf[i] == '[')) { + fputws(buf, fd_out); + continue; + } + + // Our token should begin a line + if (_wcsnicmp(&buf[i], wtoken, wcslen(wtoken)) != 0) { + fputws(buf, fd_out); + continue; + } + + // Token was found, move past token + i += wcslen(wtoken); + + // Skip spaces + i += wcsspn(&buf[i], wspace); + + // Check for an equal sign + if (buf[i] != L'=') { + fputws(buf, fd_out); + continue; + } + i++; + + // Skip spaces after equal sign + i += wcsspn(&buf[i], wspace); + + // Output the token + buf[i] = 0; + fputws(buf, fd_out); + + // Now output the new data + fwprintf(fd_out, L"%s\n", wdata); + ret = (char*)data; + } + + if (ret == NULL) { + // Didn't find an existing token => append it + fwprintf(fd_out, L"%s = %s\n", wtoken, wdata); + ret = (char*)data; + } + +out: + if (fd_in != NULL) fclose(fd_in); + if (fd_out != NULL) fclose(fd_out); + + // If an insertion occurred, delete existing file and use the new one + if (ret != NULL) { + // We're in Windows text mode => Remove CRs if requested + fd_in = _wfopen(wtmpname, L"rb"); + fd_out = _wfopen(wfilename, L"wb"); + // Don't check fds + if ((fd_in != NULL) && (fd_out != NULL)) { + size = (mode==2)?2:1; + while(fread(tmp, size, 1, fd_in) == 1) + fwrite(tmp, size, 1, fd_out); + fclose(fd_in); + fclose(fd_out); + } else { + uprintf("Could not write '%s' - original file has been left unmodified\n", filename); + ret = NULL; + if (fd_in != NULL) fclose(fd_in); + if (fd_out != NULL) fclose(fd_out); + } + } + if (wtmpname != NULL) + _wunlink(wtmpname); + safe_free(wfilename); + safe_free(wtmpname); + safe_free(wtoken); + safe_free(wdata); + + return ret; +} + /* * Parse a buffer (ANSI or UTF-8) and return the data for the 'n'th occurrence of 'token' * The returned string is UTF-8 and MUST be freed by the caller @@ -806,17 +960,17 @@ char* insert_section_data(const char* filename, const char* section, const char* wfilename = utf8_to_wchar(filename); if (wfilename == NULL) { - uprintf("Could not convert '%s' to UTF-16\n", filename); + uprintf(conversion_error, filename); goto out; } wsection = utf8_to_wchar(section); if (wfilename == NULL) { - uprintf("Could not convert '%s' to UTF-16\n", section); + uprintf(conversion_error, section); goto out; } wdata = utf8_to_wchar(data); if (wdata == NULL) { - uprintf("Could not convert '%s' to UTF-16\n", data); + uprintf(conversion_error, data); goto out; } @@ -842,9 +996,8 @@ char* insert_section_data(const char* filename, const char* section, const char* break; } fseek(fd_in, 0, SEEK_SET); - duprintf("'%s' was detected as %s\n", filename, - (mode==0)?"ANSI/UTF8 (no BOM)":((mode==1)?"UTF8 (with BOM)":"UTF16 (with BOM")); - +// duprintf("'%s' was detected as %s\n", filename, +// (mode==0)?"ANSI/UTF8 (no BOM)":((mode==1)?"UTF8 (with BOM)":"UTF16 (with BOM")); wtmpname = (wchar_t*)calloc(wcslen(wfilename)+2, sizeof(wchar_t)); if (wtmpname == NULL) { @@ -941,22 +1094,22 @@ char* replace_in_token_data(const char* filename, const char* token, const char* wfilename = utf8_to_wchar(filename); if (wfilename == NULL) { - uprintf("Could not convert '%s' to UTF-16\n", filename); + uprintf(conversion_error, filename); goto out; } wtoken = utf8_to_wchar(token); if (wfilename == NULL) { - uprintf("Could not convert '%s' to UTF-16\n", token); + uprintf(conversion_error, token); goto out; } wsrc = utf8_to_wchar(src); if (wsrc == NULL) { - uprintf("Could not convert '%s' to UTF-16\n", src); + uprintf(conversion_error, src); goto out; } wrep = utf8_to_wchar(rep); if (wsrc == NULL) { - uprintf("Could not convert '%s' to UTF-16\n", rep); + uprintf(conversion_error, rep); goto out; } @@ -1015,7 +1168,7 @@ char* replace_in_token_data(const char* filename, const char* token, const char* } // Token was found, move past token - i += strlen(token); + i += wcslen(wtoken); // Skip spaces i += wcsspn(&buf[i], wspace); diff --git a/src/registry.h b/src/registry.h index 707b8eea..89dd7f62 100644 --- a/src/registry.h +++ b/src/registry.h @@ -29,17 +29,6 @@ extern "C" { #define REGKEY_HKCU HKEY_CURRENT_USER #define REGKEY_HKLM HKEY_LOCAL_MACHINE -/* - * List of registry keys used by this application - * These keys go into HKCU\Software\COMPANY_NAME\APPLICATION_NAME\ - */ -#define REGKEY_VERBOSE_UPDATES "VerboseUpdateCheck" -#define REGKEY_LAST_UPDATE "LastUpdateCheck" -#define REGKEY_UPDATE_INTERVAL "UpdateCheckInterval" -#define REGKEY_INCLUDE_BETAS "CheckForBetas" -#define REGKEY_COMM_CHECK "CommCheck" -#define REGKEY_LOCALE "Locale" - /* Delete a registry key from \Software and all its values If the key has subkeys, this call will fail. */ static __inline BOOL DeleteRegistryKey(HKEY key_root, const char* key_name) @@ -144,7 +133,7 @@ out: // Check that a key is accessible for R/W (will create a key if not already existing) static __inline BOOL CheckRegistryKey64(HKEY root, const char* key) { LONGLONG val; - return GetRegistryKey64(root, key, &val); // && SetRegistryKey64(key, val)); + return GetRegistryKey64(root, key, &val); } static __inline int64_t ReadRegistryKey64(HKEY root, const char* key) { LONGLONG val; @@ -174,8 +163,8 @@ static __inline BOOL WriteRegistryKey32(HKEY root, const char* key, int32_t val) } /* Helpers for boolean registry operations */ -#define GetRegistryKeyBool(root, key) (ReadRegistryKey32(root, key) != 0) -#define SetRegistryKeyBool(root, key, b) WriteRegistryKey32(root, key, (b)?1:0) +#define ReadRegistryKeyBool(root, key) (ReadRegistryKey32(root, key) != 0) +#define WriteRegistryKeyBool(root, key, b) WriteRegistryKey32(root, key, (b)?1:0) #define CheckRegistryKeyBool CheckRegistryKey32 /* Helpers for String registry operations */ diff --git a/src/rufus.c b/src/rufus.c index 833890b5..c82556ed 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -39,7 +39,7 @@ #include "resource.h" #include "rufus.h" #include "drive.h" -#include "registry.h" +#include "settings.h" #include "localization.h" #include "bled/bled.h" #include "../res/grub/grub_version.h" @@ -110,7 +110,7 @@ static UINT_PTR UM_LANGUAGE_MENU_MAX = UM_LANGUAGE_MENU; static RECT relaunch_rc = { -65536, -65536, 0, 0}; static UINT uBootChecked = BST_CHECKED, uQFChecked = BST_CHECKED, uMBRChecked = BST_UNCHECKED; char ClusterSizeLabel[MAX_CLUSTER_SIZES][64]; -char msgbox[1024], msgbox_title[32]; +char msgbox[1024], msgbox_title[32], *ini_file = NULL; /* * Globals @@ -1533,7 +1533,7 @@ void InitDialog(HWND hDlg) static_sprintf(tmp, "%s%d.%d.%d.%d " APPLICATION_NAME, IsAlphaOrBeta(), rufus_version[0], rufus_version[1], rufus_version[2], rufus_version[3]); } SetWindowTextU(hDlg, tmp); - uprintf(APPLICATION_NAME " version: %d.%d.%d.%d%s\n", rufus_version[0], rufus_version[1], rufus_version[2], rufus_version[3], IsAlphaOrBeta()); + uprintf(APPLICATION_NAME " version: %d.%d.%d.%d%s", rufus_version[0], rufus_version[1], rufus_version[2], rufus_version[3], IsAlphaOrBeta()); for (i=0; i go to basic mode ToggleToGo(); @@ -2367,11 +2366,12 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine const char* rufus_loc = "rufus.loc"; const char* cmdline_hogger = "rufus.com"; int i, opt, option_index = 0, argc = 0, si = 0, lcid = GetUserDefaultUILanguage(); + FILE* fd; BOOL attached_console = FALSE, external_loc_file = FALSE, lgp_set = FALSE, automount; BYTE *loc_data, *hog_data; DWORD loc_size, hog_size, Size; - char tmp_path[MAX_PATH] = "", loc_file[MAX_PATH] = "", *tmp, *locale_name = NULL; - char** argv = NULL; + char tmp_path[MAX_PATH] = "", loc_file[MAX_PATH] = "", ini_path[MAX_PATH], ini_flags[] = "rb"; + char *tmp, *locale_name = NULL, **argv = NULL; wchar_t **wenv, **wargv; PF_TYPE_DECL(CDECL, int, __wgetmainargs, (int*, wchar_t***, wchar_t***, int, int*)); HANDLE mutex = NULL, hogmutex = NULL, hFile = NULL; @@ -2426,13 +2426,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine } } - // Use the Locale specified in the registry, if any - tmp = ReadRegistryKeyStr(REGKEY_HKCU, REGKEY_LOCALE); - if (tmp[0] != 0) { - locale_name = safe_strdup(tmp); - uprintf("found registry locale '%s'", locale_name); - } - // We have to process the arguments before we acquire the lock and process the locale PF_INIT(__wgetmainargs, Msvcrt); if (pf__wgetmainargs != NULL) { @@ -2445,6 +2438,13 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine wait_for_mutex = 150; // Try to acquire the mutex for 15 seconds } + // If our application name contains a 'p' (for "portable") create a 'rufus.ini' + tmp = &argv[0][strlen(argv[0]) -1]; + while ((((uintptr_t)tmp)>((uintptr_t)argv[0])) && (*tmp != '\\')) + tmp--; + if (strchr(tmp, 'p') != NULL) + ini_flags[0] = 'a'; + while ((opt = getopt_long(argc, argv, "?fhi:w:l:", long_options, &option_index)) != EOF) switch (opt) { case 'f': @@ -2482,6 +2482,22 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine // Retrieve the current application directory GetCurrentDirectoryU(MAX_PATH, app_dir); + // Look for a .ini file in the current app directory + static_sprintf(ini_path, "%s\\rufus.ini", app_dir); + fd = fopenU(ini_path, ini_flags); // Will create the file if portable mode is requested + if (fd != NULL) { + ini_file = ini_path; + fclose(fd); + } + uprintf("Will use settings from %s", (ini_file != NULL)?"INI file":"registry"); + + // Use the locale specified by the settings, if any + tmp = ReadSettingStr(SETTING_LOCALE); + if (tmp[0] != 0) { + locale_name = safe_strdup(tmp); + uprintf("found locale '%s'", locale_name); + } + // Init localization init_localization(); // Seek for a loc file in the current directory @@ -2572,7 +2588,7 @@ relaunch: right_to_left_mode = ((selected_locale->ctrl_id) & LOC_RIGHT_TO_LEFT); SetProcessDefaultLayout(right_to_left_mode?LAYOUT_RTL:0); if (get_loc_data_file(loc_file, selected_locale)) - WriteRegistryKeyStr(REGKEY_HKCU, REGKEY_LOCALE, selected_locale->txt[0]); + WriteSettingStr(SETTING_LOCALE, selected_locale->txt[0]); /* * Create the main Window @@ -2692,7 +2708,7 @@ relaunch: PrintStatus2000(lmprintf(MSG_260), enable_ntfs_compression); continue; } - // Alt-R => Remove all the registry keys created by Rufus + // Alt-R => Remove all the registry keys that may have been created by Rufus if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'R')) { PrintStatus(2000, DeleteRegistryKey(REGKEY_HKCU, COMPANY_NAME "\\" APPLICATION_NAME)?MSG_248:MSG_249); // Also try to delete the upper key (company name) if it's empty (don't care about the result) diff --git a/src/rufus.h b/src/rufus.h index 1841ab60..860e14f6 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -409,6 +409,7 @@ extern BOOL CheckForUpdates(BOOL force); extern void DownloadNewVersion(void); extern BOOL IsShown(HWND hDlg); extern char* get_token_data_file(const char* token, const char* filename); +extern char* set_token_data_file(const char* token, const char* data, const char* filename); extern char* get_token_data_buffer(const char* token, unsigned int n, const char* buffer, size_t buffer_size); extern char* insert_section_data(const char* filename, const char* section, const char* data, BOOL dos2unix); extern char* replace_in_token_data(const char* filename, const char* token, const char* src, const char* rep, BOOL dos2unix); diff --git a/src/rufus.rc b/src/rufus.rc index 765fb8a0..e5eee4e8 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -32,7 +32,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 242, 376 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Rufus 2.0.0.585" +CAPTION "Rufus 2.0.0.586" FONT 8, "Segoe UI", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,127,339,50,14 @@ -157,7 +157,7 @@ END IDD_DIALOG_XP DIALOGEX 12, 12, 242, 376 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Rufus 2.0.0.585" +CAPTION "Rufus 2.0.0.586" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,127,339,50,14 @@ -283,7 +283,7 @@ END IDD_DIALOG_RTL DIALOGEX 12, 12, 242, 376 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL -CAPTION "Rufus 2.0.0.585" +CAPTION "Rufus 2.0.0.586" FONT 8, "Segoe UI", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,127,339,50,14 @@ -415,7 +415,7 @@ END IDD_DIALOG_RTL_XP DIALOGEX 12, 12, 242, 376 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL -CAPTION "Rufus 2.0.0.585" +CAPTION "Rufus 2.0.0.586" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,127,339,50,14 @@ -671,8 +671,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,0,0,585 - PRODUCTVERSION 2,0,0,585 + FILEVERSION 2,0,0,586 + PRODUCTVERSION 2,0,0,586 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -689,13 +689,13 @@ BEGIN BEGIN VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "2.0.0.585" + VALUE "FileVersion", "2.0.0.586" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2015 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "2.0.0.585" + VALUE "ProductVersion", "2.0.0.586" END END BLOCK "VarFileInfo" diff --git a/src/settings.h b/src/settings.h new file mode 100644 index 00000000..e6c46dba --- /dev/null +++ b/src/settings.h @@ -0,0 +1,125 @@ +/* + * Rufus: The Reliable USB Formatting Utility + * Settings access, through either registry or INI file + * Copyright © 2015 Pete Batard + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include +#include "rufus.h" +#include "registry.h" + +#pragma once +extern char* ini_file; + +/* + * List of setting names used by this application + */ +#define SETTING_VERBOSE_UPDATES "VerboseUpdateCheck" +#define SETTING_LAST_UPDATE "LastUpdateCheck" +#define SETTING_UPDATE_INTERVAL "UpdateCheckInterval" +#define SETTING_INCLUDE_BETAS "CheckForBetas" +#define SETTING_COMM_CHECK "CommCheck" +#define SETTING_LOCALE "Locale" +#define SETTING_DISABLE_LGP "DisableLGP" + +static __inline BOOL CheckIniKey(const char* key) { + char* str = get_token_data_file(key, ini_file); + BOOL ret = (str != NULL); + safe_free(str); + return ret; +} +#define CheckIniKey64 CheckIniKey +#define CheckIniKey32 CheckIniKey +#define CheckIniKeyBool CheckIniKey +#define CheckIniKeyStr CheckIniKey + +static __inline int64_t ReadIniKey64(const char* key) { + int64_t val = 0; + char* str = get_token_data_file(key, ini_file); + if (str != NULL) { + val = strtoll(str, NULL, 0); + free(str); + } + return val; +} +static __inline BOOL WriteIniKey64(const char* key, int64_t val) { + char str[24]; + static_sprintf(str, "%lld", val); + return (set_token_data_file(key, str, ini_file) != NULL); +} + +static __inline int32_t ReadIniKey32(const char* key) { + int32_t val = 0; + char* str = get_token_data_file(key, ini_file); + if (str != NULL) { + val = strtol(str, NULL, 0); + free(str); + } + return val; +} +static __inline BOOL WriteIniKey32(const char* key, int32_t val) { + char str[12]; + static_sprintf(str, "%d", val); + return (set_token_data_file(key, str, ini_file) != NULL); +} + +static __inline char* ReadIniKeyStr(const char* key) { + static char str[512]; + char* val; + str[0] = 0; + val = get_token_data_file(key, ini_file); + if (val != NULL) { + safe_strcpy(str, sizeof(str), val); + free(val); + } + return str; +} + +static __inline BOOL WriteIniKeyStr(const char* key, const char* val) { + return (set_token_data_file(key, val, ini_file) != NULL); +} + +/* Helpers for boolean operations */ +#define ReadIniKeyBool(key) (ReadIniKey32(key) != 0) +#define WriteIniKeyBool(key, b) WriteIniKey32(key, (b)?1:0) + +/* + * Read and store settings from/to ini file or registry + */ +static __inline int64_t ReadSetting64(const char* key) { + return (ini_file != NULL)?ReadIniKey64(key):ReadRegistryKey64(REGKEY_HKCU, key); +} +static __inline BOOL WriteSetting64(const char* key, int64_t val) { + return (ini_file != NULL)?WriteIniKey64(key, val):WriteRegistryKey64(REGKEY_HKCU, key, val); +} +static __inline int32_t ReadSetting32(const char* key) { + return (ini_file != NULL)?ReadIniKey32(key):ReadRegistryKey32(REGKEY_HKCU, key); +} +static __inline BOOL WriteSetting32(const char* key, int32_t val) { + return (ini_file != NULL)?WriteIniKey32(key, val):WriteRegistryKey32(REGKEY_HKCU, key, val); +} +static __inline BOOL ReadSettingBool(const char* key) { + return (ini_file != NULL)?ReadIniKeyBool(key):ReadRegistryKeyBool(REGKEY_HKCU, key); +} +static __inline BOOL WriteSettingBool(const char* key, BOOL val) { + return (ini_file != NULL)?WriteIniKeyBool(key, val):WriteRegistryKeyBool(REGKEY_HKCU, key, val); +} +static __inline char* ReadSettingStr(const char* key) { + return (ini_file != NULL)?ReadIniKeyStr(key):ReadRegistryKeyStr(REGKEY_HKCU, key); +} +static __inline BOOL WriteSettingStr(const char* key, char* val) { + return (ini_file != NULL)?WriteIniKeyStr(key, val):WriteRegistryKeyStr(REGKEY_HKCU, key, val); +} diff --git a/src/stdfn.c b/src/stdfn.c index 2458e7fb..2a25c10b 100644 --- a/src/stdfn.c +++ b/src/stdfn.c @@ -27,6 +27,7 @@ #include "msapi_utf8.h" #include "rufus.h" #include "resource.h" +#include "settings.h" #include "localization.h" int nWindowsVersion = WINDOWS_UNDEFINED; diff --git a/src/stdlg.c b/src/stdlg.c index 01cbeb16..48f6a40f 100644 --- a/src/stdlg.c +++ b/src/stdlg.c @@ -37,6 +37,7 @@ #include "rufus.h" #include "msapi_utf8.h" #include "registry.h" +#include "settings.h" #include "resource.h" #include "license.h" #include "localization.h" @@ -58,7 +59,7 @@ static WNDPROC pOrgBrowseWndproc; static const SETTEXTEX friggin_microsoft_unicode_amateurs = {ST_DEFAULT, CP_UTF8}; static BOOL notification_is_question; static const notification_info* notification_more_info; -static BOOL reg_commcheck = FALSE; +static BOOL settings_commcheck = FALSE; static WNDPROC original_wndproc = NULL; /* @@ -518,7 +519,7 @@ INT_PTR CALLBACK AboutCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP apply_localization(IDD_ABOUTBOX, hDlg); SetTitleBarIcon(hDlg); CenterDialog(hDlg); - if (reg_commcheck) + if (settings_commcheck) ShowWindow(GetDlgItem(hDlg, IDC_ABOUT_UPDATES), SW_SHOW); safe_sprintf(about_blurb, sizeof(about_blurb), about_blurb_format, lmprintf(MSG_174), lmprintf(MSG_175, rufus_version[0], rufus_version[1], rufus_version[2], rufus_version[3]), @@ -1021,7 +1022,7 @@ INT_PTR CALLBACK UpdateCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM l IGNORE_RETVAL(ComboBox_SetItemData(hFrequency, ComboBox_AddStringU(hFrequency, lmprintf(MSG_030, lmprintf(MSG_014))), 86400)); IGNORE_RETVAL(ComboBox_SetItemData(hFrequency, ComboBox_AddStringU(hFrequency, lmprintf(MSG_015)), 604800)); IGNORE_RETVAL(ComboBox_SetItemData(hFrequency, ComboBox_AddStringU(hFrequency, lmprintf(MSG_016)), 2629800)); - freq = ReadRegistryKey32(REGKEY_HKCU, REGKEY_UPDATE_INTERVAL); + freq = ReadSetting32(SETTING_UPDATE_INTERVAL); EnableWindow(GetDlgItem(hDlg, IDC_CHECK_NOW), (freq != 0)); EnableWindow(hBeta, (freq >= 0)); switch(freq) { @@ -1045,7 +1046,7 @@ INT_PTR CALLBACK UpdateCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM l } IGNORE_RETVAL(ComboBox_AddStringU(hBeta, lmprintf(MSG_008))); IGNORE_RETVAL(ComboBox_AddStringU(hBeta, lmprintf(MSG_009))); - IGNORE_RETVAL(ComboBox_SetCurSel(hBeta, GetRegistryKeyBool(REGKEY_HKCU, REGKEY_INCLUDE_BETAS)?0:1)); + IGNORE_RETVAL(ComboBox_SetCurSel(hBeta, ReadSettingBool(SETTING_INCLUDE_BETAS)?0:1)); hPolicy = GetDlgItem(hDlg, IDC_POLICY); SendMessage(hPolicy, EM_AUTOURLDETECT, 1, 0); safe_sprintf(update_policy_text, sizeof(update_policy_text), update_policy, lmprintf(MSG_179), @@ -1070,13 +1071,13 @@ INT_PTR CALLBACK UpdateCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM l if (HIWORD(wParam) != CBN_SELCHANGE) break; freq = (int32_t)ComboBox_GetItemData(hFrequency, ComboBox_GetCurSel(hFrequency)); - WriteRegistryKey32(REGKEY_HKCU, REGKEY_UPDATE_INTERVAL, (DWORD)freq); + WriteSetting32(SETTING_UPDATE_INTERVAL, (DWORD)freq); EnableWindow(hBeta, (freq >= 0)); return (INT_PTR)TRUE; case IDC_INCLUDE_BETAS: if (HIWORD(wParam) != CBN_SELCHANGE) break; - SetRegistryKeyBool(REGKEY_HKCU, REGKEY_INCLUDE_BETAS, ComboBox_GetCurSel(hBeta) == 0); + WriteSettingBool(SETTING_INCLUDE_BETAS, ComboBox_GetCurSel(hBeta) == 0); return (INT_PTR)TRUE; } break; @@ -1095,14 +1096,14 @@ BOOL SetUpdateCheck(void) char filename[MAX_PATH] = "", exename[] = APPLICATION_NAME ".exe"; size_t fn_len, exe_len; - // Test if we have access to the registry. If not, forget it. - WriteRegistryKey32(REGKEY_HKCU, REGKEY_COMM_CHECK, commcheck); - if (ReadRegistryKey32(REGKEY_HKCU, REGKEY_COMM_CHECK) != commcheck) + // Test if we can read and write settings. If not, forget it. + WriteSetting32(SETTING_COMM_CHECK, commcheck); + if (ReadSetting32(SETTING_COMM_CHECK) != commcheck) return FALSE; - reg_commcheck = TRUE; + settings_commcheck = TRUE; // If the update interval is not set, this is the first time we run so prompt the user - if (ReadRegistryKey32(REGKEY_HKCU, REGKEY_UPDATE_INTERVAL) == 0) { + if (ReadSetting32(SETTING_UPDATE_INTERVAL) == 0) { // Add a hack for people who'd prefer the app not to prompt about update settings on first run. // If the executable is called "rufus.exe", without version, we disable the prompt @@ -1120,13 +1121,13 @@ BOOL SetUpdateCheck(void) } #endif if (!enable_updates) { - WriteRegistryKey32(REGKEY_HKCU, REGKEY_UPDATE_INTERVAL, -1); + WriteSetting32(SETTING_UPDATE_INTERVAL, -1); return FALSE; } // If the user hasn't set the interval in the dialog, set to default - if ( (ReadRegistryKey32(REGKEY_HKCU, REGKEY_UPDATE_INTERVAL) == 0) || - ((ReadRegistryKey32(REGKEY_HKCU, REGKEY_UPDATE_INTERVAL) == -1) && enable_updates) ) - WriteRegistryKey32(REGKEY_HKCU, REGKEY_UPDATE_INTERVAL, 86400); + if ( (ReadSetting32(SETTING_UPDATE_INTERVAL) == 0) || + ((ReadSetting32(SETTING_UPDATE_INTERVAL) == -1) && enable_updates) ) + WriteSetting32(SETTING_UPDATE_INTERVAL, 86400); } return TRUE; } diff --git a/src/usb.c b/src/usb.c index 10c8874b..7561f1d3 100644 --- a/src/usb.c +++ b/src/usb.c @@ -107,7 +107,7 @@ out: static __inline BOOL IsVHD(const char* buffer) { int i; - // List of the Friendly Names of the VHD devices we know + // List of the Hardware IDs of the VHD devices we know const char* vhd_name[] = { "Arsenal_________Virtual_", "KernSafeVirtual_________",