[net] Check for application update (part 4)

* Also improve Windows version check
This commit is contained in:
Pete Batard 2012-12-02 03:50:08 +00:00
parent 8506e47fd3
commit eed0b78ff0
8 changed files with 165 additions and 102 deletions

View file

@ -85,8 +85,20 @@ const char* additional_copyrights =
"All other references can be found in the source.\\line\n}"; "All other references can be found in the source.\\line\n}";
const char* update_policy = const char* update_policy =
"{\\rtf1\\ansi\n" "{\\rtf1\\ansi{\\fonttbl{\\f0\\fnil\\fcharset0 Tahoma;}{\\f1\\fnil\\fcharset2 Symbol;}}\n"
"Hey sexy mama, Wanna kill all humans?}"; "\\fs16\\b Update Policy\\b0\\line\\line\n"
"If you choose to allow update checks, you agree that the following information may be collected on our server(s):\\par\n"
"\\pard{\\pntext\\f1\\'B7\\tab}{\\*\\pn\\pnlvlblt\\pnf2\\pnindent0{\\pntxtb\\'B7}}\\fi-150\\li220 Your Operating System's architecture and version\\par\n"
"{\\pntext\\f1\\'B7\\tab}The version of the application\\par\n"
"{\\pntext\\f1\\'B7\\tab}Your IP address\\line\\pard\n"
"\\line\n"
"\\b None\\b0 of the data above will be disclosed to third parties.\\line\n"
"However we reserve the right to keep the information collected, for at most a year, \n"
"for the purpose of generating private usage statistics.\\line\n\\line\n"
"\\b Update Process\\b0\\line\\line\n"
APPLICATION_NAME " does not install or run any background services, therefore update checks are only performed when the main application is running. \n"
"Internet access is required when checking for new versions.\n"
"}";
const char* gplv3 = const char* gplv3 =
" GNU GENERAL PUBLIC LICENSE\r\n" " GNU GENERAL PUBLIC LICENSE\r\n"

View file

