[net] add Windows retail ISO downloads

* This is accomplished through Fido (https://github.com/pbatard/Fido), a *SIGNED*
  PowerShell script, that is downloaded from GitHub and that resides in memory for
  the duration of a session.
* The reason we use a downloaded PS script, rather than an embedded on, is because:
  - Microsoft have regularly been changing the deal with regards to how retail ISOs
    can be downloaded, and not for the better, so we can't simply embed a static
    means of downloading ISOs and expect that to work forever.
  - By using an external script, we can immediately respond to whatever new means of
    *ANNOYING* their legitimate users Microsoft will come up with next, as well as
    make sure that, the minute a new retail version of Windows becomes available, it
    also becomes available for download in Rufus.
* Note that if you are concerned about downloading a remote PS script that is being
  run at the same level as an elevated application, you should understand that:
  - Only scripts downloaded from GitHub, from an account that is protected with 2FA,
    are allowed to run (i.e. someone would first have to steal a *physical* 2FA key
    to be in a position to upload a malicious script).
  - On top of this, only scripts that are signed with a separate private key (RSA +
    AES-256), that is itself also protected with a strong unique password which only
    a single person knows (and must manually enter each time they want to make a new
    version of the script available for download), are allowed to run.
  The above means that there's about as much chance for someone to manage to upload
  a malicious script on the GitHub servers, that Rufus would allow to run, as there
  is for someone to upload a malicious version of Rufus itself.
  Still, if you are paranoid and have concerns that, even as you can validate from
  its source that Rufus does not attempt to execute any remote script unless a user
  actively selected and clicked the DOWNLOAD button, you can also completely disable
  the remote script download feature, if you just set the update check to disabled
  (which, by the way, Rufus *EXPLICITLY* asks you to choose whether you want to
  enable or not, the very first time you run the application).
* Also remove _unlinkU() which duplicates what DeleteFileU() already does.
This commit is contained in:
Pete Batard 2019-03-02 23:28:56 +00:00
parent c5513447c9
commit e073fb47b0
No known key found for this signature in database
GPG Key ID: 38E0CF5E69EDD671
14 changed files with 471 additions and 111 deletions

View File

@ -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

View File

@ -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 despace 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 laffichage 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 lID 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 dun disque dur."

View File

@ -2,7 +2,7 @@
* Rufus: The Reliable USB Formatting Utility
* Formatting function calls
* Copyright © 2007-2009 Tom Thornhill/Ridgecrop
* Copyright © 2011-2018 Pete Batard <pete@akeo.ie>
* Copyright © 2011-2019 Pete Batard <pete@akeo.ie>
*
* 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) {

View File

@ -1,7 +1,7 @@
/*
* Rufus: The Reliable USB Formatting Utility
* Extract icon from executable and set autorun.inf
* Copyright © 2012-2016 Pete Batard <pete@akeo.ie>
* Copyright © 2012-2019 Pete Batard <pete@akeo.ie>
*
* 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);
}

View File

@ -1,7 +1,7 @@
/*
* Rufus: The Reliable USB Formatting Utility
* ISO file extraction
* Copyright © 2011-2018 Pete Batard <pete@akeo.ie>
* Copyright © 2011-2019 Pete Batard <pete@akeo.ie>
* Based on libcdio's iso & udf samples:
* Copyright © 2003-2014 Rocky Bernstein <rocky@gnu.org>
*
@ -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);

View File

@ -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 <pete@akeo.ie>
* Copyright © 2010-2019 Pete Batard <pete@akeo.ie>
*
* 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;

332
src/net.c
View File

@ -1,7 +1,7 @@
/*
* Rufus: The Reliable USB Formatting Utility
* Networking functionality (web file download, check for update, etc.)
* Copyright © 2012-2018 Pete Batard <pete@akeo.ie>
* Copyright © 2012-2019 Pete Batard <pete@akeo.ie>
*
* 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<max_channel) && (!found_new_version); k++) {
uprintf("Checking %s channel...", channel[k]);
// At this stage we can query the server for various update version files.
@ -717,7 +729,7 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
// Now download the signature file
static_sprintf(sigpath, "%s/%s.sig", server_url, urlpath);
dwDownloaded = DownloadToFileOrBuffer(sigpath, NULL, &sig, NULL);
dwDownloaded = (DWORD)DownloadToFileOrBuffer(sigpath, NULL, &sig, NULL);
if ((dwDownloaded != RSA_SIGNATURE_SIZE) || (!ValidateOpensslSignature(buf, dwTotalSize, sig, dwDownloaded))) {
uprintf("FATAL: Version signature is invalid!");
goto out;
@ -725,7 +737,7 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
vuprintf("Version signature is valid");
status++;
parse_update(buf, dwTotalSize+1);
parse_update(buf, dwTotalSize + 1);
vuprintf("UPDATE DATA:");
vuprintf(" version: %d.%d.%d (%s)", update.version[0], update.version[1], update.version[2], channel[k]);
@ -733,9 +745,9 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
vuprintf(" url: %s", update.download_url);
found_new_version = ((to_uint64_t(update.version) > 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);
}

View File

@ -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

View File

@ -1,6 +1,6 @@
/*
* Rufus: The Reliable USB Formatting Utility
* Copyright © 2011-2018 Pete Batard <pete@akeo.ie>
* Copyright © 2011-2019 Pete Batard <pete@akeo.ie>
*
* 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<argc; i++) safe_free(argv[i]);
safe_free(argv);

View File

@ -1,6 +1,6 @@
/*
* Rufus: The Reliable USB Formatting Utility
* Copyright © 2011-2018 Pete Batard <pete@akeo.ie>
* Copyright © 2011-2019 Pete Batard <pete@akeo.ie>
*
* 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)

View File

@ -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"

View File

@ -1,7 +1,7 @@
/*
* Rufus: The Reliable USB Formatting Utility
* Standard Windows function calls
* Copyright © 2013-2018 Pete Batard <pete@akeo.ie>
* Copyright © 2013-2019 Pete Batard <pete@akeo.ie>
*
* 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;

View File

@ -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;
}

View File

@ -1,7 +1,7 @@
/*
* Rufus: The Reliable USB Formatting Utility
* UI-related function calls
* Copyright © 2018 Pete Batard <pete@akeo.ie>
* Copyright © 2018-2019 Pete Batard <pete@akeo.ie>
*
* 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