diff --git a/src/net.c b/src/net.c index f6ccd03a..c2fdef8b 100644 --- a/src/net.c +++ b/src/net.c @@ -42,7 +42,8 @@ /* Globals */ -DWORD error_code; +static DWORD error_code; +static BOOL update_check_in_progress = FALSE; /* MinGW is missing some of those */ #if !defined(ERROR_INTERNET_DISCONNECTED) @@ -232,9 +233,13 @@ const char* WinInetErrorString(void) /* * Download a file from an URL * Mostly taken from http://support.microsoft.com/kb/234913 + * If hProgressDialog is not NULL, this function will send INIT and EXIT messages + * to the dialog in question, with WPARAM being set to nonzero for EXIT on success + * and also attempt to indicate progress using an IDC_PROGRESS control */ -BOOL DownloadFile(const char* url, const char* file, HWND hProgressDialog, HWND hProgressBar) +BOOL DownloadFile(const char* url, const char* file, HWND hProgressDialog) { + HWND hProgressBar = NULL; BOOL r = FALSE; DWORD dwFlags, dwSize, dwDownloaded, dwTotalSize, dwStatus; FILE* fd = NULL; @@ -246,16 +251,16 @@ BOOL DownloadFile(const char* url, const char* file, HWND hProgressDialog, HWND hostname, sizeof(hostname), 0, NULL, 1, urlpath, sizeof(urlpath), NULL, 1}; int i; - // We reuse the ISO progress dialog for download progress - if (hProgressDialog != NULL) - SetWindowTextU(hProgressDialog, "Downloading file..."); - if (hProgressBar != NULL) { - progress_style = GetWindowLong(hProgressBar, GWL_STYLE); - SetWindowLong(hProgressBar, GWL_STYLE, progress_style & (~PBS_MARQUEE)); - SendMessage(hProgressBar, PBM_SETPOS, 0, 0); - } - if (hProgressDialog != NULL) + if (hProgressDialog != NULL) { + // Use the progress control provided, if any + hProgressBar = GetDlgItem(hProgressDialog, IDC_PROGRESS); + if (hProgressBar != NULL) { + progress_style = GetWindowLong(hProgressBar, GWL_STYLE); + SetWindowLong(hProgressBar, GWL_STYLE, progress_style & (~PBS_MARQUEE)); + SendMessage(hProgressBar, PBM_SETPOS, 0, 0); + } SendMessage(hProgressDialog, UM_ISO_INIT, 0, 0); + } PrintStatus(0, FALSE, "Downloading %s: Connecting...\n", file); uprintf("Downloading %s from %s\n", file, url); @@ -333,7 +338,7 @@ BOOL DownloadFile(const char* url, const char* file, HWND hProgressDialog, HWND break; dwSize += dwDownloaded; SendMessage(hProgressBar, PBM_SETPOS, (WPARAM)(MAX_PROGRESS*((1.0f*dwSize)/(1.0f*dwTotalSize))), 0); - PrintStatus(0, FALSE, "Downloading %s: %0.1f%%\n", file, (100.0f*dwSize)/(1.0f*dwTotalSize)); + PrintStatus(0, FALSE, "Downloading: %0.1f%%\n", (100.0f*dwSize)/(1.0f*dwTotalSize)); if (fwrite(buf, 1, dwDownloaded, fd) != dwDownloaded) { uprintf("Error writing file %s: %s\n", file, WinInetErrorString()); goto out; @@ -351,7 +356,7 @@ BOOL DownloadFile(const char* url, const char* file, HWND hProgressDialog, HWND out: if (hProgressDialog != NULL) - SendMessage(hProgressDialog, UM_ISO_EXIT, 0, 0); + SendMessage(hProgressDialog, UM_ISO_EXIT, (WPARAM)r, 0); if (fd != NULL) fclose(fd); if (!r) { _unlink(file); @@ -367,9 +372,29 @@ out: return r; } -// TODO: check that no format operation is occurring -DWORD WINAPI CheckForUpdatesThread(LPVOID param) +/* Threaded download */ +static const char *_url, *_file; +static HWND _hProgressDialog; +static DWORD WINAPI _DownloadFileThread(LPVOID param) { + ExitThread(DownloadFile(_url, _file, _hProgressDialog)); +} + +HANDLE DownloadFileThreaded(const char* url, const char* file, HWND hProgressDialog) +{ + _url = url; + _file = file; + _hProgressDialog = hProgressDialog; + return CreateThread(NULL, 0, _DownloadFileThread, NULL, 0, NULL); +} + + +/* + * Background thread to check for updates + */ +static DWORD WINAPI CheckForUpdatesThread(LPVOID param) +{ + BOOL force = (BOOL)param; const char* server_url = RUFUS_URL "/"; int i, j, verbose = 2, verpos[4]; static char* archname[] = {"win_x86", "win_x64"}; @@ -382,35 +407,38 @@ DWORD WINAPI CheckForUpdatesThread(LPVOID param) hostname, sizeof(hostname), 0, NULL, 1, urlpath, sizeof(urlpath), NULL, 1}; SYSTEMTIME ServerTime, LocalTime; FILETIME FileTime; - int64_t local_time, reg_time, server_time, update_interval; + int64_t local_time = 0, reg_time, server_time, update_interval; BOOL is_x64 = FALSE, (__stdcall *pIsWow64Process)(HANDLE, PBOOL) = NULL; - // Wait a while before checking for updates - // TODO: Also check on inactivity - do { - Sleep(10000); - } while (iso_op_in_progress || format_op_in_progress); + update_check_in_progress = TRUE; + if (!force) { + // Wait a while before checking for updates + // TODO: Also check on inactivity + do { + Sleep(10000); + } while (iso_op_in_progress || format_op_in_progress); - // TODO: reenable this - // verbose = ReadRegistryKey32(REGKEY_VERBOSE_UPDATES); - if ((ReadRegistryKey32(REGKEY_UPDATE_INTERVAL) == -1)) { - vuprintf("Check for updates disabled, as per registry settings.\n"); - goto out; - } - reg_time = ReadRegistryKey64(REGKEY_LAST_UPDATE); - update_interval = (int64_t)ReadRegistryKey32(REGKEY_UPDATE_INTERVAL); - if (update_interval == 0) { - WriteRegistryKey32(REGKEY_UPDATE_INTERVAL, DEFAULT_UPDATE_INTERVAL); - update_interval = DEFAULT_UPDATE_INTERVAL; - } - GetSystemTime(&LocalTime); - if (!SystemTimeToFileTime(&LocalTime, &FileTime)) - goto out; - local_time = ((((int64_t)FileTime.dwHighDateTime)<<32) + FileTime.dwLowDateTime) / 10000000; - vvuprintf("Local time: %" PRId64 "\n", local_time); - if (local_time < reg_time + update_interval) { - vuprintf("Next update check in %" PRId64 " seconds.\n", reg_time + update_interval - local_time); - goto out; + // TODO: reenable this + // verbose = ReadRegistryKey32(REGKEY_VERBOSE_UPDATES); + if ((ReadRegistryKey32(REGKEY_UPDATE_INTERVAL) == -1)) { + vuprintf("Check for updates disabled, as per registry settings.\n"); + goto out; + } + reg_time = ReadRegistryKey64(REGKEY_LAST_UPDATE); + update_interval = (int64_t)ReadRegistryKey32(REGKEY_UPDATE_INTERVAL); + if (update_interval == 0) { + WriteRegistryKey32(REGKEY_UPDATE_INTERVAL, DEFAULT_UPDATE_INTERVAL); + update_interval = DEFAULT_UPDATE_INTERVAL; + } + GetSystemTime(&LocalTime); + if (!SystemTimeToFileTime(&LocalTime, &FileTime)) + goto out; + local_time = ((((int64_t)FileTime.dwHighDateTime)<<32) + FileTime.dwLowDateTime) / 10000000; + vvuprintf("Local time: %" PRId64 "\n", local_time); + if (local_time < reg_time + update_interval) { + vuprintf("Next update check in %" PRId64 " seconds.\n", reg_time + update_interval - local_time); + goto out; + } } PrintStatus(3000, FALSE, "Checking for " APPLICATION_NAME " updates...\n"); @@ -505,11 +533,13 @@ DWORD WINAPI CheckForUpdatesThread(LPVOID param) // Always store the server response time - the only clock we trust! WriteRegistryKey64(REGKEY_LAST_UPDATE, server_time); // Might as well let the user know - if (local_time > server_time + 600) { - uprintf("Your local clock appears more than 10 minutes early - You ought to fix that...\n"); - } - if (local_time < server_time - 600) { - uprintf("Your local clock appears more than 10 minutes late - you ought to fix that...\n"); + if (!force) { + if (local_time > server_time + 600) { + uprintf("Your local clock appears more than 10 minutes early - You ought to fix that...\n"); + } + if (local_time < server_time - 600) { + uprintf("Your local clock appears more than 10 minutes late - you ought to fix that...\n"); + } } dwSize = sizeof(dwTotalSize); @@ -532,13 +562,18 @@ out: if (hRequest) InternetCloseHandle(hRequest); if (hConnection) InternetCloseHandle(hConnection); if (hSession) InternetCloseHandle(hSession); - + update_check_in_progress = FALSE; ExitThread(0); } -BOOL CheckForUpdates(void) +/* + * Initiate a check for updates. If force is true, ignore the wait period + */ +BOOL CheckForUpdates(BOOL force) { - if (CreateThread(NULL, 0, CheckForUpdatesThread, NULL, 0, 0) == NULL) { + if (update_check_in_progress) + return FALSE; + if (CreateThread(NULL, 0, CheckForUpdatesThread, (LPVOID)force, 0, NULL) == NULL) { uprintf("Unable to start check for updates thread"); return FALSE; } diff --git a/src/resource.h b/src/resource.h index f1d651db..b367991a 100644 --- a/src/resource.h +++ b/src/resource.h @@ -63,7 +63,6 @@ #define IDC_SELECT_ISO 1016 #define IDC_SET_ICON 1017 #define IDC_RUFUS_MBR 1018 -#define IDC_ISO_PROGRESS 1019 #define IDC_ISO_FILENAME 1020 #define IDC_ISO_ABORT 1021 #define IDC_DISK_ID 1022 @@ -89,7 +88,6 @@ #define IDC_INCLUDE_BETAS 1063 #define IDC_RELEASE_NOTES 1064 #define IDC_DOWNLOAD 1065 -#define IDC_UPDATE_PROGRESS 1066 #define IDC_WEBSITE 1067 #define IDC_YOUR_VERSION 1068 #define IDC_LATEST_VERSION 1069 diff --git a/src/rufus.c b/src/rufus.c index ff52c762..70629a20 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -1199,7 +1199,7 @@ BOOL CALLBACK ISOProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: - hISOProgressBar = GetDlgItem(hDlg, IDC_ISO_PROGRESS); + hISOProgressBar = GetDlgItem(hDlg, IDC_PROGRESS); hISOFileName = GetDlgItem(hDlg, IDC_ISO_FILENAME); // Use maximum granularity for the progress bar SendMessage(hISOProgressBar, PBM_SETRANGE, 0, MAX_PROGRESS<<16); @@ -1283,8 +1283,9 @@ DWORD WINAPI ISOScanThread(LPVOID param) "Note: the file will be downloaded in the current directory. Once a\n" "vesamenu.c32 exists there, it will always be used as replacement.\n", "Replace vesamenu.c32?", MB_YESNO|MB_ICONWARNING) == IDYES) { + SetWindowTextU(hISOProgressDlg, "Downloading file..."); SetWindowTextU(hISOFileName, VESAMENU_URL); - if (DownloadFile(VESAMENU_URL, vesamenu_filename, hISOProgressDlg, hISOProgressBar)) + if (DownloadFile(VESAMENU_URL, vesamenu_filename, hISOProgressDlg)) use_own_vesamenu = TRUE; } } @@ -1550,7 +1551,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA hLogDlg = CreateDialogA(hMainInstance, MAKEINTRESOURCEA(IDD_LOG), hDlg, (DLGPROC)LogProc); InitDialog(hDlg); GetUSBDevices(0); - CheckForUpdates(); + CheckForUpdates(FALSE); PostMessage(hMainDialog, UM_ISO_CREATE, 0, 0); return (INT_PTR)TRUE; @@ -1774,7 +1775,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA selection_default = DT_ISO; CreateTooltip(hSelectISO, iso_path, -1); FormatStatus = 0; - if (CreateThread(NULL, 0, ISOScanThread, NULL, 0, 0) == NULL) { + if (CreateThread(NULL, 0, ISOScanThread, NULL, 0, NULL) == NULL) { uprintf("Unable to start ISO scanning thread"); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_START_THREAD); } @@ -1915,18 +1916,43 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA /* * Application Entrypoint */ +// If we ever need to process more than one commandline arguments, uncomment the following parts +// typedef int (CDECL *__wgetmainargs_t)(int*, wchar_t***, wchar_t***, int, int*); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { +// int i, argc = 0, si = 0; +// char** argv = NULL; +// wchar_t **wenv, **wargv; +// PF_DECL(__wgetmainargs); HANDLE mutex = NULL; HWND hDlg = NULL; MSG msg; + int wait_for_mutex = 0; uprintf("*** RUFUS INIT ***\n"); - // Prevent 2 applications from running at the same time +// PF_INIT(__wgetmainargs, msvcrt); +// if (pf__wgetmainargs != NULL) { +// pf__wgetmainargs(&argc, &wargv, &wenv, 1, &si); +// argv = (char**)calloc(argc, sizeof(char*)); +// for (i=0; i0) && (mutex != NULL) && (GetLastError() == ERROR_ALREADY_EXISTS); wait_for_mutex--) { + CloseHandle(mutex); + Sleep(100); + mutex = CreateMutexA(NULL, TRUE, "Global/RUFUS"); + } + if ((mutex == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS)) { MessageBoxA(NULL, "Another Rufus application is running.\n" "Please close the first application before running another one.", "Other instance detected", MB_ICONSTOP); @@ -2009,6 +2035,11 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine DeleteRegistryKey(COMPANY_NAME); continue; } + // Alt-U => Force an update check + if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'U')) { + CheckForUpdates(TRUE); + continue; + } TranslateMessage(&msg); DispatchMessage(&msg); } diff --git a/src/rufus.h b/src/rufus.h index e503a5e7..8f753910 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -262,10 +262,11 @@ extern BOOL SetAutorun(const char* path); extern char* FileDialog(BOOL save, char* path, char* filename, char* ext, char* ext_desc); extern BOOL FileIO(BOOL save, char* path, char** buffer, DWORD* size); extern LONG GetEntryWidth(HWND hDropDown, const char* entry); -extern BOOL DownloadFile(const char* url, const char* file, HWND hProgressDialog, HWND hProgressBar); +extern BOOL DownloadFile(const char* url, const char* file, HWND hProgressDialog); +extern HANDLE DownloadFileThreaded(const char* url, const char* file, HWND hProgressDialog); extern INT_PTR CALLBACK UpdateCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); extern BOOL SetUpdateCheck(void); -extern BOOL CheckForUpdates(void); +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); diff --git a/src/rufus.rc b/src/rufus.rc index 781cefff..38b96d09 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -30,7 +30,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 206, 316 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW -CAPTION "Rufus v1.2.1.203" +CAPTION "Rufus v1.2.1.204" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,94,278,50,14 @@ -85,7 +85,7 @@ CAPTION "Copying ISO files..." FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN LTEXT "Opening ISO image - please wait...",IDC_ISO_FILENAME,8,10,246,13,SS_PATHELLIPSIS - CONTROL "",IDC_ISO_PROGRESS,"msctls_progress32",WS_BORDER,7,26,247,8 + CONTROL "",IDC_PROGRESS,"msctls_progress32",WS_BORDER,7,26,247,8 PUSHBUTTON "Cancel",IDC_ISO_ABORT,111,43,50,14 END @@ -146,7 +146,7 @@ BEGIN PUSHBUTTON "Close",IDCANCEL,167,244,50,14,WS_GROUP CONTROL "",IDC_RELEASE_NOTES,"RichEdit20W",ES_MULTILINE | ES_READONLY | WS_VSCROLL,15,77,352,88,WS_EX_STATICEDGE DEFPUSHBUTTON "Download",IDC_DOWNLOAD,293,211,74,14,WS_GROUP - CONTROL "",IDC_UPDATE_PROGRESS,"msctls_progress32",WS_BORDER,15,212,270,11 + CONTROL "",IDC_PROGRESS,"msctls_progress32",WS_BORDER,15,212,270,11 GROUPBOX "Release Notes",IDC_STATIC,8,63,367,111 LTEXT "A newer version is available. Please download the latest version!",IDC_STATIC,10,32,229,8 LTEXT "[...]",IDC_YOUR_VERSION,10,8,124,8 @@ -272,8 +272,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,2,1,203 - PRODUCTVERSION 1,2,1,203 + FILEVERSION 1,2,1,204 + PRODUCTVERSION 1,2,1,204 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -290,13 +290,13 @@ BEGIN BEGIN VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "1.2.1.203" + VALUE "FileVersion", "1.2.1.204" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "(c) 2011-2012 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "1.2.1.203" + VALUE "ProductVersion", "1.2.1.204" END END BLOCK "VarFileInfo" diff --git a/src/stdlg.c b/src/stdlg.c index b4cf45d8..3673f2d2 100644 --- a/src/stdlg.c +++ b/src/stdlg.c @@ -1189,8 +1189,6 @@ BOOL SetUpdateCheck(void) ((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; } @@ -1205,11 +1203,14 @@ INT_PTR CALLBACK NewVersionCallback(HWND hDlg, UINT message, WPARAM wParam, LPAR ENLINK* enl; wchar_t wUrl[256]; char tmp[128]; - char* filepath; - static BOOL was_downloaded = FALSE; + static char* filepath = NULL; + static int download_status = 0; + STARTUPINFOA si; + PROCESS_INFORMATION pi; switch (message) { case WM_INITDIALOG: + download_status = 0; SetTitleBarIcon(hDlg); CenterDialog(hDlg); hNotes = GetDlgItem(hDlg, IDC_RELEASE_NOTES); @@ -1224,7 +1225,9 @@ INT_PTR CALLBACK NewVersionCallback(HWND hDlg, UINT message, WPARAM wParam, LPAR update.version[0], update.version[1], update.version[2], update.version[3]); SetWindowTextA(GetDlgItem(hDlg, IDC_LATEST_VERSION), tmp); SetWindowTextA(GetDlgItem(hDlg, IDC_DOWNLOAD_URL), update.download_url); - SendMessage(GetDlgItem(hDlg, IDC_UPDATE_PROGRESS), PBM_SETRANGE, 0, MAX_PROGRESS<<16); + SendMessage(GetDlgItem(hDlg, IDC_PROGRESS), PBM_SETRANGE, 0, MAX_PROGRESS<<16); + if (update.download_url == NULL) + EnableWindow(GetDlgItem(hDlg, IDC_DOWNLOAD), FALSE); break; case WM_NOTIFY: switch (((LPNMHDR)lParam)->code) { @@ -1250,24 +1253,55 @@ INT_PTR CALLBACK NewVersionCallback(HWND hDlg, UINT message, WPARAM wParam, LPAR switch (LOWORD(wParam)) { case IDCLOSE: case IDCANCEL: + safe_free(filepath); EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; - case IDC_DOWNLOAD: - if (update.download_url == NULL) - return (INT_PTR)TRUE; - for (i=(int)safe_strlen(update.download_url); (i>0)&&(update.download_url[i]!='/'); i--); - filepath = FileDialog(TRUE, app_dir, (char*)&update.download_url[i+1], "exe", "Application"); - if (filepath != NULL) { - if (DownloadFile(update.download_url, filepath, NULL, GetDlgItem(hDlg, IDC_UPDATE_PROGRESS))) { - // TODO: create a thread and allow aborts + invoke a launcher when successful - SetWindowTextA(GetDlgItem(hDlg, IDC_DOWNLOAD), "Done"); - EnableWindow(GetDlgItem(hDlg, IDC_DOWNLOAD), FALSE); + case IDC_DOWNLOAD: // Also doubles as abort and laucnh function + switch(download_status) { + case 1: // Abort + FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANCELLED; + break; + case 2: // Launch newer version and close this one + for (i=(int)safe_strlen(filepath); (i>0)&&(filepath[i]!='\\'); i--); + safe_strcpy(tmp, sizeof(tmp), &filepath[i+1]); + safe_strcat(tmp, sizeof(tmp), " /W"); + filepath[i] = 0; + memset(&si, 0, sizeof(si)); + memset(&pi, 0, sizeof(pi)); + si.cb = sizeof(si); + if (!CreateProcessU(NULL, tmp, NULL, NULL, FALSE, 0, NULL, filepath, &si, &pi)) { + PrintStatus(0, FALSE, "Failed to launch new application"); + uprintf("Failed to launch new application: %s\n", WindowsErrorString()); + } else { + PrintStatus(0, FALSE, "Launching new application..."); + PostMessage(hDlg, WM_COMMAND, (WPARAM)IDCLOSE, 0); + PostMessage(hMainDialog, WM_CLOSE, 0, 0); } - safe_free(filepath); + break; + default: // Download + for (i=(int)safe_strlen(update.download_url); (i>0)&&(update.download_url[i]!='/'); i--); + filepath = FileDialog(TRUE, app_dir, (char*)&update.download_url[i+1], "exe", "Application"); + if (filepath != NULL) + DownloadFileThreaded(update.download_url, filepath, hDlg); + break; } return (INT_PTR)TRUE; } break; + case UM_ISO_INIT: + FormatStatus = 0; + download_status = 1; + SetWindowTextA(GetDlgItem(hDlg, IDC_DOWNLOAD), "Abort"); + return (INT_PTR)TRUE; + case UM_ISO_EXIT: + if (wParam) { + SetWindowTextA(GetDlgItem(hDlg, IDC_DOWNLOAD), "Launch"); + download_status = 2; + } else { + SetWindowTextA(GetDlgItem(hDlg, IDC_DOWNLOAD), "Download"); + download_status = 0; + } + return (INT_PTR)TRUE; } return (INT_PTR)FALSE; }