@ -387,10 +387,11 @@ DWORD WINAPI CheckForUpdatesThread(LPVOID param)
// Sleep(15000); // Sleep(15000);
// verbose = ReadRegistryKey32(REGKEY_VERBOSE_UPDATES); // verbose = ReadRegistryKey32(REGKEY_VERBOSE_UPDATES);
if (GetRegistryKeyBool(REGKEY_DISABLE_UPDATES)) { // TODO: reenable this
vuprintf("Check for updates disabled, as per registry settings.\n"); // if (GetRegistryKeyBool(REGKEY_DISABLE_UPDATES)) {
return FALSE; // vuprintf("Check for updates disabled, as per registry settings.\n");
} // return FALSE;
// }
reg_time = ReadRegistryKey64(REGKEY_LAST_UPDATE); reg_time = ReadRegistryKey64(REGKEY_LAST_UPDATE);
update_interval = (int64_t)ReadRegistryKey32(REGKEY_UPDATE_INTERVAL); update_interval = (int64_t)ReadRegistryKey32(REGKEY_UPDATE_INTERVAL);
if (update_interval == 0) { if (update_interval == 0) {

View file

@ -31,12 +31,13 @@ extern "C" {
* These keys go into HKCU\Software\COMPANY_NAME\APPLICATION_NAME\ * These keys go into HKCU\Software\COMPANY_NAME\APPLICATION_NAME\
*/ */
#define REGKEY_VERBOSE_UPDATES "VerboseUpdateCheck" #define REGKEY_VERBOSE_UPDATES "VerboseUpdateCheck"
#define REGKEY_DISABLE_UPDATES "DisableUpdateCheck"
#define REGKEY_LAST_UPDATE "LastUpdateCheck" #define REGKEY_LAST_UPDATE "LastUpdateCheck"
#define REGKEY_UPDATE_INTERVAL "UpdateCheckInterval" #define REGKEY_UPDATE_INTERVAL "UpdateCheckInterval"
#define REGKEY_LAST_VERSION_SEEN "LastVersionSeen" #define REGKEY_LAST_VERSION_SEEN "LastVersionSeen"
#define REGKEY_INCLUDE_BETAS "CheckForBetas"
#define REGKEY_COMM_CHECK "CommCheck"
/* Delete a registry key from HKCU\Software and all its subkeys /* Delete a registry key from HKCU\Software and all its values
If the key has subkeys, this call will fail. */ If the key has subkeys, this call will fail. */
static __inline BOOL DeleteRegistryKey(const char* key_name) static __inline BOOL DeleteRegistryKey(const char* key_name)
{ {
@ -117,9 +118,9 @@ static __inline int64_t ReadRegistryKey64(const char* key) {
GetRegistryKey64(key, &val); GetRegistryKey64(key, &val);
return (int64_t)val; return (int64_t)val;
} }
static __inline void WriteRegistryKey64(const char* key, int64_t val) { static __inline BOOL WriteRegistryKey64(const char* key, int64_t val) {
LONGLONG tmp = (LONGLONG)val; LONGLONG tmp = (LONGLONG)val;
SetRegistryKey64(key, tmp); return SetRegistryKey64(key, tmp);
} }
/* Helpers for 32 bit registry operations */ /* Helpers for 32 bit registry operations */
@ -134,14 +135,14 @@ static __inline int32_t ReadRegistryKey32(const char* key) {
GetRegistryKey32(key, &val); GetRegistryKey32(key, &val);
return (int32_t)val; return (int32_t)val;
} }
static __inline void WriteRegistryKey32(const char* key, int32_t val) { static __inline BOOL WriteRegistryKey32(const char* key, int32_t val) {
DWORD tmp = (DWORD)val; DWORD tmp = (DWORD)val;
SetRegistryKey32(key, tmp); return SetRegistryKey32(key, tmp);
} }
/* Helpers for boolean registry operations */ /* Helpers for boolean registry operations */
#define GetRegistryKeyBool(key) (ReadRegistryKey32(key) != 0) #define GetRegistryKeyBool(key) (ReadRegistryKey32(key) != 0)
#define SetRegistryKeyBool(key) WriteRegistryKey32(key, 1) #define SetRegistryKeyBool(key, b) WriteRegistryKey32(key, (b)?1:0)
#define CheckRegistryKeyBool CheckRegistryKey32 #define CheckRegistryKeyBool CheckRegistryKey32
/* Helpers for String registry operations */ /* Helpers for String registry operations */

View file

@ -69,6 +69,7 @@
#define IDC_EXTRA_PARTITION 1023 #define IDC_EXTRA_PARTITION 1023
#define IDC_ABOUT_LICENSE 1030 #define IDC_ABOUT_LICENSE 1030
#define IDC_ABOUT_ICON 1031 #define IDC_ABOUT_ICON 1031
#define IDC_ABOUT_UPDATES 1032
#define IDC_ABOUT_COPYRIGHTS 1033 #define IDC_ABOUT_COPYRIGHTS 1033
#define IDC_LICENSE_TEXT 1036 #define IDC_LICENSE_TEXT 1036
#define IDC_NOTIFICATION_ICON 1040 #define IDC_NOTIFICATION_ICON 1040
@ -81,7 +82,7 @@
#define IDC_LOG_SAVE 1051 #define IDC_LOG_SAVE 1051
#define IDC_LOG_CLEAR 1052 #define IDC_LOG_CLEAR 1052
#define IDC_MORE_INFO 1060 #define IDC_MORE_INFO 1060
#define IDC_UPDATES_POLICY 1061 #define IDC_POLICY 1061
#define IDC_UPDATE_FREQUENCY 1062 #define IDC_UPDATE_FREQUENCY 1062
#define IDC_INCLUDE_BETAS 1063 #define IDC_INCLUDE_BETAS 1063
#define IDC_ABOUT_BLURB 1064 #define IDC_ABOUT_BLURB 1064

View file

@ -1496,7 +1496,7 @@ void InitDialog(HWND hDlg)
CreateTooltip(hClusterSize, "Minimum size that each data block occupies", -1); CreateTooltip(hClusterSize, "Minimum size that each data block occupies", -1);
CreateTooltip(hLabel, "Use this field to set the drive label\nInternational characters are accepted", -1); CreateTooltip(hLabel, "Use this field to set the drive label\nInternational characters are accepted", -1);
CreateTooltip(GetDlgItem(hDlg, IDC_ADVANCED), "Toggle advanced options", -1); CreateTooltip(GetDlgItem(hDlg, IDC_ADVANCED), "Toggle advanced options", -1);
CreateTooltip(GetDlgItem(hDlg, IDC_BADBLOCKS), "Test the device for bad blocks using a set byte pattern", -1); CreateTooltip(GetDlgItem(hDlg, IDC_BADBLOCKS), "Test the device for bad blocks using a byte pattern", -1);
CreateTooltip(GetDlgItem(hDlg, IDC_QUICKFORMAT), "Unchek this box to use the \"slow\" format method", -1); CreateTooltip(GetDlgItem(hDlg, IDC_QUICKFORMAT), "Unchek this box to use the \"slow\" format method", -1);
CreateTooltip(hDOS, "Check this box to make the USB drive bootable", -1); CreateTooltip(hDOS, "Check this box to make the USB drive bootable", -1);
CreateTooltip(hDOSType, "Boot method", -1); CreateTooltip(hDOSType, "Boot method", -1);
@ -1528,6 +1528,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
wchar_t wtmp[128], wstr[MAX_PATH]; wchar_t wtmp[128], wstr[MAX_PATH];
static UINT uDOSChecked = BST_CHECKED, uQFChecked; static UINT uDOSChecked = BST_CHECKED, uQFChecked;
static BOOL first_log_display = TRUE, user_changed_label = FALSE; static BOOL first_log_display = TRUE, user_changed_label = FALSE;
notification_info more_info = { IDD_UPDATE_POLICY, UpdateCallback };
switch (message) { switch (message) {
@ -1541,6 +1542,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
break; break;
case WM_INITDIALOG: case WM_INITDIALOG:
SetUpdateCheck();
// Create the log window (hidden) // Create the log window (hidden)
hLogDlg = CreateDialogA(hMainInstance, MAKEINTRESOURCEA(IDD_LOG), hDlg, (DLGPROC)LogProc); hLogDlg = CreateDialogA(hMainInstance, MAKEINTRESOURCEA(IDD_LOG), hDlg, (DLGPROC)LogProc);
InitDialog(hDlg); InitDialog(hDlg);
@ -1627,20 +1629,6 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
break; break;
#ifdef RUFUS_TEST #ifdef RUFUS_TEST
case IDC_TEST: case IDC_TEST:
testme = Notification(MSG_QUESTION, IDD_UPDATE_POLICY, UpdateCallback,
"Rufus updates", "Do you want to allow " APPLICATION_NAME " to check for updates?\n");
uprintf("User said %s\n", testme?"YES":"NO");
// CheckForUpdates();
/*
InitProgress();
if (!IsWindow(hISOProgressDlg)) {
hISOProgressDlg = CreateDialogA(hMainInstance, MAKEINTRESOURCEA(IDD_ISO_EXTRACT),
hDlg, (DLGPROC)ISOProc);
// The window is not visible by default but takes focus => restore it
SetFocus(hDlg);
}
DownloadFile("http://cloud.github.com/downloads/pbatard/rufus/vesamenu.c32", "vesamenu.c32");
*/
break; break;
#endif #endif
case IDC_ADVANCED: case IDC_ADVANCED:
@ -1904,12 +1892,12 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
SendMessage(hProgress, PBM_SETSTATE, (WPARAM)PBST_PAUSED, 0); SendMessage(hProgress, PBM_SETSTATE, (WPARAM)PBST_PAUSED, 0);
SetTaskbarProgressState(TASKBAR_PAUSED); SetTaskbarProgressState(TASKBAR_PAUSED);
PrintStatus(0, FALSE, "Cancelled"); PrintStatus(0, FALSE, "Cancelled");
Notification(MSG_INFO, 0, NULL, "Cancelled", "Operation cancelled by the user."); Notification(MSG_INFO, NULL, "Cancelled", "Operation cancelled by the user.");
} else { } else {
SendMessage(hProgress, PBM_SETSTATE, (WPARAM)PBST_ERROR, 0); SendMessage(hProgress, PBM_SETSTATE, (WPARAM)PBST_ERROR, 0);
SetTaskbarProgressState(TASKBAR_ERROR); SetTaskbarProgressState(TASKBAR_ERROR);
PrintStatus(0, FALSE, "FAILED"); PrintStatus(0, FALSE, "FAILED");
Notification(MSG_ERROR, 0, NULL, "Error", "Error: %s.%s", StrError(FormatStatus), Notification(MSG_ERROR, NULL, "Error", "Error: %s.%s", StrError(FormatStatus),
(strchr(StrError(FormatStatus), '\n') != NULL)?"":"\nFor more information, please check the log."); (strchr(StrError(FormatStatus), '\n') != NULL)?"":"\nFor more information, please check the log.");
} }
return (INT_PTR)TRUE; return (INT_PTR)TRUE;
@ -1944,17 +1932,17 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
// Initialize COM for folder selection // Initialize COM for folder selection
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
// Retrieve the current application directory
GetCurrentDirectoryU(MAX_PATH, app_dir);
// Set the Windows version
DetectWindowsVersion();
// Some dialogs have Rich Edit controls and won't display without this // Some dialogs have Rich Edit controls and won't display without this
if (LoadLibraryA("Riched20.dll") == NULL) { if (LoadLibraryA("Riched20.dll") == NULL) {
uprintf("Could not load RichEdit library - some dialogs may not display: %s\n", WindowsErrorString()); uprintf("Could not load RichEdit library - some dialogs may not display: %s\n", WindowsErrorString());
} }
// Retrieve the current application directory
GetCurrentDirectoryU(MAX_PATH, app_dir);
// Set the Windows version
nWindowsVersion = DetectWindowsVersion();
// We use local group policies rather than direct registry manipulation // We use local group policies rather than direct registry manipulation
// 0x9e disables removable and fixed drive notifications // 0x9e disables removable and fixed drive notifications
SetLGP(FALSE, "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", "NoDriveTypeAutorun", 0x9e); SetLGP(FALSE, "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", "NoDriveTypeAutorun", 0x9e);

View file

@ -24,7 +24,7 @@
/* Program options */ /* Program options */
#define RUFUS_DEBUG // print debug info to Debug facility #define RUFUS_DEBUG // print debug info to Debug facility
/* Features not ready for prime time and that may *DESTROY* your data - USE AT YOUR OWN RISKS! */ /* Features not ready for prime time and that may *DESTROY* your data - USE AT YOUR OWN RISKS! */
#define RUFUS_TEST //#define RUFUS_TEST
#define APPLICATION_NAME "Rufus" #define APPLICATION_NAME "Rufus"
#define COMPANY_NAME "Akeo Consulting" #define COMPANY_NAME "Akeo Consulting"
@ -96,6 +96,10 @@ enum notification_type {
MSG_QUESTION, MSG_QUESTION,
}; };
typedef INT_PTR (CALLBACK *Callback_t)(HWND, UINT, WPARAM, LPARAM); typedef INT_PTR (CALLBACK *Callback_t)(HWND, UINT, WPARAM, LPARAM);
typedef struct {
WORD id;
Callback_t callback;
} notification_info; // To provide a "More info..." on notifications
/* Timers used throughout the program */ /* Timers used throughout the program */
enum timer_type { enum timer_type {
@ -182,12 +186,12 @@ typedef enum TASKBAR_PROGRESS_FLAGS
enum WindowsVersion { enum WindowsVersion {
WINDOWS_UNDEFINED, WINDOWS_UNDEFINED,
WINDOWS_UNSUPPORTED, WINDOWS_UNSUPPORTED,
WINDOWS_2K,
WINDOWS_XP, WINDOWS_XP,
WINDOWS_2003_XP64, WINDOWS_2003,
WINDOWS_VISTA, WINDOWS_VISTA,
WINDOWS_7, WINDOWS_7,
WINDOWS_8 WINDOWS_8,
WINDOWS_9
}; };
/* /*
@ -212,7 +216,7 @@ extern enum WindowsVersion nWindowsVersion;
/* /*
* Shared prototypes * Shared prototypes
*/ */
extern void DetectWindowsVersion(void); extern enum WindowsVersion DetectWindowsVersion(void);
extern const char *WindowsErrorString(void); extern const char *WindowsErrorString(void);
extern void DumpBufferHex(void *buf, size_t size); extern void DumpBufferHex(void *buf, size_t size);
extern void PrintStatus(unsigned int duration, BOOL debug, const char *format, ...); extern void PrintStatus(unsigned int duration, BOOL debug, const char *format, ...);
@ -227,7 +231,7 @@ extern INT_PTR CreateAboutBox(void);
extern BOOL CreateTooltip(HWND hControl, const char* message, int duration); extern BOOL CreateTooltip(HWND hControl, const char* message, int duration);
extern void DestroyTooltip(HWND hWnd); extern void DestroyTooltip(HWND hWnd);
extern void DestroyAllTooltips(void); extern void DestroyAllTooltips(void);
extern BOOL Notification(int type, WORD extra_id, Callback_t extra_callback, char* title, char* format, ...); extern BOOL Notification(int type, const notification_info* more_info, char* title, char* format, ...);
extern BOOL Question(char* title, char* format, ...); extern BOOL Question(char* title, char* format, ...);
extern BOOL ExtractDOS(const char* path); extern BOOL ExtractDOS(const char* path);
extern BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan); extern BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan);
@ -245,6 +249,7 @@ extern BOOL FileIO(BOOL save, char* path, char** buffer, DWORD* size);
extern LONG GetEntryWidth(HWND hDropDown, const char* entry); extern LONG GetEntryWidth(HWND hDropDown, const char* entry);
extern BOOL DownloadFile(const char* url, const char* file); extern BOOL DownloadFile(const char* url, const char* file);
extern INT_PTR CALLBACK UpdateCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); extern INT_PTR CALLBACK UpdateCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
extern BOOL SetUpdateCheck(void);
extern BOOL CheckForUpdates(void); extern BOOL CheckForUpdates(void);
extern BOOL IsShown(HWND hDlg); extern BOOL IsShown(HWND hDlg);
extern char* get_token_data_file(const char* token, const char* filename); extern char* get_token_data_file(const char* token, const char* filename);

View file

@ -30,7 +30,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 206, 316 IDD_DIALOG DIALOGEX 12, 12, 206, 316
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW EXSTYLE WS_EX_APPWINDOW
CAPTION "Rufus v1.2.1.200" CAPTION "Rufus v1.2.1.201"
FONT 8, "MS Shell Dlg", 400, 0, 0x1 FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN BEGIN
DEFPUSHBUTTON "Start",IDC_START,94,278,50,14 DEFPUSHBUTTON "Start",IDC_START,94,278,50,14
@ -73,9 +73,10 @@ FONT 8, "Microsoft Sans Serif", 400, 0, 0x0
BEGIN BEGIN
ICON IDI_ICON,IDC_ABOUT_ICON,11,8,20,20 ICON IDI_ICON,IDC_ABOUT_ICON,11,8,20,20
DEFPUSHBUTTON "OK",IDOK,231,181,50,14,WS_GROUP DEFPUSHBUTTON "OK",IDOK,231,181,50,14,WS_GROUP
PUSHBUTTON "License...",IDC_ABOUT_LICENSE,46,181,50,14,WS_GROUP PUSHBUTTON "License",IDC_ABOUT_LICENSE,46,181,50,14,WS_GROUP
CONTROL "",IDC_ABOUT_COPYRIGHTS,"RichEdit20W",WS_VSCROLL | 0x804,46,101,235,74,WS_EX_STATICEDGE CONTROL "",IDC_ABOUT_COPYRIGHTS,"RichEdit20W",ES_MULTILINE | ES_READONLY | WS_VSCROLL,46,101,235,74,WS_EX_STATICEDGE
CONTROL "",IDC_ABOUT_BLURB,"RichEdit20W",WS_TABSTOP | 0x884,46,7,235,93 CONTROL "",IDC_ABOUT_BLURB,"RichEdit20W",ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | WS_TABSTOP,46,7,235,93
PUSHBUTTON "Updates",IDC_ABOUT_UPDATES,100,181,50,14,NOT WS_VISIBLE | WS_GROUP
END END
IDD_ISO_EXTRACT DIALOGEX 0, 0, 262, 66 IDD_ISO_EXTRACT DIALOGEX 0, 0, 262, 66
@ -117,24 +118,24 @@ BEGIN
CONTROL "",IDC_STATIC,"Static",SS_WHITERECT,0,0,263,38 CONTROL "",IDC_STATIC,"Static",SS_WHITERECT,0,0,263,38
ICON 32516,IDC_NOTIFICATION_ICON,6,6,20,20 ICON 32516,IDC_NOTIFICATION_ICON,6,6,20,20
LTEXT "",IDC_NOTIFICATION_TEXT,35,10,219,20 LTEXT "",IDC_NOTIFICATION_TEXT,35,10,219,20
DEFPUSHBUTTON "No",IDNO,211,44,50,14 DEFPUSHBUTTON "No",IDNO,206,44,50,14
DEFPUSHBUTTON "More info...",IDC_MORE_INFO,8,44,50,14,NOT WS_VISIBLE DEFPUSHBUTTON "More info...",IDC_MORE_INFO,8,44,50,14,NOT WS_VISIBLE
DEFPUSHBUTTON "Yes",IDYES,159,44,50,14,NOT WS_VISIBLE DEFPUSHBUTTON "Yes",IDYES,154,44,50,14,NOT WS_VISIBLE
END END
IDD_UPDATE_POLICY DIALOGEX 0, 0, 287, 195 IDD_UPDATE_POLICY DIALOGEX 0, 0, 287, 198
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Update policy and settings" CAPTION "Update policy and settings"
FONT 8, "Microsoft Sans Serif", 400, 0, 0x0 FONT 8, "Microsoft Sans Serif", 400, 0, 0x0
BEGIN BEGIN
ICON IDI_ICON,IDC_ABOUT_ICON,11,8,20,20 ICON IDI_ICON,IDC_ABOUT_ICON,11,8,21,20
DEFPUSHBUTTON "OK",IDOK,231,166,50,14,WS_GROUP DEFPUSHBUTTON "Close",IDCLOSE,229,176,50,14,WS_GROUP
CONTROL "",IDC_UPDATES_POLICY,"RichEdit20W",ES_MULTILINE | ES_READONLY | WS_VSCROLL,46,8,235,130,WS_EX_STATICEDGE CONTROL "",IDC_POLICY,"RichEdit20W",ES_MULTILINE | ES_READONLY | WS_VSCROLL,46,8,235,130,WS_EX_STATICEDGE
COMBOBOX IDC_UPDATE_FREQUENCY,121,150,66,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_UPDATE_FREQUENCY,145,155,66,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
LTEXT "Check for updates:",IDC_STATIC,52,152,61,11 LTEXT "Check for updates (at most):",IDC_STATIC,52,157,92,11
LTEXT "Include beta versions:",IDC_STATIC,52,168,75,11 LTEXT "Include beta versions:",IDC_STATIC,52,173,93,11
COMBOBOX IDC_INCLUDE_BETAS,151,166,36,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_INCLUDE_BETAS,145,171,36,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
GROUPBOX "Settings",IDC_STATIC,46,140,149,43 GROUPBOX "Settings",IDC_STATIC,46,145,173,45
END END
@ -248,8 +249,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,2,1,200 FILEVERSION 1,2,1,201
PRODUCTVERSION 1,2,1,200 PRODUCTVERSION 1,2,1,201
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -266,13 +267,13 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
VALUE "FileDescription", "Rufus" VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "1.2.1.200" VALUE "FileVersion", "1.2.1.201"
VALUE "InternalName", "Rufus" VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "(c) 2011-2012 Pete Batard (GPL v3)" VALUE "LegalCopyright", "(c) 2011-2012 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
VALUE "OriginalFilename", "rufus.exe" VALUE "OriginalFilename", "rufus.exe"
VALUE "ProductName", "Rufus" VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "1.2.1.200" VALUE "ProductVersion", "1.2.1.201"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -37,6 +37,7 @@
#include "rufus.h" #include "rufus.h"
#include "msapi_utf8.h" #include "msapi_utf8.h"
#include "registry.h"
#include "resource.h" #include "resource.h"
#include "license.h" #include "license.h"
@ -60,41 +61,43 @@ static LPITEMIDLIST (WINAPI *pSHSimpleIDListFromPath)(PCWSTR pszPath) = NULL;
static HICON hMessageIcon = (HICON)INVALID_HANDLE_VALUE; static HICON hMessageIcon = (HICON)INVALID_HANDLE_VALUE;
static char* szMessageText = NULL; static char* szMessageText = NULL;
static char* szMessageTitle = NULL; static char* szMessageTitle = NULL;
enum WindowsVersion nWindowsVersion = WINDOWS_UNSUPPORTED; enum WindowsVersion nWindowsVersion = WINDOWS_UNDEFINED;
static HWND hBrowseEdit; static HWND hBrowseEdit;
static WNDPROC pOrgBrowseWndproc; static WNDPROC pOrgBrowseWndproc;
static const SETTEXTEX friggin_microsoft_unicode_amateurs = {ST_DEFAULT, CP_UTF8}; static const SETTEXTEX friggin_microsoft_unicode_amateurs = {ST_DEFAULT, CP_UTF8};
static BOOL notification_is_question; static BOOL notification_is_question;
static WORD notification_info_id; static const notification_info* notification_more_info;
static Callback_t notification_info_callback; static BOOL reg_commcheck = FALSE;
/* /*
* Detect Windows version * Detect Windows version
*/ */
void DetectWindowsVersion(void) enum WindowsVersion DetectWindowsVersion(void)
{ {
OSVERSIONINFO OSVersion; OSVERSIONINFO OSVersion;
memset(&OSVersion, 0, sizeof(OSVERSIONINFO)); memset(&OSVersion, 0, sizeof(OSVERSIONINFO));
OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); OSVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
nWindowsVersion = WINDOWS_UNSUPPORTED; if (GetVersionEx(&OSVersion) == 0)
if ((GetVersionEx(&OSVersion) != 0) && (OSVersion.dwPlatformId == VER_PLATFORM_WIN32_NT)) { return WINDOWS_UNDEFINED;
if ((OSVersion.dwMajorVersion == 5) && (OSVersion.dwMinorVersion == 0)) { if (OSVersion.dwPlatformId != VER_PLATFORM_WIN32_NT)
nWindowsVersion = WINDOWS_2K; return WINDOWS_UNSUPPORTED;
} else if ((OSVersion.dwMajorVersion == 5) && (OSVersion.dwMinorVersion == 1)) { // See the Remarks section from http://msdn.microsoft.com/en-us/library/windows/desktop/ms724833.aspx
nWindowsVersion = WINDOWS_XP; if ((OSVersion.dwMajorVersion < 5) || ((OSVersion.dwMajorVersion == 5) && (OSVersion.dwMinorVersion == 0)))
} else if ((OSVersion.dwMajorVersion == 5) && (OSVersion.dwMinorVersion == 2)) { return WINDOWS_UNSUPPORTED; // Win2k or earlier
nWindowsVersion = WINDOWS_2003_XP64; if ((OSVersion.dwMajorVersion == 5) && (OSVersion.dwMinorVersion == 1))
} else if (OSVersion.dwMajorVersion == 6) { return WINDOWS_XP;
if (OSVersion.dwBuildNumber < 7000) { if ((OSVersion.dwMajorVersion == 5) && (OSVersion.dwMinorVersion == 2))
nWindowsVersion = WINDOWS_VISTA; return WINDOWS_2003;
} else { if ((OSVersion.dwMajorVersion == 6) && (OSVersion.dwMinorVersion == 0))
nWindowsVersion = WINDOWS_7; return WINDOWS_VISTA;
} if ((OSVersion.dwMajorVersion == 6) && (OSVersion.dwMinorVersion == 1))
} else if (OSVersion.dwMajorVersion >= 8) { return WINDOWS_7;
nWindowsVersion = WINDOWS_8; if ((OSVersion.dwMajorVersion == 6) && (OSVersion.dwMinorVersion == 2))
} return WINDOWS_8;
} if ((OSVersion.dwMajorVersion > 6) || ((OSVersion.dwMajorVersion == 6) && (OSVersion.dwMinorVersion >= 3)))
return WINDOWS_9;
return WINDOWS_UNSUPPORTED;
} }
/* /*
@ -660,6 +663,8 @@ INT_PTR CALLBACK AboutCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP
switch (message) { switch (message) {
case WM_INITDIALOG: case WM_INITDIALOG:
CenterDialog(hDlg); CenterDialog(hDlg);
if (reg_commcheck)
ShowWindow(GetDlgItem(hDlg, IDC_ABOUT_UPDATES), SW_SHOW);
safe_sprintf(about_blurb, sizeof(about_blurb), about_blurb_format, safe_sprintf(about_blurb, sizeof(about_blurb), about_blurb_format,
rufus_version[0], rufus_version[1], rufus_version[2], rufus_version[3]); rufus_version[0], rufus_version[1], rufus_version[2], rufus_version[3]);
for (i=0; i<ARRAYSIZE(hEdit); i++) { for (i=0; i<ARRAYSIZE(hEdit); i++) {
@ -698,6 +703,9 @@ INT_PTR CALLBACK AboutCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP
case IDC_ABOUT_LICENSE: case IDC_ABOUT_LICENSE:
DialogBoxA(hMainInstance, MAKEINTRESOURCEA(IDD_LICENSE), hDlg, LicenseCallback); DialogBoxA(hMainInstance, MAKEINTRESOURCEA(IDD_LICENSE), hDlg, LicenseCallback);
break; break;
case IDC_ABOUT_UPDATES:
DialogBoxA(hMainInstance, MAKEINTRESOURCEA(IDD_UPDATE_POLICY), hDlg, UpdateCallback);
break;
} }
break; break;
} }
@ -740,7 +748,7 @@ INT_PTR CALLBACK NotificationCallback(HWND hDlg, UINT message, WPARAM wParam, LP
} else { } else {
ShowWindow(GetDlgItem(hDlg, IDYES), SW_SHOW); ShowWindow(GetDlgItem(hDlg, IDYES), SW_SHOW);
} }
if (notification_info_callback != NULL) { if ((notification_more_info != NULL) && (notification_more_info->callback != NULL)) {
ShowWindow(GetDlgItem(hDlg, IDC_MORE_INFO), SW_SHOW); ShowWindow(GetDlgItem(hDlg, IDC_MORE_INFO), SW_SHOW);
} }
// Set the control text // Set the control text
@ -773,7 +781,9 @@ INT_PTR CALLBACK NotificationCallback(HWND hDlg, UINT message, WPARAM wParam, LP
EndDialog(hDlg, LOWORD(wParam)); EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE; return (INT_PTR)TRUE;
case IDC_MORE_INFO: case IDC_MORE_INFO:
DialogBoxA(hMainInstance, MAKEINTRESOURCEA(notification_info_id), hDlg, notification_info_callback); if (notification_more_info != NULL)
DialogBoxA(hMainInstance, MAKEINTRESOURCEA(notification_more_info->id),
hDlg, notification_more_info->callback);
break; break;
} }
break; break;
@ -784,7 +794,7 @@ INT_PTR CALLBACK NotificationCallback(HWND hDlg, UINT message, WPARAM wParam, LP
/* /*
* Display a custom notification * Display a custom notification
*/ */
BOOL Notification(int type, WORD extra_id, Callback_t extra_callback, char* title, char* format, ...) BOOL Notification(int type, const notification_info* more_info, char* title, char* format, ...)
{ {
BOOL ret; BOOL ret;
va_list args; va_list args;
@ -795,8 +805,7 @@ BOOL Notification(int type, WORD extra_id, Callback_t extra_callback, char* titl
safe_vsnprintf(szMessageText, MAX_PATH-1, format, args); safe_vsnprintf(szMessageText, MAX_PATH-1, format, args);
va_end(args); va_end(args);
szMessageText[MAX_PATH-1] = 0; szMessageText[MAX_PATH-1] = 0;
notification_info_callback = extra_callback; notification_more_info = more_info;
notification_info_id = extra_id;
notification_is_question = FALSE; notification_is_question = FALSE;
switch(type) { switch(type) {
@ -1104,22 +1113,24 @@ BOOL SetTaskbarProgressValue(ULONGLONG ullCompleted, ULONGLONG ullTotal)
*/ */
INT_PTR CALLBACK UpdateCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) INT_PTR CALLBACK UpdateCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{ {
HWND hPolicy, hCombo; HWND hPolicy;
static HWND hFrequency, hBeta;
DWORD frequency = -1;
switch (message) { switch (message) {
case WM_INITDIALOG: case WM_INITDIALOG:
CenterDialog(hDlg); CenterDialog(hDlg);
hCombo = GetDlgItem(hDlg, IDC_UPDATE_FREQUENCY); hFrequency = GetDlgItem(hDlg, IDC_UPDATE_FREQUENCY);
IGNORE_RETVAL(ComboBox_SetItemData(hCombo, ComboBox_AddStringU(hCombo, "Disabled"), -1)); IGNORE_RETVAL(ComboBox_SetItemData(hFrequency, ComboBox_AddStringU(hFrequency, "Disabled"), -1));
IGNORE_RETVAL(ComboBox_SetItemData(hCombo, ComboBox_AddStringU(hCombo, "Daily (Default)"), 86400)); IGNORE_RETVAL(ComboBox_SetItemData(hFrequency, ComboBox_AddStringU(hFrequency, "Daily (Default)"), 86400));
IGNORE_RETVAL(ComboBox_SetItemData(hCombo, ComboBox_AddStringU(hCombo, "Weekly"), 604800)); IGNORE_RETVAL(ComboBox_SetItemData(hFrequency, ComboBox_AddStringU(hFrequency, "Weekly"), 604800));
IGNORE_RETVAL(ComboBox_SetItemData(hCombo, ComboBox_AddStringU(hCombo, "Monthly"), 2629800)); IGNORE_RETVAL(ComboBox_SetItemData(hFrequency, ComboBox_AddStringU(hFrequency, "Monthly"), 2629800));
IGNORE_RETVAL(ComboBox_SetCurSel(hCombo, 1)); IGNORE_RETVAL(ComboBox_SetCurSel(hFrequency, 1));
hCombo = GetDlgItem(hDlg, IDC_INCLUDE_BETAS); hBeta = GetDlgItem(hDlg, IDC_INCLUDE_BETAS);
IGNORE_RETVAL(ComboBox_AddStringU(hCombo, "No")); IGNORE_RETVAL(ComboBox_AddStringU(hBeta, "Yes"));
IGNORE_RETVAL(ComboBox_AddStringU(hCombo, "Yes")); IGNORE_RETVAL(ComboBox_AddStringU(hBeta, "No"));
IGNORE_RETVAL(ComboBox_SetCurSel(hCombo, 0)); IGNORE_RETVAL(ComboBox_SetCurSel(hBeta, 1));
hPolicy = GetDlgItem(hDlg, IDC_UPDATES_POLICY); hPolicy = GetDlgItem(hDlg, IDC_POLICY);
SendMessage(hPolicy, EM_AUTOURLDETECT, 1, 0); SendMessage(hPolicy, EM_AUTOURLDETECT, 1, 0);
SendMessageA(hPolicy, EM_SETTEXTEX, (WPARAM)&friggin_microsoft_unicode_amateurs, (LPARAM)update_policy); SendMessageA(hPolicy, EM_SETTEXTEX, (WPARAM)&friggin_microsoft_unicode_amateurs, (LPARAM)update_policy);
SendMessage(hPolicy, EM_SETSEL, -1, -1); SendMessage(hPolicy, EM_SETSEL, -1, -1);
@ -1128,12 +1139,55 @@ INT_PTR CALLBACK UpdateCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM l
break; break;
case WM_COMMAND: case WM_COMMAND:
switch (LOWORD(wParam)) { switch (LOWORD(wParam)) {
case IDOK: case IDCLOSE:
case IDCANCEL: case IDCANCEL:
EndDialog(hDlg, LOWORD(wParam)); EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE; return (INT_PTR)TRUE;
case IDC_UPDATE_FREQUENCY:
if (HIWORD(wParam) != CBN_SELCHANGE)
break;
WriteRegistryKey32(REGKEY_UPDATE_INTERVAL, (DWORD)ComboBox_GetItemData(hFrequency, ComboBox_GetCurSel(hFrequency)));
return (INT_PTR)TRUE;
case IDC_INCLUDE_BETAS:
if (HIWORD(wParam) != CBN_SELCHANGE)
break;
SetRegistryKeyBool(REGKEY_INCLUDE_BETAS, ComboBox_GetCurSel(hBeta) == 0);
return (INT_PTR)TRUE;
} }
break; break;
} }
return (INT_PTR)FALSE; return (INT_PTR)FALSE;
} }
/*
* Initial update check setup
*/
BOOL SetUpdateCheck(void)
{
BOOL enable_updates;
DWORD commcheck = GetTickCount();
notification_info more_info = { IDD_UPDATE_POLICY, UpdateCallback };
// Test if we have access to the registry. If not, forget it.
WriteRegistryKey32(REGKEY_COMM_CHECK, commcheck);
if (ReadRegistryKey32(REGKEY_COMM_CHECK) != commcheck)
return FALSE;
reg_commcheck = TRUE;
// If the update interval is not set, this is the first time we run so prompt the user
if (ReadRegistryKey32(REGKEY_UPDATE_INTERVAL) == 0) {
enable_updates = Notification(MSG_QUESTION, &more_info,
APPLICATION_NAME " updates", "Do you want to allow " APPLICATION_NAME " to check for updates?\n");
if (!enable_updates) {
WriteRegistryKey32(REGKEY_UPDATE_INTERVAL, -1); // large enough
return FALSE;
}
// If the user hasn't set the interval in the dialog, set to default
if ( (ReadRegistryKey32(REGKEY_UPDATE_INTERVAL) == 0) ||
((ReadRegistryKey32(REGKEY_UPDATE_INTERVAL) == -1) && enable_updates) )
WriteRegistryKey32(REGKEY_UPDATE_INTERVAL, 86400);
}
// TODO: check for lastcheck + interval & launch the background thread here?
// TODO: make sure we check for updates if user just accepted
return TRUE;
}