diff --git a/res/loc/ChangeLog.txt b/res/loc/ChangeLog.txt index acd9470f..8618735a 100644 --- a/res/loc/ChangeLog.txt +++ b/res/loc/ChangeLog.txt @@ -4,7 +4,7 @@ rufus.loc since its original version. To edit a translation, please make sure to follow: https://github.com/pbatard/rufus/wiki/Localization#Editing_a_translation Or simply download the latest pollock.exe from https://rufus.ie/locale/ and follow -its directions. +its directions. o v3.5 - *NEW* MSG_127 "Do not show this message again" @@ -15,6 +15,18 @@ o v3.5 - *NEW* MSG_132 "Another program or process is accessing this drive. Do you want to format it anyway?" - *NEW* MSG_133 "Rufus has detected that you are attempting to create a Windows To Go media based on a 1809 ISO. (...)" - *NEW* MSG_134 "Because MBR has been selected for the partition scheme, Rufus can only create a partition up to 2 TB (...)" + - *NEW* MSG_135 "Version" + - *NEW* MSG_136 "Release" + - *NEW* MSG_137 "Edition" + - *NEW* MSG_138 "Language" + - *NEW* MSG_139 "Architecture" + - *NEW* MSG_140 "Confirm" + - *NEW* MSG_141 "Back" + - *NEW* MSG_142 "Please wait..." + - *NEW* MSG_143 "Download ISO Image" + - *NEW* MSG_144 "Download using a browser" + - *NEW* MSG_149 "Running download script..." + - *UPDATED* MSG_165 o v3.2 (2018.07.20) The following appears in Advanced format options → Check device for bad blocks → dropdown menu with @@ -54,7 +66,7 @@ o v3.0 (2018.03.27) - *NEW* IDS_STATUS_TXT "Status" - *REPLACED* MSG_031 -> "BIOS (or UEFI-CSM)" - *REPLACED* MSG_032 -> "UEFI (non CSM)" - - *REPLACED* MSG_033 -> "BIOS or UEFI" + - *REPLACED* MSG_033 -> "BIOS or UEFI" - *REMOVED* MSG_087 - *RENAMED* IDC_WINDOWS_INSTALL -> MSG_117 - *RENAMED* IDC_WINDOWS_TO_GO -> MSG_118 diff --git a/res/loc/rufus.loc b/res/loc/rufus.loc index b9f905e9..ba8eae8f 100644 --- a/res/loc/rufus.loc +++ b/res/loc/rufus.loc @@ -208,7 +208,6 @@ t MSG_076 "Unable to patch/setup files for boot." t MSG_077 "Unable to assign a drive letter." t MSG_078 "Can't mount GUID volume." t MSG_079 "The device is not ready." - t MSG_080 "Rufus detected that Windows is still flushing its internal buffers onto the USB device.\n\n" "Depending on the speed of your USB device, this operation may take a long time to complete, " "especially for large files.\n\nWe recommend that you let Windows finish, to avoid corruption. " @@ -339,6 +338,17 @@ t MSG_133 "Rufus has detected that you are attempting to create a Windows To Go "Also note that the reason Rufus cannot automatically fix this for you is that 'WppRecorder.sys' is a Microsoft copyrighted file, so we cannot legally embed a copy of the file in the application..." t MSG_134 "Because MBR has been selected for the partition scheme, Rufus can only create a partition up to 2 TB on this media, which will leave %s of disk space unavailable.\n\n" "Are you sure you want to continue?" +t MSG_135 "Version" +t MSG_136 "Release" +t MSG_137 "Edition" +t MSG_138 "Language" +t MSG_139 "Architecture" +t MSG_140 "Confirm" +t MSG_141 "Back" +t MSG_142 "Please wait..." +t MSG_143 "Download ISO Image" +t MSG_144 "Download using a browser" +t MSG_149 "Running download script..." t MSG_150 "Type of computer you plan to use this bootable drive with. It is your responsibility to determine whether " "your target is of BIOS or UEFI type before you start creating the drive, as it may fail to boot otherwise." # You shouldn't translate 'Legacy Mode' as this is an option that usually appears in English in the UEFI settings. @@ -356,7 +366,7 @@ t MSG_161 "Check the device for bad blocks using a test pattern" t MSG_162 "Uncheck this box to use the \"slow\" format method" t MSG_163 "Method that will be used to create partitions" t MSG_164 "Method that will be used to make the drive bootable" -t MSG_165 "Click to select an image..." +t MSG_165 "Click to select or download an image..." t MSG_166 "Check this box to allow the display of international labels " "and set a device icon (creates an autorun.inf)" t MSG_167 "Install an MBR that allows boot selection and can masquerade the BIOS USB drive ID" @@ -4273,6 +4283,14 @@ t MSG_131 "Cette ISO contient plusieurs images Windows.\nVeuillez sélectioner l t MSG_132 "Ce lecteur est utilisé par une autre application ou un autre processus. Voulez-vous quand même le formater ?" t MSG_133 "Rufus a détecté que vous êtes en train de créer un média 'Windows To Go' à partir d'une ISO 1809.\n\nA cause d'un *BUG MICROSOFT*, ce média va planter durant le démarrage de Windows (Blue Screen Of Death), à moins que vous ne remplaciez le fichier 'WppRecorder.sys' par la version 1803.\n\nVeuillez aussi noter que la raison pour laquelle Rufus ne peut pas corriger ce problème pour vous est que le fichier 'WppRecorder.sys' est sujet au copyright de Microsoft, donc nous ne pouvons pas légalement en produire une copie avec cette application..." t MSG_134 "Parce que MBR a été sélectionné pour le schéma de partition, Rufus peut seulement créer une partition sur ce média occupant jusqu’à 2 To, ce qui laissera %s d’espace disque non-disponible.\n\nEtes-vous sûr de vouloir continuer ?" +t MSG_137 "Édition" +t MSG_138 "Langue de produit" +t MSG_140 "Confirmer" +t MSG_141 "Retour" +t MSG_142 "Veuillez patienter..." +t MSG_143 "Télécharger une image ISO" +t MSG_144 "Télécharger avec un navigateur" +t MSG_149 "Execution du script de téléchargement..." t MSG_150 "Type d'ordinateur avec lequel vous comptez utiliser ce disque démarrable. Il est de votre responsabilité de déterminer s'il s'agit d'un type BIOS ou UEFI avant de commencer a créer votre périphérique, car il risque de ne pas démarrer sinon." t MSG_151 "'UEFI-CSM' signifie que le périphérique démarrera seulement en mode émulation BIOS (i.e. 'Legacy Mode') sous UEFI, et non pas en mode UEFI natif." t MSG_152 "'non CSM' signifie que le périphérique démarrera seulement en mode UEFI natif, et non pas en mode émulation BIOS (i.e. 'Legacy Mode')." @@ -4288,7 +4306,7 @@ t MSG_161 "Détecte la présence de blocs défectueux en écrivant un motif de t t MSG_162 "Décochez cette case si vous voulez utiliser la méthode de formatage \"lente\"" t MSG_163 "Methode qui sera utilisée pour créer les partitions" t MSG_164 "Méthode à utiliser pour rendre le périphérique démarrable" -t MSG_165 "Cliquez ici pour sélectionner une image..." +t MSG_165 "Cliquez ici pour sélectionner ou télécharger une image..." t MSG_166 "Cochez cette case pour permettre l’affichage des caractères étendus/internationaux et ajouter une icône (ceci crée un fichier autorun.inf)" t MSG_167 "Installe un MBR permettant la sélection du périphérique de démarrage. Peut aussi camoufler l’ID de disque pour le BIOS" t MSG_168 "Camoufle le premier disque USB démarrable (généralement 0x80) sous une ID différente.\nChangez cette option si vous installez Windows XP avec plus d’un disque dur." diff --git a/src/format.c b/src/format.c index b5f3c1c1..26ee8274 100644 --- a/src/format.c +++ b/src/format.c @@ -2,7 +2,7 @@ * Rufus: The Reliable USB Formatting Utility * Formatting function calls * Copyright © 2007-2009 Tom Thornhill/Ridgecrop - * Copyright © 2011-2018 Pete Batard + * Copyright © 2011-2019 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 @@ -1897,7 +1897,7 @@ DWORD WINAPI FormatThread(void* param) FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_BADBLOCKS_FAILURE); ClearMBRGPT(hPhysicalDrive, SelectedDrive.DiskSize, SelectedDrive.SectorSize, FALSE); fclose(log_fd); - _unlinkU(logfile); + DeleteFileU(logfile); goto out; } uprintf("Bad Blocks: Check completed, %d bad block%s found. (%d/%d/%d errors)\n", @@ -1917,7 +1917,7 @@ DWORD WINAPI FormatThread(void* param) } else { // We didn't get any errors => delete the log file fclose(log_fd); - _unlinkU(logfile); + DeleteFileU(logfile); } } while (r == IDRETRY); if (r == IDABORT) { diff --git a/src/icon.c b/src/icon.c index fefd7873..8c2cfd7e 100644 --- a/src/icon.c +++ b/src/icon.c @@ -1,7 +1,7 @@ /* * Rufus: The Reliable USB Formatting Utility * Extract icon from executable and set autorun.inf - * Copyright © 2012-2016 Pete Batard + * Copyright © 2012-2019 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 @@ -86,9 +86,9 @@ typedef struct #pragma pack(pop) /* - * Extract an icon set from the exe and save it as .ico + * Extract the main icon set from the exe */ -static BOOL SaveIcon(const char* filename) +BOOL ExtractAppIcon(const char* path, BOOL bSilent) { HGLOBAL res_handle; HRSRC res; @@ -101,10 +101,10 @@ static BOOL SaveIcon(const char* filename) icondir = (GRPICONDIR*)GetResource(hMainInstance, MAKEINTRESOURCEA(IDI_ICON), _RT_GROUP_ICON, "icon", &res_size, FALSE); - hFile = CreateFileA(filename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, - NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); + hFile = CreateFileU(path, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, + NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { - uprintf("Unable to create icon '%s': %s.", filename, WindowsErrorString()); + uprintf("Unable to create icon '%s': %s.", path, WindowsErrorString()); goto out; } @@ -141,7 +141,7 @@ static BOOL SaveIcon(const char* filename) goto out; } } - uprintf("Created: %s", filename); + suprintf("Created: %s", path); r = TRUE; out: @@ -185,5 +185,5 @@ BOOL SetAutorun(const char* path) // .inf -> .ico filename[strlen(filename)-1] = 'o'; filename[strlen(filename)-2] = 'c'; - return SaveIcon(filename); + return ExtractAppIcon(filename, FALSE); } diff --git a/src/iso.c b/src/iso.c index e4b48ada..39256c9c 100644 --- a/src/iso.c +++ b/src/iso.c @@ -1,7 +1,7 @@ /* * Rufus: The Reliable USB Formatting Utility * ISO file extraction - * Copyright © 2011-2018 Pete Batard + * Copyright © 2011-2019 Pete Batard * Based on libcdio's iso & udf samples: * Copyright © 2003-2014 Rocky Bernstein * @@ -860,7 +860,7 @@ out: } free(buf); } - _unlinkU(isolinux_tmp); + DeleteFileU(isolinux_tmp); } if (img_report.sl_version != 0) { static_sprintf(img_report.sl_version_str, "%d.%02d", @@ -896,7 +896,7 @@ out: uprintf(" Checking txtsetup.sif:\n OsLoadOptions = %s", tmp); img_report.uses_minint = (strstr(tmp, "/minint") != NULL); } - _unlinkU(tmp_sif); + DeleteFileU(tmp_sif); safe_free(tmp); } if (HAS_WININST(img_report)) { @@ -917,7 +917,7 @@ out: GetGrubVersion(buf, size); } free(buf); - _unlinkU(path); + DeleteFileU(path); } if (img_report.grub2_version[0] != 0) uprintf(" Detected Grub version: %s", img_report.grub2_version); diff --git a/src/msapi_utf8.h b/src/msapi_utf8.h index e9316cf3..9056dbdd 100644 --- a/src/msapi_utf8.h +++ b/src/msapi_utf8.h @@ -1,9 +1,9 @@ /* * MSAPI_UTF8: Common API calls using UTF-8 strings * Compensating for what Microsoft should have done a long long time ago. - * Also see http://utf8everywhere.org/ + * Also see https://utf8everywhere.org * - * Copyright © 2010-2017 Pete Batard + * Copyright © 2010-2019 Pete Batard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -983,15 +983,6 @@ static __inline int _openU(const char *filename, int oflag , int pmode) } #endif -static __inline int _unlinkU(const char *path) -{ - int ret; - wconvert(path); - ret = _wunlink(wpath); - wfree(path); - return ret; -} - static __inline int _stat64U(const char *path, struct __stat64 *buffer) { int ret; diff --git a/src/net.c b/src/net.c index 6c52c3c0..eacffe8b 100644 --- a/src/net.c +++ b/src/net.c @@ -1,7 +1,7 @@ /* * Rufus: The Reliable USB Formatting Utility * Networking functionality (web file download, check for update, etc.) - * Copyright © 2012-2018 Pete Batard + * Copyright © 2012-2019 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 @@ -45,9 +45,12 @@ #define DEFAULT_UPDATE_INTERVAL (24*3600) DWORD DownloadStatus; +BYTE* fido_script = NULL; +extern loc_cmd* selected_locale; +extern HANDLE dialog_handle; extern BOOL force_update, is_x86_32; -static DWORD error_code; +static DWORD error_code, fido_len = 0; static BOOL update_check_in_progress = FALSE; static BOOL force_update_check = FALSE; @@ -231,19 +234,20 @@ const char* WinInetErrorString(void) * 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 */ -static DWORD DownloadToFileOrBuffer(const char* url, const char* file, BYTE** buffer, HWND hProgressDialog) +static uint64_t DownloadToFileOrBuffer(const char* url, const char* file, BYTE** buffer, HWND hProgressDialog) { HWND hProgressBar = NULL; BOOL r = FALSE; - DWORD dwFlags, dwSize, dwWritten, dwDownloaded, dwTotalSize; + DWORD dwFlags, dwSize, dwWritten, dwDownloaded; HANDLE hFile = INVALID_HANDLE_VALUE; const char* accept_types[] = {"*/*\0", NULL}; + const char* short_name; unsigned char buf[DOWNLOAD_BUFFER_SIZE]; - char agent[64], hostname[64], urlpath[128]; + char agent[64], hostname[64], urlpath[128], strsize[32];; HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL; URL_COMPONENTSA UrlParts = {sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0, hostname, sizeof(hostname), 0, NULL, 1, urlpath, sizeof(urlpath), NULL, 1}; - const char* short_name; + uint64_t size = 0, total_size = 0; size_t i; // Can't link with wininet.lib because of sideloading issues @@ -338,16 +342,18 @@ static DWORD DownloadToFileOrBuffer(const char* url, const char* file, BYTE** bu pfHttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&DownloadStatus, &dwSize, NULL); if (DownloadStatus != 200) { error_code = ERROR_INTERNET_ITEM_NOT_FOUND; + SetLastError(ERROR_SEVERITY_ERROR | FAC(FACILITY_HTTP) | error_code); uprintf("Unable to access file: %d", DownloadStatus); goto out; } - dwSize = sizeof(dwTotalSize); - if (!pfHttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwTotalSize, &dwSize, NULL)) { + dwSize = sizeof(strsize); + if (!pfHttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_LENGTH, (LPVOID)strsize, &dwSize, NULL)) { uprintf("Unable to retrieve file length: %s", WinInetErrorString()); goto out; } + total_size = (uint64_t)atoll(strsize); if (hProgressDialog != NULL) - uprintf("File length: %d bytes", dwTotalSize); + uprintf("File length: %s", SizeToHumanReadable(total_size, FALSE, FALSE)); if (file != NULL) { hFile = CreateFileU(file, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); @@ -360,7 +366,7 @@ static DWORD DownloadToFileOrBuffer(const char* url, const char* file, BYTE** bu uprintf("No buffer pointer provided for download"); goto out; } - *buffer = malloc(dwTotalSize); + *buffer = malloc(total_size); if (*buffer == NULL) { uprintf("Could not allocate buffer for download"); goto out; @@ -368,7 +374,6 @@ static DWORD DownloadToFileOrBuffer(const char* url, const char* file, BYTE** bu } // Keep checking for data until there is nothing left. - dwSize = 0; while (1) { // User may have cancelled the download if (IS_ERROR(FormatStatus)) @@ -376,8 +381,8 @@ static DWORD DownloadToFileOrBuffer(const char* url, const char* file, BYTE** bu if (!pfInternetReadFile(hRequest, buf, sizeof(buf), &dwDownloaded) || (dwDownloaded == 0)) break; if (hProgressDialog != NULL) { - SendMessage(hProgressBar, PBM_SETPOS, (WPARAM)(MAX_PROGRESS*((1.0f*dwSize) / (1.0f*dwTotalSize))), 0); - PrintInfo(0, MSG_241, (100.0f*dwSize) / (1.0f*dwTotalSize)); + SendMessage(hProgressBar, PBM_SETPOS, (WPARAM)(MAX_PROGRESS*((1.0f*size) / (1.0f*total_size))), 0); + PrintInfo(0, MSG_241, (100.0f*size) / (1.0f*total_size)); } if (file != NULL) { if (!WriteFile(hFile, buf, dwDownloaded, &dwWritten, NULL)) { @@ -388,13 +393,13 @@ static DWORD DownloadToFileOrBuffer(const char* url, const char* file, BYTE** bu goto out; } } else { - memcpy(&(*buffer)[dwSize], buf, dwDownloaded); + memcpy(&(*buffer)[size], buf, dwDownloaded); } - dwSize += dwDownloaded; + size += dwDownloaded; } - if (dwSize != dwTotalSize) { - uprintf("Could not download complete file - read: %d bytes, expected: %d bytes", dwSize, dwTotalSize); + if (size != total_size) { + uprintf("Could not download complete file - read: %lld bytes, expected: %lld bytes", size, total_size); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT; goto out; } else { @@ -408,13 +413,18 @@ static DWORD DownloadToFileOrBuffer(const char* url, const char* file, BYTE** bu } out: + error_code = GetLastError(); if (hFile != INVALID_HANDLE_VALUE) { // Force a flush - May help with the PKI API trying to process downloaded updates too early... FlushFileBuffers(hFile); CloseHandle(hFile); } - if ((!r) && (file != NULL)) - _unlinkU(file); + if (!r) { + if (file != NULL) + DeleteFileU(file); + if (buffer != NULL) + safe_free(*buffer); + } if (hRequest) pfInternetCloseHandle(hRequest); if (hConnection) @@ -422,7 +432,8 @@ out: if (hSession) pfInternetCloseHandle(hSession); - return r ? dwSize : 0; + SetLastError(error_code); + return r ? size : 0; } // Download and validate a signed file. The file must have a corresponding '.sig' on the server. @@ -444,10 +455,10 @@ DWORD DownloadSignedFile(const char* url, const char* file, HWND hProgressDialog strcpy(url_sig, url); strcat(url_sig, ".sig"); - buf_len = DownloadToFileOrBuffer(url, NULL, &buf, hProgressDialog); + buf_len = (DWORD)DownloadToFileOrBuffer(url, NULL, &buf, hProgressDialog); if (buf_len == 0) goto out; - sig_len = DownloadToFileOrBuffer(url_sig, NULL, &sig, NULL); + sig_len = (DWORD)DownloadToFileOrBuffer(url_sig, NULL, &sig, NULL); if ((sig_len != RSA_SIGNATURE_SIZE) || (!ValidateOpensslSignature(buf, buf_len, sig, sig_len))) { uprintf("FATAL: Download signature is invalid ✗"); DownloadStatus = 403; // Forbidden @@ -633,6 +644,7 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) #else max_channel = releases_only ? 1 : (int)ARRAYSIZE(channel) - 1; #endif + vuprintf("Using %s for the update check", RUFUS_URL); for (k=0; (k to_uint64_t(rufus_version)) || (force_update)) - && ( (os_version.dwMajorVersion > update.platform_min[0]) - || ( (os_version.dwMajorVersion == update.platform_min[0]) && (os_version.dwMinorVersion >= update.platform_min[1])) ); - uprintf("N%sew %s version found%c", found_new_version?"":"o n", channel[k], found_new_version?'!':'.'); + && ((os_version.dwMajorVersion > update.platform_min[0]) + || ((os_version.dwMajorVersion == update.platform_min[0]) && (os_version.dwMinorVersion >= update.platform_min[1]))); + uprintf("N%sew %s version found%c", found_new_version ? "" : "o n", channel[k], found_new_version ? '!' : '.'); } out: @@ -747,7 +759,7 @@ out: pfInternetCloseHandle(hConnection); if (hSession) pfInternetCloseHandle(hSession); - switch(status) { + switch (status) { case 1: PrintInfoDebug(3000, MSG_244); break; @@ -756,14 +768,14 @@ out: break; case 3: case 4: - PrintInfo(3000, found_new_version?MSG_246:MSG_247); + PrintInfo(3000, found_new_version ? MSG_246 : MSG_247); default: break; } // Start the new download after cleanup if (found_new_version) { // User may have started an operation while we were checking - while ((!force_update_check) && (iso_op_in_progress || format_op_in_progress || (dialog_showing>0))) { + while ((!force_update_check) && (iso_op_in_progress || format_op_in_progress || (dialog_showing > 0))) { Sleep(15000); } DownloadNewVersion(); @@ -789,3 +801,263 @@ BOOL CheckForUpdates(BOOL force) } return TRUE; } + +/* + * Download an ISO through Fido + */ +static DWORD WINAPI DownloadISOThread(LPVOID param) +{ + char cmdline[512], locale_str[1024], iso_name[128], pipe[64] = "\\\\.\\pipe\\"; + char powershell_path[MAX_PATH], icon_path[MAX_PATH] = "", script_path[MAX_PATH] = ""; + char *p, *url = NULL; + BYTE *sig = NULL; + HANDLE hFile, hPipe; + DWORD i, dwSize, dwAvail, dwPipeSize = 4096; + GUID guid; + + IGNORE_RETVAL(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)); + + // Use a GUID as random unique string, else ill-intentioned security "researchers" + // may either spam our pipe or replace our script to fool antivirus solutions into + // thinking that Rufus is doing something malicious... + CoCreateGuid(&guid); + strcpy(&pipe[9], GuidToString(&guid)); + static_sprintf(icon_path, "%s%s.ico", temp_dir, APPLICATION_NAME); + ExtractAppIcon(icon_path, TRUE); + + PrintInfo(0, MSG_149); + +#if defined(RUFUS_TEST) + // In test mode, just use our local script + static_strcpy(script_path, "D:\\Projects\\Fido\\Fido.ps1"); +#else + // If we don't have the script, download it + if (fido_len == 0) { + fido_len = (DWORD)DownloadToFileOrBuffer(FIDO_URL, NULL, &fido_script, hMainDialog); + if (fido_len == 0) + goto out; + dwSize = (DWORD)DownloadToFileOrBuffer(FIDO_URL ".sig", NULL, &sig, NULL); + if ((dwSize != RSA_SIGNATURE_SIZE) || (!ValidateOpensslSignature(fido_script, fido_len, sig, dwSize))) { + uprintf("FATAL: Signature is invalid ✗"); + free(sig); + goto out; + } + free(sig); + uprintf("Signature is valid ✓"); + } + + assert((fido_script != NULL) && (fido_len != 0)); + + static_sprintf(script_path, "%s%s.ps1", temp_dir, GuidToString(&guid)); + hFile = CreateFileU(script_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + uprintf("Unable to create download script '%s': %s", script_path, WindowsErrorString()); + goto out; + } + if ((!WriteFile(hFile, fido_script, fido_len, &dwSize, NULL)) || (dwSize != fido_len)) { + uprintf("Unable to write download script '%s': %s", script_path, WindowsErrorString()); + goto out; + } + // TODO: Try to Harden this so that only us and the powershell we launch can access the file + safe_closehandle(hFile); +#endif + static_sprintf(powershell_path, "%s\\WindowsPowerShell\\v1.0\\powershell.exe", system_dir); + static_sprintf(locale_str, "%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s", + selected_locale->txt[0], lmprintf(MSG_135), lmprintf(MSG_136), lmprintf(MSG_137), + lmprintf(MSG_138), lmprintf(MSG_139), lmprintf(MSG_040), lmprintf(MSG_140), + lmprintf(MSG_141), lmprintf(MSG_006), lmprintf(MSG_007), lmprintf(MSG_042), + lmprintf(MSG_142), lmprintf(MSG_143)); + + hPipe = CreateNamedPipeA(pipe, PIPE_ACCESS_INBOUND, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, + dwPipeSize, dwPipeSize, 0, NULL); + if (hPipe == INVALID_HANDLE_VALUE) { + uprintf("Could not create pipe '%s': %s", pipe, WindowsErrorString); + } + + static_sprintf(cmdline, "%s -NonInteractive -NoProfile –ExecutionPolicy Bypass " + "-File %s -PipeName %s -LocData \"%s\" -Icon %s -AppTitle \"%s\" -ShowBrowserOption", + powershell_path, script_path, &pipe[9], locale_str, icon_path, lmprintf(MSG_143)); + FormatStatus = RunCommand(cmdline, app_dir, TRUE); + if ((FormatStatus == 0) && PeekNamedPipe(hPipe, NULL, dwPipeSize, NULL, &dwAvail, NULL) && (dwAvail != 0)) { + url = malloc(dwAvail + 1); + if ((url != NULL) && ReadFile(hPipe, url, dwAvail, &dwSize, NULL) && (dwSize != 0)) { + IMG_SAVE img_save = { 0 }; + url[dwSize] = 0; + for (i = dwSize - 1; i != 0; i--) { + if (url[i] == '/') + break; + } + static_strcpy(iso_name, &url[i + 1]); + // There's extra stuff after the ISO name, which we need to account for + p = strstr(iso_name, ".iso"); + if (p != NULL) { + p[4] = 0; + } else { + for (i = 0; i < strlen(iso_name); i++) { + if (iso_name[i] == '?') { + iso_name[i] = 0; + break; + } + } + } + + EXT_DECL(img_ext, iso_name, __VA_GROUP__("*.iso"), __VA_GROUP__(lmprintf(MSG_036))); + img_save.Type = IMG_SAVE_TYPE_ISO; + img_save.ImagePath = FileDialog(TRUE, NULL, &img_ext, 0); + if (img_save.ImagePath == NULL) { + goto out; + } + // Download the ISO and report errors if any + // TODO: We may want to start a timer here too... + SendMessage(hProgress, PBM_SETSTATE, (WPARAM)PBST_NORMAL, 0); + SetTaskbarProgressState(TASKBAR_NORMAL); + SetTaskbarProgressValue(0, MAX_PROGRESS); + SendMessage(hProgress, PBM_SETPOS, 0, 0); + FormatStatus = 0; + format_op_in_progress = TRUE; + if (DownloadToFileOrBuffer(url, img_save.ImagePath, NULL, hMainDialog) == 0) { + if (SCODE_CODE(FormatStatus) == ERROR_CANCELLED) { + uprintf("Download cancelled by user"); + SendMessage(hProgress, PBM_SETSTATE, (WPARAM)PBST_PAUSED, 0); + SetTaskbarProgressState(TASKBAR_PAUSED); + PrintInfo(0, MSG_211); + Notification(MSG_INFO, NULL, NULL, lmprintf(MSG_211), lmprintf(MSG_041)); + } else { + FormatStatus = GetLastError(); + SendMessage(hProgress, PBM_SETSTATE, (WPARAM)PBST_ERROR, 0); + SetTaskbarProgressState(TASKBAR_ERROR); + PrintInfo(0, MSG_212); + MessageBeep(MB_ICONERROR); + FlashTaskbar(dialog_handle); + SetLastError(FormatStatus); + Notification(MSG_ERROR, NULL, NULL, lmprintf(MSG_194, iso_name), lmprintf(MSG_043, WinInetErrorString())); + } + } + // TODO: If download was successful we should select and scan the ISO + format_op_in_progress = FALSE; + safe_free(img_save.ImagePath); + } + } + +out: + if (icon_path[0] != 0) + DeleteFileU(icon_path); +#if !defined(RUFUS_TEST) + if (script_path[0] != 0) + DeleteFileU(script_path); +#endif + free(url); + SendMessage(hMainDialog, UM_ENABLE_CONTROLS, 0, 0); + ExitThread(FormatStatus); +} + +BOOL DownloadISO() +{ + if (CreateThread(NULL, 0, DownloadISOThread, NULL, 0, NULL) == NULL) { + uprintf("Unable to start Windows ISO download thread"); + FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_CANT_START_THREAD); + SendMessage(hMainDialog, UM_ENABLE_CONTROLS, 0, 0); + return FALSE; + } + // TODO: Can we locate our modal Window and position it/set it on top? + // TODO: Send close message to Fido if the user closes Rufus + return TRUE; +} + +BOOL IsDownloadable(char* url) +{ + DWORD dwFlags, dwSize, dwTotalSize = 0; + const char* accept_types[] = { "*/*\0", NULL }; + char agent[64], hostname[64], urlpath[128]; + HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL; + URL_COMPONENTSA UrlParts = { sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0, + hostname, sizeof(hostname), 0, NULL, 1, urlpath, sizeof(urlpath), NULL, 1 }; + + PF_TYPE_DECL(WINAPI, BOOL, InternetCrackUrlA, (LPCSTR, DWORD, DWORD, LPURL_COMPONENTSA)); + PF_TYPE_DECL(WINAPI, BOOL, InternetGetConnectedState, (LPDWORD, DWORD)); + PF_TYPE_DECL(WINAPI, HINTERNET, InternetOpenA, (LPCSTR, DWORD, LPCSTR, LPCSTR, DWORD)); + PF_TYPE_DECL(WINAPI, HINTERNET, InternetConnectA, (HINTERNET, LPCSTR, INTERNET_PORT, LPCSTR, LPCSTR, DWORD, DWORD, DWORD_PTR)); + PF_TYPE_DECL(WINAPI, BOOL, InternetCloseHandle, (HINTERNET)); + PF_TYPE_DECL(WINAPI, HINTERNET, HttpOpenRequestA, (HINTERNET, LPCSTR, LPCSTR, LPCSTR, LPCSTR, LPCSTR*, DWORD, DWORD_PTR)); + PF_TYPE_DECL(WINAPI, BOOL, HttpSendRequestA, (HINTERNET, LPCSTR, DWORD, LPVOID, DWORD)); + PF_TYPE_DECL(WINAPI, BOOL, HttpQueryInfoA, (HINTERNET, DWORD, LPVOID, LPDWORD, LPDWORD)); + PF_INIT_OR_OUT(InternetCrackUrlA, WinInet); + PF_INIT_OR_OUT(InternetGetConnectedState, WinInet); + PF_INIT_OR_OUT(InternetOpenA, WinInet); + PF_INIT_OR_OUT(InternetConnectA, WinInet); + PF_INIT_OR_OUT(InternetCloseHandle, WinInet); + PF_INIT_OR_OUT(HttpOpenRequestA, WinInet); + PF_INIT_OR_OUT(HttpSendRequestA, WinInet); + PF_INIT_OR_OUT(HttpQueryInfoA, WinInet); + + FormatStatus = 0; + DownloadStatus = 404; + + assert(url != NULL); + + if ((!pfInternetCrackUrlA(url, (DWORD)safe_strlen(url), 0, &UrlParts)) + || (UrlParts.lpszHostName == NULL) || (UrlParts.lpszUrlPath == NULL)) { + uprintf("Unable to decode URL: %s", WinInetErrorString()); + goto out; + } + hostname[sizeof(hostname) - 1] = 0; + + // Open an Internet session + if (!pfInternetGetConnectedState(&dwFlags, 0)) { + SetLastError(ERROR_INTERNET_NOT_INITIALIZED); + uprintf("Network is unavailable: %s", WinInetErrorString()); + goto out; + } + + static_sprintf(agent, APPLICATION_NAME "/%d.%d.%d (Windows NT %d.%d%s)", + rufus_version[0], rufus_version[1], rufus_version[2], + nWindowsVersion >> 4, nWindowsVersion & 0x0F, is_x64() ? "; WOW64" : ""); + hSession = pfInternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); + if (hSession == NULL) { + uprintf("Could not open Internet session: %s", WinInetErrorString()); + goto out; + } + + hConnection = pfInternetConnectA(hSession, UrlParts.lpszHostName, UrlParts.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)NULL); + if (hConnection == NULL) { + uprintf("Could not connect to server %s:%d: %s", UrlParts.lpszHostName, UrlParts.nPort, WinInetErrorString()); + goto out; + } + + hRequest = pfHttpOpenRequestA(hConnection, "GET", UrlParts.lpszUrlPath, NULL, NULL, accept_types, + INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS | + INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_NO_UI | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_HYPERLINK | + ((UrlParts.nScheme == INTERNET_SCHEME_HTTPS) ? INTERNET_FLAG_SECURE : 0), (DWORD_PTR)NULL); + if (hRequest == NULL) { + uprintf("Could not open URL %s: %s", url, WinInetErrorString()); + goto out; + } + + if (!pfHttpSendRequestA(hRequest, NULL, 0, NULL, 0)) { + uprintf("Unable to send request: %s", WinInetErrorString()); + goto out; + } + + // Get the file size + dwSize = sizeof(DownloadStatus); + pfHttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, (LPVOID)&DownloadStatus, &dwSize, NULL); + if (DownloadStatus != 200) { + error_code = ERROR_INTERNET_ITEM_NOT_FOUND; + uprintf("Unable to access file: %d", DownloadStatus); + goto out; + } + dwSize = sizeof(dwTotalSize); + if (!pfHttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwTotalSize, &dwSize, NULL)) + uprintf("Unable to retrieve file length: %s", WinInetErrorString()); + +out: + if (hRequest) + pfInternetCloseHandle(hRequest); + if (hConnection) + pfInternetCloseHandle(hConnection); + if (hSession) + pfInternetCloseHandle(hSession); + + return (dwTotalSize > 0); +} diff --git a/src/resource.h b/src/resource.h index bfbb7e33..b67f5c5e 100644 --- a/src/resource.h +++ b/src/resource.h @@ -91,6 +91,8 @@ #define IDR_UEFI_NTFS 502 #define IDR_TOGO_SAN_POLICY_XML 503 #define IDR_TOGO_UNATTEND_XML 504 +#define IDM_SELECT 901 +#define IDM_DOWNLOAD 902 #define IDC_DEVICE 1001 #define IDC_FILE_SYSTEM 1002 #define IDC_START 1003 diff --git a/src/rufus.c b/src/rufus.c index 623e2dc0..e0b02a66 100755 --- a/src/rufus.c +++ b/src/rufus.c @@ -1,6 +1,6 @@ /* * Rufus: The Reliable USB Formatting Utility - * Copyright © 2011-2018 Pete Batard + * Copyright © 2011-2019 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 @@ -66,16 +66,17 @@ static BOOL app_changed_label = FALSE; static BOOL allowed_filesystem[FS_MAX] = { 0 }; static int64_t last_iso_blocking_status; static int selected_pt = -1, selected_fs = FS_UNKNOWN, preselected_fs = FS_UNKNOWN; -static int image_index = 0; +static int image_index = 0, select_index = 0; static RECT relaunch_rc = { -65536, -65536, 0, 0}; static UINT uQFChecked = BST_CHECKED, uMBRChecked = BST_UNCHECKED; -static HANDLE format_thid = NULL, dialog_handle = NULL; +static HANDLE format_thid = NULL; static HWND hSelectImage = NULL, hStart = NULL; static char szTimer[12] = "00:00:00"; static unsigned int timer; -static char uppercase_select[64], uppercase_start[64], uppercase_close[64], uppercase_cancel[64]; +static char uppercase_select[2][64], uppercase_start[64], uppercase_close[64], uppercase_cancel[64]; -extern BOOL enable_iso, enable_joliet, enable_rockridge, enable_ntfs_compression; +extern BOOL enable_iso, enable_joliet, enable_rockridge; +extern BYTE* fido_script; extern uint8_t* grub2_buf; extern long grub2_len; extern char* szStatusMessage; @@ -98,13 +99,14 @@ WORD selected_langid = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT); DWORD MainThreadId; HWND hDeviceList, hPartitionScheme, hTargetSystem, hFileSystem, hClusterSize, hLabel, hBootType, hNBPasses, hLog = NULL; HWND hLogDialog = NULL, hProgress = NULL, hDiskID; +HANDLE dialog_handle = NULL; BOOL is_x86_32, use_own_c32[NB_OLD_C32] = { FALSE, FALSE }, mbr_selected_by_user = FALSE; BOOL iso_op_in_progress = FALSE, format_op_in_progress = FALSE, right_to_left_mode = FALSE, has_uefi_csm; BOOL enable_HDDs = FALSE, force_update = FALSE, enable_ntfs_compression = FALSE, no_confirmation_on_cancel = FALSE, lock_drive = TRUE; BOOL advanced_mode_device, advanced_mode_format, allow_dual_uefi_bios, detect_fakes, enable_vmdk, force_large_fat32, usb_debug; BOOL 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, installed_uefi_ntfs; +BOOL write_as_image = FALSE, installed_uefi_ntfs = FALSE, enable_fido = FALSE; uint64_t persistence_size = 0; float fScale = 1.0f; int dialog_showing = 0, selection_default = BT_IMAGE, windows_to_go_selection = 0, persistence_unit_selection = -1; @@ -1516,9 +1518,11 @@ static void InitDialog(HWND hDlg) if (strcmp("SCHLIEßEN", uppercase_close) == 0) strcpy(uppercase_close, "SCHLIESSEN"); SetWindowTextU(GetDlgItem(hDlg, IDCANCEL), uppercase_close); - GetWindowTextU(GetDlgItem(hDlg, IDC_SELECT), uppercase_select, sizeof(uppercase_select)); - CharUpperBuffU(uppercase_select, sizeof(uppercase_select)); - SetWindowTextU(GetDlgItem(hDlg, IDC_SELECT), uppercase_select); + GetWindowTextU(GetDlgItem(hDlg, IDC_SELECT), uppercase_select[0], sizeof(uppercase_select[0])); + static_strcpy(uppercase_select[1], lmprintf(MSG_040)); + CharUpperBuffU(uppercase_select[0], sizeof(uppercase_select[0])); + CharUpperBuffU(uppercase_select[1], sizeof(uppercase_select[1])); + SetWindowTextU(GetDlgItem(hDlg, IDC_SELECT), uppercase_select[0]); strcpy(uppercase_cancel, lmprintf(MSG_007)); CharUpperBuffU(uppercase_cancel, sizeof(uppercase_cancel)); @@ -1870,7 +1874,9 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA BOOL set_selected_fs; DRAWITEMSTRUCT* pDI; LPTOOLTIPTEXT lpttt; + NMBCDROPDOWN* pDropDown; HDROP droppedFileInfo; + HMENU hMenu; POINT Point; RECT rc, DialogRect, DesktopRect; HDC hDC; @@ -1886,7 +1892,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA case WM_COMMAND: #ifdef RUFUS_TEST if (LOWORD(wParam) == IDC_TEST) { - DeletePartitions((DWORD)ComboBox_GetItemData(hDeviceList, ComboBox_GetCurSel(hDeviceList))); + uprintf("%s is %s", FIDO_URL, IsDownloadable(FIDO_URL) ? "available" : "NOT available"); break; } #endif @@ -2146,33 +2152,38 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA pt = (int)ComboBox_GetItemData(hTargetSystem, ComboBox_GetCurSel(hTargetSystem)); return (INT_PTR)TRUE; case IDC_SELECT: - if (iso_provided) { - uprintf("\r\nImage provided: '%s'", image_path); - iso_provided = FALSE; // One off thing... + if (select_index == 1) { + EnableControls(FALSE); + DownloadISO(); } else { - char* old_image_path = image_path; - // If declared globaly, lmprintf(MSG_036) would be called on each message... - EXT_DECL(img_ext, NULL, __VA_GROUP__("*.iso;*.img;*.vhd;*.gz;*.bzip2;*.bz2;*.xz;*.lzma;*.Z;*.zip"), - __VA_GROUP__(lmprintf(MSG_036))); - image_path = FileDialog(FALSE, NULL, &img_ext, 0); - if (image_path == NULL) { - if (old_image_path != NULL) { - // Reselect previous image - image_path = old_image_path; - } else { - CreateTooltip(hSelectImage, lmprintf(MSG_173), -1); - PrintStatus(0, MSG_086); - } - break; + if (iso_provided) { + uprintf("\r\nImage provided: '%s'", image_path); + iso_provided = FALSE; // One off thing... } else { - free(old_image_path); + char* old_image_path = image_path; + // If declared globaly, lmprintf(MSG_036) would be called on each message... + EXT_DECL(img_ext, NULL, __VA_GROUP__("*.iso;*.img;*.vhd;*.gz;*.bzip2;*.bz2;*.xz;*.lzma;*.Z;*.zip"), + __VA_GROUP__(lmprintf(MSG_036))); + image_path = FileDialog(FALSE, NULL, &img_ext, 0); + if (image_path == NULL) { + if (old_image_path != NULL) { + // Reselect previous image + image_path = old_image_path; + } else { + CreateTooltip(hSelectImage, lmprintf(MSG_173), -1); + PrintStatus(0, MSG_086); + } + break; + } else { + free(old_image_path); + } + } + FormatStatus = 0; + format_op_in_progress = FALSE; + 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); } - } - FormatStatus = 0; - format_op_in_progress = FALSE; - 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); } break; case IDC_RUFUS_MBR: @@ -2258,6 +2269,11 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA case IDC_SAVE: SaveVHD(); break; + case IDM_SELECT: + case IDM_DOWNLOAD: + select_index = LOWORD(wParam) - IDM_SELECT; + SetWindowTextU(GetDlgItem(hDlg, IDC_SELECT), uppercase_select[select_index]); + break; default: return (INT_PTR)FALSE; } @@ -2267,6 +2283,15 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA ShowWindow(GetDlgItem(hMainDialog, IDS_CSM_HELP_TXT), ((tt == TT_UEFI) || has_uefi_csm) ? SW_SHOW : SW_HIDE); CreateTooltip(GetDlgItem(hMainDialog, IDS_CSM_HELP_TXT), lmprintf((tt == TT_UEFI) ? MSG_152 : MSG_151), 30000); break; + case UM_ENABLE_CONTROLS: + if (!IS_ERROR(FormatStatus)) + PrintInfo(0, MSG_210); + else if (SCODE_CODE(FormatStatus)) + PrintInfo(0, MSG_211); + else + PrintInfo(0, MSG_212); + EnableControls(TRUE); + break; case UM_MEDIA_CHANGE: wParam = DBT_CUSTOMEVENT; // Fall through @@ -2428,6 +2453,17 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA break; } break; + case BCN_DROPDOWN: + pDropDown = (LPNMBCDROPDOWN)lParam; + Point.x = pDropDown->rcButton.left; + Point.y = pDropDown->rcButton.bottom; + ClientToScreen(pDropDown->hdr.hwndFrom, &Point); + hMenu = CreatePopupMenu(); + InsertMenuU(hMenu, -1, MF_BYPOSITION | ((select_index == 0) ? MF_CHECKED : 0), IDM_SELECT, uppercase_select[0]); + InsertMenuU(hMenu, -1, MF_BYPOSITION | ((select_index == 1) ? MF_CHECKED : 0), IDM_DOWNLOAD, uppercase_select[1]); + TrackPopupMenuEx(hMenu, TPM_LEFTALIGN | TPM_TOPALIGN, Point.x, Point.y, hMainDialog, NULL); + DestroyMenu(hMenu); + break; } break; @@ -3080,6 +3116,8 @@ relaunch: // We always launch with the image options displaying image_options = IMOP_WINTOGO; image_option_txt[0] = 0; + select_index = 0; + enable_fido = FALSE; SetProcessDefaultLayout(right_to_left_mode?LAYOUT_RTL:0); if (get_loc_data_file(loc_file, selected_locale)) WriteSettingStr(SETTING_LOCALE, selected_locale->txt[0]); @@ -3370,6 +3408,7 @@ out: safe_free(update.download_url); safe_free(update.release_notes); safe_free(grub2_buf); + safe_free(fido_script); if (argv != NULL) { for (i=0; i + * Copyright © 2011-2019 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 @@ -97,12 +97,14 @@ #define RSA_SIGNATURE_SIZE 256 #define CBN_SELCHANGE_INTERNAL (CBN_SELCHANGE + 256) #if defined(RUFUS_TEST) -#define RUFUS_URL "http://pi3" +#define RUFUS_URL "http://nano/~rufus" #else #define RUFUS_URL "https://rufus.ie" #endif #define DOWNLOAD_URL RUFUS_URL "/downloads" #define FILES_URL RUFUS_URL "/files" +// TODO: Resolve https://github.com/pbatard/Fido/releases/latest and use that as our base +#define FIDO_URL "https://github.com/pbatard/Fido/releases/download/v1.0/Fido.ps1" #define SECURE_BOOT_MORE_INFO_URL "https://github.com/pbatard/rufus/wiki/FAQ#Why_do_I_need_to_disable_Secure_Boot_to_use_UEFINTFS" #define WPPRECORDER_MORE_INFO_URL "https://github.com/pbatard/rufus/wiki/FAQ#BSODs_with_Windows_To_Go_drives_created_from_Windows_10_1809_ISOs" #define SEVENZIP_URL "https://www.7-zip.org" @@ -186,6 +188,7 @@ enum user_message_type { UM_NO_UPDATE, UM_UPDATE_CSM_TOOLTIP, UM_RESIZE_BUTTONS, + UM_ENABLE_CONTROLS, UM_FORMAT_START, // Start of the WM IDs for the language menu items UM_LANGUAGE_MENU = WM_APP + 0x100 @@ -453,7 +456,8 @@ extern int nWindowsVersion, nWindowsBuildNumber, dialog_showing; extern int fs, bt, pt, tt; extern unsigned long syslinux_ldlinux_len[2]; extern char WindowsVersionStr[128], ubuffer[UBUFFER_SIZE], embedded_sl_version_str[2][12]; -extern char szFolderPath[MAX_PATH], app_dir[MAX_PATH], temp_dir[MAX_PATH], system_dir[MAX_PATH], sysnative_dir[MAX_PATH]; +extern char szFolderPath[MAX_PATH], app_dir[MAX_PATH], temp_dir[MAX_PATH], system_dir[MAX_PATH]; +extern char sysnative_dir[MAX_PATH]; extern char* image_path; /* @@ -494,6 +498,7 @@ extern BOOL Notification(int type, const char* dont_display_setting, const notif extern int SelectionDialog(char* title, char* message, char** choices, int size); extern void ListDialog(char* title, char* message, char** items, int size); extern SIZE GetTextSize(HWND hCtrl, char* txt); +extern BOOL ExtractAppIcon(const char* filename, BOOL bSilent); extern BOOL ExtractDOS(const char* path); extern BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan); extern int64_t ExtractISOFile(const char* iso, const char* iso_file, const char* dest_file, DWORD attributes); @@ -521,6 +526,8 @@ extern INT_PTR CALLBACK UpdateCallback(HWND hDlg, UINT message, WPARAM wParam, L extern BOOL SetUpdateCheck(void); extern BOOL CheckForUpdates(BOOL force); extern void DownloadNewVersion(void); +extern BOOL DownloadISO(void); +extern BOOL IsDownloadable(char* url); extern BOOL IsShown(HWND hDlg); extern char* get_token_data_file_indexed(const char* token, const char* filename, int index); #define get_token_data_file(token, filename) get_token_data_file_indexed(token, filename, 1) diff --git a/src/rufus.rc b/src/rufus.rc index e18fa7d2..c054073f 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.5.1448" +CAPTION "Rufus 3.5.1449" FONT 9, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP @@ -43,7 +43,7 @@ BEGIN LTEXT "Boot selection",IDS_BOOT_SELECTION_TXT,8,43,216,8 COMBOBOX IDC_BOOT_SELECTION,8,52,148,10,CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP PUSHBUTTON "#",IDC_HASH,162,52,10,12,BS_FLAT | NOT WS_VISIBLE - PUSHBUTTON "SELECT",IDC_SELECT,180,52,45,10 + CONTROL "SELECT",IDC_SELECT,"Button", WS_TABSTOP,180,52,45,10 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 @@ -394,8 +394,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 3,5,1448,0 - PRODUCTVERSION 3,5,1448,0 + FILEVERSION 3,5,1449,0 + PRODUCTVERSION 3,5,1449,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -413,13 +413,13 @@ BEGIN VALUE "Comments", "https://akeo.ie" VALUE "CompanyName", "Akeo Consulting" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "3.5.1448" + VALUE "FileVersion", "3.5.1449" VALUE "InternalName", "Rufus" - VALUE "LegalCopyright", "© 2011-2018 Pete Batard (GPL v3)" + VALUE "LegalCopyright", "© 2011-2019 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "https://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus-3.5.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "3.5.1448" + VALUE "ProductVersion", "3.5.1449" END END BLOCK "VarFileInfo" diff --git a/src/stdfn.c b/src/stdfn.c index 142d4909..5b0267c9 100644 --- a/src/stdfn.c +++ b/src/stdfn.c @@ -1,7 +1,7 @@ /* * Rufus: The Reliable USB Formatting Utility * Standard Windows function calls - * Copyright © 2013-2018 Pete Batard + * Copyright © 2013-2019 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 @@ -604,7 +604,7 @@ DWORD RunCommand(const char* cmd, const char* dir, BOOL log) uprintf("Could not set commandline pipe: %s", WindowsErrorString()); goto out; } - si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; + si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES | STARTF_PREVENTPINNING | STARTF_TITLEISAPPID; si.wShowWindow = SW_HIDE; si.hStdOutput = hOutputWrite; si.hStdError = hOutputWrite; diff --git a/src/stdlg.c b/src/stdlg.c index 43c390f0..f9127584 100644 --- a/src/stdlg.c +++ b/src/stdlg.c @@ -45,7 +45,7 @@ #include "license.h" /* Globals */ -extern BOOL is_x86_32; +extern BOOL is_x86_32, enable_fido; static HICON hMessageIcon = (HICON)INVALID_HANDLE_VALUE; static char* szMessageText = NULL; static char* szMessageTitle = NULL; @@ -1542,6 +1542,13 @@ BOOL SetUpdateCheck(void) ((ReadSetting32(SETTING_UPDATE_INTERVAL) == -1) && enable_updates) ) WriteSetting32(SETTING_UPDATE_INTERVAL, 86400); } + // Also detect if we can use FIDO, which depends on: + // - Update check being enabled + // - URL for the script being reachable + if (ReadSetting32(SETTING_UPDATE_INTERVAL) > 0) { + uprintf("Checking for %s...", FIDO_URL); + enable_fido = IsDownloadable(FIDO_URL); + } return TRUE; } @@ -1668,7 +1675,7 @@ INT_PTR CALLBACK NewVersionCallback(HWND hDlg, UINT message, WPARAM wParam, LPAR if (ValidateSignature(hDlg, filepath) != NO_ERROR) { // Unconditionally delete the download and disable the "Launch" control - _unlinkU(filepath); + DeleteFileU(filepath); EnableWindow(GetDlgItem(hDlg, IDC_DOWNLOAD), FALSE); break; } diff --git a/src/ui.c b/src/ui.c index 3bc939f0..f5b297f8 100644 --- a/src/ui.c +++ b/src/ui.c @@ -1,7 +1,7 @@ /* * Rufus: The Reliable USB Formatting Utility * UI-related function calls - * Copyright © 2018 Pete Batard + * Copyright © 2018-2019 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 @@ -43,6 +43,7 @@ UINT_PTR UM_LANGUAGE_MENU_MAX = UM_LANGUAGE_MENU; HIMAGELIST hUpImageList, hDownImageList; +extern BOOL enable_fido; int advanced_device_section_height, advanced_format_section_height; // (empty) check box width, (empty) drop down width, button height (for and without dropdown match) int cbw, ddw, ddbh = 0, bh = 0; @@ -147,6 +148,8 @@ void GetMainButtonsWidth(HWND hDlg) { unsigned int i; RECT rc; + LONG style; + char download[64]; GetWindowRect(GetDlgItem(hDlg, main_button_ids[0]), &rc); MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2); @@ -154,8 +157,17 @@ void GetMainButtonsWidth(HWND hDlg) for (i = 0; i < ARRAYSIZE(main_button_ids); i++) bw = max(bw, GetTextWidth(hDlg, main_button_ids[i]) + cbw); - // The 'CLOSE' button is also be used to display 'CANCEL' => measure that too + // The 'CLOSE' button is also be used to display 'CANCEL' and we sometimes + // want to add "DOWNLOAD" into the Select split button => measure that too. bw = max(bw, GetTextSize(GetDlgItem(hDlg, IDCANCEL), lmprintf(MSG_007)).cx + cbw); + if (enable_fido) { + static_strcpy(download, lmprintf(MSG_040)); + CharUpperBuffU(download, sizeof(download)); + bw = max(bw, GetTextSize(GetDlgItem(hDlg, IDC_SELECT), download).cx + (3 * cbw) / 2); + style = GetWindowLong(GetDlgItem(hDlg, IDC_SELECT), GWL_STYLE); + style|= BS_SPLITBUTTON; + SetWindowLong(GetDlgItem(hDlg, IDC_SELECT), GWL_STYLE, style); + } } // The following goes over the data that gets populated into the half-width dropdowns