1
1
Fork 0
mirror of https://github.com/pbatard/rufus.git synced 2024-08-14 23:57:05 +00:00

Merge remote-tracking branch 'pbatard/rufus'

This commit is contained in:
René van der Zee 2018-07-05 21:49:23 +02:00
commit d14029310f
20 changed files with 661 additions and 342 deletions

20
configure vendored
View file

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for rufus 3.1.
# Generated by GNU Autoconf 2.69 for rufus 3.2.
#
# Report bugs to <https://github.com/pbatard/rufus/issues>.
#
@ -580,8 +580,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='rufus'
PACKAGE_TARNAME='rufus'
PACKAGE_VERSION='3.1'
PACKAGE_STRING='rufus 3.1'
PACKAGE_VERSION='3.2'
PACKAGE_STRING='rufus 3.2'
PACKAGE_BUGREPORT='https://github.com/pbatard/rufus/issues'
PACKAGE_URL='https://rufus.akeo.ie'
@ -1228,7 +1228,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures rufus 3.1 to adapt to many kinds of systems.
\`configure' configures rufus 3.2 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1294,7 +1294,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of rufus 3.1:";;
short | recursive ) echo "Configuration of rufus 3.2:";;
esac
cat <<\_ACEOF
@ -1385,7 +1385,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
rufus configure 3.1
rufus configure 3.2
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@ -1440,7 +1440,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by rufus $as_me 3.1, which was
It was created by rufus $as_me 3.2, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@ -2303,7 +2303,7 @@ fi
# Define the identity of the package.
PACKAGE='rufus'
VERSION='3.1'
VERSION='3.2'
cat >>confdefs.h <<_ACEOF
@ -4481,7 +4481,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by rufus $as_me 3.1, which was
This file was extended by rufus $as_me 3.2, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -4535,7 +4535,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
rufus config.status 3.1
rufus config.status 3.2
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"

View file

@ -1,4 +1,4 @@
AC_INIT([rufus], [3.1], [https://github.com/pbatard/rufus/issues], [rufus], [https://rufus.akeo.ie])
AC_INIT([rufus], [3.2], [https://github.com/pbatard/rufus/issues], [rufus], [https://rufus.akeo.ie])
AM_INIT_AUTOMAKE([-Wno-portability foreign no-dist no-dependencies])
AC_CONFIG_SRCDIR([src/rufus.c])
AC_CONFIG_MACRO_DIR([m4])

View file

@ -8,7 +8,7 @@
for an interesting struggle, when you also happen to have a comma in one of the fields... -->
<Identity
Name="Rufus"
Version="3.1.1320.0"
Version="3.2.1320.0"
ProcessorArchitecture="x86"
Publisher='CN=Akeo Consulting, O=Akeo Consulting, STREET=24 Grey Rock, L=Milford, S=Co. Donegal, PostalCode=F92 D667, C=IE' />
<Properties>

View file

@ -1,5 +1,5 @@
@echo off
set VERSION=3.1
set VERSION=3.2
rem Make sure you don't have anything you don't want included in the package, as anything residing in the
rem current directory will be included, including any previous .appx, which makes for nice recursion...

View file

@ -15,7 +15,11 @@ content. PLEASE, do not just look at this Changelog when updating your
translation, but always use the English section of rufus.loc as your base.
For instance, MSG_114, that was introduced in v1.0.8 is MORE than one line!
o Version 1.0.23 (2018.??.??)
o Version 1.0.24 (2018.??.??)
- *NEW* MSG_087
- *NEW* MSG_172
o Version 1.0.23 (2018.03.27)
- All positioning ('m', 's') has now been removed as well as some controls, for the 3.0 UI redesign
- *NEW* IDS_DRIVE_PROPERTIES_TXT "Drive Properties"
- *NEW* IDS_BOOT_SELECTION_TXT "Boot selection"

View file

@ -208,7 +208,7 @@ t MSG_032 "UEFI (non CSM)"
t MSG_033 "BIOS or UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d pass"
t MSG_035 "%d passes"
t MSG_035 "%d passes %s"
t MSG_036 "ISO Image"
t MSG_037 "Application"
t MSG_038 "Abort"
@ -277,6 +277,7 @@ t MSG_084 "This ISO image seems to use an obsolete version of '%s'.\n"
"'%s' exists there, it will be reused automatically."
t MSG_085 "Downloading '%s'"
t MSG_086 "No image selected"
t MSG_087 "for %s devices"
t MSG_088 "Image is too big"
t MSG_089 "The image is too big for the selected target."
t MSG_090 "Unsupported ISO"
@ -386,6 +387,7 @@ t MSG_169 "Create an extra hidden partition and try to align partitions boundari
"This can improve boot detection for older BIOSes"
t MSG_170 "Enable the listing of USB Hard Drive enclosures. USE AT YOUR OWN RISKS!!!"
t MSG_171 "Start the formatting operation.\nThis will DESTROY any data on the target!"
t MSG_172 "Invalid download signature"
t MSG_173 "Click to select..."
# The following will appear in the about dialog
t MSG_174 "Rufus - The Reliable USB Formatting Utility"
@ -684,7 +686,7 @@ t MSG_032 "UEFI (بدون CSM)"
t MSG_033 "BIOS أو UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d تجاوز"
t MSG_035 "%d تجاوزات"
t MSG_035 "%d تجاوزات %s"
t MSG_036 "ISO صورة"
t MSG_037 "تطبيق"
t MSG_038 "توقف"
@ -1136,7 +1138,7 @@ t MSG_032 "UEFI (yox CSM)"
t MSG_033 "BIOS və ya UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d Keçid"
t MSG_035 "%d Keçid"
t MSG_035 "%d Keçid %s"
t MSG_036 "ISO Əksi"
t MSG_037 "Proqram"
t MSG_038 "İmtina et"
@ -1583,7 +1585,7 @@ t MSG_030 "%s (Стандартно)"
#t MSG_033 "%s дялова схема за UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d Пробег"
t MSG_035 "%d Пробега"
t MSG_035 "%d Пробега %s"
t MSG_036 "ISO образ"
t MSG_037 "Приложение"
t MSG_038 "Прекрати"
@ -2028,7 +2030,7 @@ t MSG_032 "UEFI (非 CSM)"
t MSG_033 "BIOS 或 UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d 遍"
t MSG_035 "%d 遍"
t MSG_035 "%d 遍 %s"
t MSG_036 "ISO 镜像"
t MSG_037 "程序"
t MSG_038 "中止"
@ -2471,7 +2473,7 @@ t MSG_032 "UEFI (無 CSM)"
t MSG_033 "BIOS 或 UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d 回"
t MSG_035 "%d 回"
t MSG_035 "%d 回 %s"
t MSG_036 "ISO 映像"
t MSG_037 "程式"
t MSG_038 "終止"
@ -2885,7 +2887,7 @@ t MSG_032 "UEFI (bez CSM)"
t MSG_033 "BIOS ili UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d prolaz"
t MSG_035 "%d prolaza"
t MSG_035 "%d prolaza %s"
t MSG_036 "ISO slika"
t MSG_037 "Aplikacija"
t MSG_038 "Prekini"
@ -3340,7 +3342,7 @@ t MSG_032 "UEFI (ne CSM)"
t MSG_033 "BIOS nebo UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d pokus"
t MSG_035 "%d pokusy"
t MSG_035 "%d pokusy %s"
t MSG_036 "Obraz ISO"
t MSG_037 "Aplikace"
t MSG_038 "Přerušit"
@ -3792,7 +3794,7 @@ t MSG_032 "UEFI (ikke CSM)"
t MSG_033 "BIOS eller UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d gennemløb"
t MSG_035 "%d gennemløb"
t MSG_035 "%d gennemløb %s"
t MSG_036 "ISO-image"
t MSG_037 "Applikation"
t MSG_038 "Annuller"
@ -4228,7 +4230,7 @@ t MSG_032 "UEFI (geen CSM)"
t MSG_033 "BIOS of UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d Ronde"
t MSG_035 "%d Rondes"
t MSG_035 "%d Rondes %s"
t MSG_036 "ISO image"
t MSG_037 "Applicatie"
t MSG_038 "Afbreken"
@ -4667,7 +4669,7 @@ t MSG_032 "UEFI (ei-CSM)"
t MSG_033 "BIOS tai UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d testi"
t MSG_035 "%d testiä"
t MSG_035 "%d testiä %s"
t MSG_036 "ISO-kuva"
t MSG_037 "Sovellus"
t MSG_038 "Keskeytä"
@ -5105,7 +5107,7 @@ t MSG_031 "BIOS (ou UEFI-CSM)"
t MSG_032 "UEFI (non CSM)"
t MSG_033 "BIOS ou UEFI"
t MSG_034 "%d passe"
t MSG_035 "%d passes"
t MSG_035 "%d passes %s"
t MSG_036 "Image ISO"
t MSG_037 "Application"
t MSG_038 "Annuler"
@ -5528,7 +5530,7 @@ t MSG_032 "UEFI (ohne CSM)"
t MSG_033 "BIOS oder UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d Durchgang"
t MSG_035 "%d Durchgänge"
t MSG_035 "%d Durchgänge %s"
t MSG_036 "ISO-Abbild"
t MSG_037 "Programm"
t MSG_038 "Abbruch"
@ -5956,7 +5958,7 @@ t MSG_032 "UEFI (εκτός από CSM)"
t MSG_033 "BIOS ή UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d Πέρασμα"
t MSG_035 "%d Περάσματα"
t MSG_035 "%d Περάσματα %s"
t MSG_036 "Είδωλο ISO"
t MSG_037 "Εφαρμογή"
t MSG_038 "Τερματισμός"
@ -6412,7 +6414,7 @@ t MSG_032 "UEFI (שאינו CSM)"
t MSG_033 "BIOS או UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "מעבר אחד"
t MSG_035 "%d מעברים"
t MSG_035 "%d מעברים %s"
t MSG_036 "קובץ ISO"
t MSG_037 "יישום"
t MSG_038 "ביטול"
@ -6889,7 +6891,7 @@ t MSG_032 "UEFI (nem CSM)"
t MSG_033 "BIOS vagy UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d vizsgálva"
t MSG_035 "%d vizsgálva"
t MSG_035 "%d vizsgálva %s"
t MSG_036 "ISO kép"
t MSG_037 "Alkalmazás"
t MSG_038 "Megszakít"
@ -7341,7 +7343,7 @@ t MSG_032 "UEFI (non CSM)"
t MSG_033 "BIOS atau UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d kali uji"
t MSG_035 "%d kali uji"
t MSG_035 "%d kali uji %s"
t MSG_036 "ISO Image"
t MSG_037 "Aplikasi"
t MSG_038 "Batal"
@ -7789,7 +7791,7 @@ t MSG_031 "BIOS (o UEFI CSM)"
t MSG_032 "UEFI (non CSM)"
t MSG_033 "BIOS o UEFI"
t MSG_034 "%d test"
t MSG_035 "%d test"
t MSG_035 "%d test %s"
t MSG_036 "Immagine ISO"
t MSG_037 "Applicazione"
t MSG_038 "Annulla"
@ -8229,7 +8231,7 @@ t MSG_032 "UEFI (CSM無効)"
t MSG_033 "BIOSまたはUEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d パス"
t MSG_035 "%d パス"
t MSG_035 "%d パス %s"
t MSG_036 "ISOイメージ"
t MSG_037 "アプリケーション"
t MSG_038 "中止"
@ -8698,7 +8700,7 @@ t MSG_032 "UEFI (CSM 지원 안 됨)"
t MSG_033 "BIOS 또는 UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "한번만 검사"
t MSG_035 "%d회 검사"
t MSG_035 "%d회 검사 %s"
t MSG_036 "ISO 이미지"
t MSG_037 "프로그램"
t MSG_038 "취소"
@ -9146,7 +9148,7 @@ t MSG_032 "BIOS (bez CSM)"
t MSG_033 "BIOS vai UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d mēģ."
t MSG_035 "%d mēģ."
t MSG_035 "%d mēģ. %s"
t MSG_036 "ISO virtuālais attēls"
t MSG_037 "Programma"
t MSG_038 "Pārtraukt"
@ -9596,7 +9598,7 @@ t MSG_032 "UEFI (ne CSM)"
t MSG_033 "BIOS arba UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d bandymas"
t MSG_035 "%d bandymai"
t MSG_035 "%d bandymai %s"
t MSG_036 "ISO atvaizdas"
t MSG_037 "Programa"
t MSG_038 "Nutraukti"
@ -10051,7 +10053,7 @@ t MSG_030 "%s (Lalai)"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d kali lulus"
t MSG_035 "%d kali lulus"
t MSG_035 "%d kali lulus %s"
t MSG_036 "Imej ISO"
t MSG_037 "Aplikasi"
t MSG_038 "Batal"
@ -10480,7 +10482,7 @@ t MSG_032 "UEFI (ikke CSM)"
t MSG_033 "BIOS eller UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d Passering"
t MSG_035 "%d Passeringer"
t MSG_035 "%d Passeringer %s"
t MSG_036 "ISO-bilde"
t MSG_037 "Applikasjon"
t MSG_038 "Avbryt"
@ -10959,7 +10961,7 @@ t MSG_032 "UEFI (non CSM)"
t MSG_033 "BIOS یا UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d گذره"
t MSG_035 "%d گذره"
t MSG_035 "%d گذره %s"
t MSG_036 "ایمیج ISO"
t MSG_037 "برنامه"
t MSG_038 "لغو"
@ -11427,7 +11429,7 @@ t MSG_032 "UEFI (bez CSM)"
t MSG_033 "BIOS lub UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d Przebieg"
t MSG_035 "%d Przebiegi"
t MSG_035 "%d Przebiegi %s"
t MSG_036 "Obraz ISO"
t MSG_037 "Aplikacja"
t MSG_038 "Przerwij"
@ -11891,7 +11893,7 @@ t MSG_032 "UEFI (não CSM)"
t MSG_033 "BIOS ou UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d passo"
t MSG_035 "%d passos"
t MSG_035 "%d passos %s"
t MSG_036 "Imagem ISO"
t MSG_037 "Aplicativo"
t MSG_038 "Abortar"
@ -12364,7 +12366,7 @@ t MSG_032 "UEFI (não CSM)"
t MSG_033 "BIOS ou UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d passo"
t MSG_035 "%d passos"
t MSG_035 "%d passos %s"
t MSG_036 "Imagem ISO"
t MSG_037 "Aplicação"
t MSG_038 "Abortar"
@ -12808,7 +12810,7 @@ t MSG_031 "BIOS (sau UEFI-CSM)"
t MSG_032 "UEFI (non CSM)"
t MSG_033 "BIOS sau UEFI"
t MSG_034 "%d pas"
t MSG_035 "%d pași"
t MSG_035 "%d pași %s"
t MSG_036 "Imagine ISO"
t MSG_037 "Cerere"
t MSG_038 "Anulează"
@ -13233,7 +13235,7 @@ t MSG_032 "UEFI (non-CSM)"
t MSG_033 "BIOS или UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d проход"
t MSG_035 "%d прохода"
t MSG_035 "%d прохода %s"
t MSG_036 "ISO-образ"
t MSG_037 "Приложение"
t MSG_038 "Отменить"
@ -13675,7 +13677,7 @@ t MSG_030 "%s (Uobičajeno)"
#t MSG_033 "%s particijska šema za UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d sekvenca"
t MSG_035 "%d sekvence"
t MSG_035 "%d sekvence %s"
t MSG_036 "ISO datoteke"
t MSG_037 "Aplikacija"
t MSG_038 "Prekini"
@ -14122,7 +14124,7 @@ t MSG_032 "UEFI (bez CSM)"
t MSG_033 "BIOS alebo UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d pokus"
t MSG_035 "%d pokusy"
t MSG_035 "%d pokusy %s"
t MSG_036 "Obraz ISO"
t MSG_037 "Aplikácia"
t MSG_038 "Ukončiť"
@ -14576,7 +14578,7 @@ t MSG_032 "UEFI (brez CSM)"
t MSG_033 "BIOS ali UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d prehod"
t MSG_035 "%d prehoda/-i"
t MSG_035 "%d prehoda/-i %s"
t MSG_036 "sliko ISO"
t MSG_037 "Aplikacija"
t MSG_038 "Prekini"
@ -15010,7 +15012,7 @@ t MSG_032 "UEFI (no CSM)"
t MSG_033 "BIOS o UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d paso"
t MSG_035 "%d pasos"
t MSG_035 "%d pasos %s"
t MSG_036 "Imagen ISO"
t MSG_037 "Aplicación"
t MSG_038 "Abortar"
@ -15467,7 +15469,7 @@ t MSG_032 "UEFI (icke CSM)"
t MSG_033 "BIOS eller UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d gång"
t MSG_035 "%d gånger"
t MSG_035 "%d gånger %s"
t MSG_036 "ISO-avbild"
t MSG_037 "Program"
t MSG_038 "Avbryt"
@ -15926,7 +15928,7 @@ t MSG_032 "UEFI (ที่ไม่ใช่ CSM)"
t MSG_033 "BIOS หรือ UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d รอบ"
t MSG_035 "%d รอบ"
t MSG_035 "%d รอบ %s"
t MSG_036 "อิมเมจ ISO"
t MSG_037 "แอพพลิเคชั่น"
t MSG_038 "ยกเลิก"
@ -16393,7 +16395,7 @@ t MSG_032 "UEFI (CSM yok)"
t MSG_033 "BIOS ya da UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d Geçiş"
t MSG_035 "%d Geçiş"
t MSG_035 "%d Geçiş %s"
t MSG_036 "ISO Yansıması"
t MSG_037 "Uygulama"
t MSG_038 "Vazgeç"
@ -16847,7 +16849,7 @@ t MSG_032 "UEFI (без CSM)"
t MSG_033 "BIOS чи UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "%d прохід"
t MSG_035 "%d проходи"
t MSG_035 "%d проходи %s"
t MSG_036 "ISO-образ"
t MSG_037 "Додаток"
t MSG_038 "Відмінити"
@ -17283,7 +17285,7 @@ t MSG_030 "%s (Mặc định)"
#t MSG_033 "Sắp xếp phân vùng %s cho UEFI"
# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
t MSG_034 "Qua %d lần"
t MSG_035 "Qua %d lần"
t MSG_035 "Qua %d lần %s"
t MSG_036 "Ảnh ISO"
t MSG_037 "Ứng dụng"
t MSG_038 "Huỷ bỏ"

View file

@ -7,7 +7,7 @@
*
* Copyright 1995, 1996, 1997, 1998, 1999 by Theodore Ts'o
* Copyright 1999 by David Beattie
* Copyright 2011-2016 by Pete Batard
* Copyright 2011-2018 by Pete Batard
*
* This file is based on the minix file system programs fsck and mkfs
* written and copyrighted by Linus Torvalds <Linus.Torvalds@cs.helsinki.fi>
@ -350,13 +350,14 @@ static void pattern_fill(unsigned char *buffer, unsigned int pattern,
unsigned char bpattern[sizeof(pattern)], *ptr;
if (pattern == (unsigned int) ~0) {
PrintInfo(3500, MSG_236);
srand((unsigned int)GetTickCount64());
for (ptr = buffer; ptr < buffer + n; ptr++) {
// coverity[dont_call]
(*ptr) = rand() % (1 << (8 * sizeof(char)));
}
PrintInfo(3500, MSG_236);
} else {
PrintInfo(3500, MSG_237, pattern);
bpattern[0] = 0;
for (i = 0; i < sizeof(bpattern); i++) {
if (pattern == 0)
@ -372,7 +373,6 @@ static void pattern_fill(unsigned char *buffer, unsigned int pattern,
else
i--;
}
PrintInfo(3500, MSG_237, bpattern[i]);
cur_pattern++;
}
}
@ -422,16 +422,22 @@ static int64_t do_write(HANDLE hDrive, unsigned char * buffer, uint64_t tryout,
}
static unsigned int test_rw(HANDLE hDrive, blk_t last_block, size_t block_size, blk_t first_block,
size_t blocks_at_once, int nb_passes)
size_t blocks_at_once, int pattern_type, int nb_passes)
{
const unsigned int pattern[BADLOCKS_PATTERN_TYPES][BADBLOCK_PATTERN_COUNT] =
{ BADBLOCK_PATTERN_SLC, BADCLOCK_PATTERN_MLC, BADBLOCK_PATTERN_TLC };
unsigned char *buffer = NULL, *read_buffer;
const unsigned int pattern[] = BADBLOCK_PATTERNS;
int i, pat_idx;
unsigned int bb_count = 0;
blk_t got, tryout, recover_block = ~0, *blk_id;
size_t id_offset;
size_t id_offset = 0;
if ((nb_passes < 1) || (nb_passes > 4)) {
if ((pattern_type < 0) || (pattern_type >= BADLOCKS_PATTERN_TYPES)) {
uprintf("%sInvalid pattern type\n", bb_prefix);
cancel_ops = -1;
return 0;
}
if ((nb_passes < 1) || (nb_passes > BADBLOCK_PATTERN_COUNT)) {
uprintf("%sInvalid number of passes\n", bb_prefix);
cancel_ops = -1;
return 0;
@ -446,26 +452,31 @@ static unsigned int test_rw(HANDLE hDrive, blk_t last_block, size_t block_size,
return 0;
}
uprintf("%sChecking from block %lu to %lu\n", bb_prefix,
(unsigned long) first_block, (unsigned long) last_block - 1);
uprintf("%sChecking from block %lu to %lu (1 block = %s)\n", bb_prefix,
(unsigned long) first_block, (unsigned long) last_block - 1,
SizeToHumanReadable(BADBLOCK_BLOCK_SIZE, FALSE, FALSE));
nr_pattern = nb_passes;
cur_pattern = 0;
for (pat_idx = 0; pat_idx < nb_passes; pat_idx++) {
srand((unsigned int)GetTickCount64());
if (cancel_ops) goto out;
if (cancel_ops)
goto out;
if (detect_fakes && (pat_idx == 0)) {
srand((unsigned int)GetTickCount64());
id_offset = rand() * (block_size - sizeof(blk_t)) / RAND_MAX;
uprintf("%sUsing offset %d for fake device check\n", bb_prefix, id_offset);
}
// coverity[dont_call]
id_offset = rand() * (block_size-sizeof(blk_t)) / RAND_MAX;
pattern_fill(buffer, pattern[pat_idx], blocks_at_once * block_size);
uprintf("%sUsing offset %d for fake device check\n", bb_prefix, id_offset);
pattern_fill(buffer, pattern[pattern_type][pat_idx], blocks_at_once * block_size);
num_blocks = last_block - 1;
currently_testing = first_block;
if (s_flag | v_flag)
uprintf("%sWriting test pattern 0x%02X\n", bb_prefix, pattern[pat_idx]);
uprintf("%sWriting test pattern 0x%02X\n", bb_prefix, pattern[pattern_type][pat_idx]);
cur_op = OP_WRITE;
tryout = blocks_at_once;
while (currently_testing < last_block) {
if (cancel_ops) goto out;
if (cancel_ops)
goto out;
if (max_bb && bb_count >= max_bb) {
if (s_flag || v_flag) {
uprintf(abort_msg);
@ -477,7 +488,7 @@ static unsigned int test_rw(HANDLE hDrive, blk_t last_block, size_t block_size,
}
if (currently_testing + tryout > last_block)
tryout = last_block - currently_testing;
if (detect_fakes) {
if (detect_fakes && (pat_idx == 0)) {
/* Add the block number at a fixed (random) offset during each pass to
allow for the detection of 'fake' media (eg. 2GB USB masquerading as 16GB) */
for (i=0; i<(int)blocks_at_once; i++) {
@ -525,7 +536,7 @@ static unsigned int test_rw(HANDLE hDrive, blk_t last_block, size_t block_size,
}
if (currently_testing + tryout > last_block)
tryout = last_block - currently_testing;
if (detect_fakes) {
if (detect_fakes && (pat_idx == 0)) {
for (i=0; i<(int)blocks_at_once; i++) {
blk_id = (blk_t*)(intptr_t)(buffer + id_offset+ i*block_size);
*blk_id = (blk_t)(currently_testing + i);
@ -563,11 +574,11 @@ out:
return bb_count;
}
BOOL BadBlocks(HANDLE hPhysicalDrive, ULONGLONG disk_size, size_t block_size,
int nb_passes, badblocks_report *report, FILE* fd)
BOOL BadBlocks(HANDLE hPhysicalDrive, ULONGLONG disk_size, int nb_passes,
int flash_type, badblocks_report *report, FILE* fd)
{
errcode_t error_code;
blk_t first_block = 0, last_block = disk_size/block_size;
blk_t last_block = disk_size / BADBLOCK_BLOCK_SIZE;
if (report == NULL) return FALSE;
num_read_errors = 0;
@ -589,7 +600,7 @@ BOOL BadBlocks(HANDLE hPhysicalDrive, ULONGLONG disk_size, size_t block_size,
cancel_ops = 0;
/* use a timer to update status every second */
SetTimer(hMainDialog, TID_BADBLOCKS_UPDATE, 1000, alarm_intr);
report->bb_count = test_rw(hPhysicalDrive, last_block, block_size, first_block, BB_BLOCKS_AT_ONCE, nb_passes);
report->bb_count = test_rw(hPhysicalDrive, last_block, BADBLOCK_BLOCK_SIZE, 0, BB_BLOCKS_AT_ONCE, flash_type, nb_passes);
KillTimer(hMainDialog, TID_BADBLOCKS_UPDATE);
free(bb_list->list);
free(bb_list);

View file

@ -7,7 +7,7 @@
*
* Copyright 1995, 1996, 1997, 1998, 1999 by Theodore Ts'o
* Copyright 1999 by David Beattie
* Copyright 2011-2013 by Pete Batard
* Copyright 2011-2018 by Pete Batard
*
* This file is based on the minix file system programs fsck and mkfs
* written and copyrighted by Linus Torvalds <Linus.Torvalds@cs.helsinki.fi>
@ -55,5 +55,5 @@ typedef struct {
/*
* Shared prototypes
*/
BOOL BadBlocks(HANDLE hPhysicalDrive, ULONGLONG disk_size, size_t block_size,
int test_type, badblocks_report *report, FILE* fd);
BOOL BadBlocks(HANDLE hPhysicalDrive, ULONGLONG disk_size, int nb_passes,
int flash_type, badblocks_report *report, FILE* fd);

View file

@ -32,6 +32,7 @@
#include <inttypes.h>
#include <commctrl.h>
#include <setupapi.h>
#include <assert.h>
#include "rufus.h"
#include "missing.h"
@ -452,16 +453,12 @@ BOOL GetDevices(DWORD devnum)
if (strcmp(genstor_name[s], "SD") == 0)
card_start = s;
}
// Overkill, but better safe than sorry. And yeah, we could have used
// arrays of arrays to avoid this, but it's more readable this way.
if ((uasp_start <= 0) || (uasp_start >= ARRAYSIZE(usbstor_name))) {
uprintf("Spock gone crazy error in %s:%d", __FILE__, __LINE__);
goto out;
}
if ((card_start <= 0) || (card_start >= ARRAYSIZE(genstor_name))) {
uprintf("Spock gone crazy error in %s:%d", __FILE__, __LINE__);
goto out;
}
// Better safe than sorry. And yeah, we could have used arrays of
// arrays to avoid this, but it's more readable this way.
assert((uasp_start > 0) && (uasp_start < ARRAYSIZE(usbstor_name)));
assert((card_start > 0) && (card_start < ARRAYSIZE(genstor_name)));
devid_list = NULL;
if (full_list_size != 0) {
full_list_size += 1; // add extra NUL terminator

View file

@ -26,6 +26,7 @@
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "rufus.h"
@ -288,8 +289,8 @@ static const char* kb_to_hr(const char* kb)
}
}
// Should never happen, so let's try to get some attention here
MessageBoxA(hMainDialog, "YO BNLA #1", "UHAHAHHA?", MB_OKCANCEL|MB_ICONWARNING);
return "Someone missed a keyboard!";
assert(i < ARRAYSIZE(kb_hr_list));
return NULL;
}
typedef struct {
@ -425,8 +426,8 @@ static const char* cp_to_hr(ULONG cp)
}
}
// Should never happen, so this oughta get some attention
MessageBoxA(hMainDialog, "YO BNLA #2", "UHAHAHHA?", MB_OKCANCEL|MB_ICONWARNING);
return "Someone missed a codepage!";
assert(i < ARRAYSIZE(cp_hr_list));
return NULL;
}
// http://blogs.msdn.com/b/michkap/archive/2004/12/05/275231.aspx

View file

@ -25,6 +25,7 @@
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include "rufus.h"
#include "missing.h"
@ -109,11 +110,9 @@ BOOL GetAutoMount(BOOL* enabled)
* clear the MBR of!), so we mitigate the risk by forcing our indexes to belong to
* the specific range [DRIVE_INDEX_MIN; DRIVE_INDEX_MAX].
*/
#define CheckDriveIndex(DriveIndex) do { \
if ((DriveIndex < DRIVE_INDEX_MIN) || (DriveIndex > DRIVE_INDEX_MAX)) { \
uprintf("ERROR: Bad index value %d. Please check the code!", DriveIndex); \
goto out; \
} \
#define CheckDriveIndex(DriveIndex) do { \
assert((DriveIndex >= DRIVE_INDEX_MIN) && (DriveIndex <= DRIVE_INDEX_MAX)); \
if ((DriveIndex < DRIVE_INDEX_MIN) || (DriveIndex > DRIVE_INDEX_MAX)) goto out; \
DriveIndex -= DRIVE_INDEX_MIN; } while (0)
/*

View file

@ -31,6 +31,7 @@
#include <stddef.h>
#include <ctype.h>
#include <locale.h>
#include <assert.h>
#include "rufus.h"
#include "missing.h"
@ -1856,6 +1857,7 @@ DWORD WINAPI FormatThread(void* param)
if (IsChecked(IDC_BAD_BLOCKS)) {
do {
int sel = ComboBox_GetCurSel(hNBPasses);
// create a log file for bad blocks report. Since %USERPROFILE% may
// have localized characters, we use the UTF-8 API.
userdir = getenvU("USERPROFILE");
@ -1874,8 +1876,8 @@ DWORD WINAPI FormatThread(void* param)
fflush(log_fd);
}
if (!BadBlocks(hPhysicalDrive, SelectedDrive.DiskSize, SelectedDrive.SectorSize,
ComboBox_GetCurSel(hNBPasses)+1, &report, log_fd)) {
if (!BadBlocks(hPhysicalDrive, SelectedDrive.DiskSize, (sel >= 2) ? 4 : sel +1,
(sel < 2) ? 0 : sel - 2, &report, log_fd)) {
uprintf("Bad blocks: Check failed.\n");
if (!IS_ERROR(FormatStatus))
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_BADBLOCKS_FAILURE);
@ -2029,8 +2031,8 @@ DWORD WINAPI FormatThread(void* param)
// All good
} else if (tt == TT_UEFI) {
// For once, no need to do anything - just check our sanity
assert((bt == BT_IMAGE) && IS_EFI_BOOTABLE(img_report) && (fs <= FS_NTFS));
if ( (bt != BT_IMAGE) || !IS_EFI_BOOTABLE(img_report) || (fs > FS_NTFS) ) {
uprintf("Spock gone crazy error in %s:%d", __FILE__, __LINE__);
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INSTALL_FAILURE;
goto out;
}

View file

@ -512,6 +512,22 @@ static __inline int PathGetDriveNumberU(char* lpPath)
return ret;
}
// This one is tricky since we can't blindly convert a
// UTF-16 position to a UTF-8 one. So we do it manually.
static __inline const char* PathFindFileNameU(const char* szPath)
{
size_t i;
if (szPath == NULL)
return NULL;
for (i = strlen(szPath); i != 0; i--) {
if ((szPath[i] == '/') || (szPath[i] == '\\')) {
i++;
break;
}
}
return &szPath[i];
}
// This function differs from regular GetTextExtentPoint in that it uses a zero terminated string
static __inline BOOL GetTextExtentPointU(HDC hdc, const char* lpString, LPSIZE lpSize)
{

261
src/net.c
View file

@ -29,6 +29,7 @@
#include <malloc.h>
#include <string.h>
#include <inttypes.h>
#include <assert.h>
#include "rufus.h"
#include "missing.h"
@ -44,7 +45,6 @@
#define DEFAULT_UPDATE_INTERVAL (24*3600)
DWORD DownloadStatus;
BOOL PromptOnError = TRUE;
extern BOOL force_update;
static DWORD error_code;
@ -216,13 +216,14 @@ const char* WinInetErrorString(void)
}
/*
* Download a file from an URL
* Download a file or fill a buffer from an URL
* Mostly taken from http://support.microsoft.com/kb/234913
* If file is NULL, a buffer is allocated for the download (that needs to be freed by the caller)
* If hProgressDialog is not NULL, this function will send INIT and EXIT messages
* to the dialog in question, with WPARAM being set to nonzero for EXIT on success
* and also attempt to indicate progress using an IDC_PROGRESS control
*/
DWORD DownloadFile(const char* url, const char* file, HWND hProgressDialog)
static DWORD DownloadToFileOrBuffer(const char* url, const char* file, BYTE** buffer, HWND hProgressDialog)
{
HWND hProgressBar = NULL;
BOOL r = FALSE;
@ -234,8 +235,8 @@ DWORD DownloadFile(const char* url, const char* file, HWND hProgressDialog)
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};
size_t last_slash;
int i;
const char* short_name;
size_t i;
// Can't link with wininet.lib because of sideloading issues
PF_TYPE_DECL(WINAPI, BOOL, InternetCrackUrlA, (LPCSTR, DWORD, DWORD, LPURL_COMPONENTSA));
@ -257,7 +258,8 @@ DWORD DownloadFile(const char* url, const char* file, HWND hProgressDialog)
PF_INIT_OR_OUT(HttpSendRequestA, WinInet);
PF_INIT_OR_OUT(HttpQueryInfoA, WinInet);
DownloadStatus = 0;
FormatStatus = 0;
DownloadStatus = 404;
if (hProgressDialog != NULL) {
// Use the progress control provided, if any
hProgressBar = GetDlgItem(hProgressDialog, IDC_PROGRESS);
@ -268,22 +270,18 @@ DWORD DownloadFile(const char* url, const char* file, HWND hProgressDialog)
SendMessage(hProgressDialog, UM_PROGRESS_INIT, 0, 0);
}
if (file == NULL)
goto out;
assert(url != NULL);
for (last_slash = safe_strlen(file); last_slash != 0; last_slash--) {
if ((file[last_slash] == '/') || (file[last_slash] == '\\')) {
last_slash++;
break;
}
short_name = (file != NULL) ? PathFindFileNameU(file) : PathFindFileNameU(url);
if (hProgressDialog != NULL) {
PrintInfo(0, MSG_085, short_name);
uprintf("Downloading %s", url);
}
PrintInfo(0, MSG_085, &file[last_slash]);
uprintf("Downloading '%s' from %s\n", &file[last_slash], url);
if ( (!pfInternetCrackUrlA(url, (DWORD)safe_strlen(url), 0, &UrlParts))
|| (UrlParts.lpszHostName == NULL) || (UrlParts.lpszUrlPath == NULL)) {
uprintf("Unable to decode URL: %s\n", WinInetErrorString());
uprintf("Unable to decode URL: %s", WinInetErrorString());
goto out;
}
hostname[sizeof(hostname)-1] = 0;
@ -295,7 +293,7 @@ DWORD DownloadFile(const char* url, const char* file, HWND hProgressDialog)
if (i <= 0) {
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa384702.aspx is wrong...
SetLastError(ERROR_INTERNET_NOT_INITIALIZED);
uprintf("Network is unavailable: %s\n", WinInetErrorString());
uprintf("Network is unavailable: %s", WinInetErrorString());
goto out;
}
static_sprintf(agent, APPLICATION_NAME "/%d.%d.%d (Windows NT %d.%d%s)",
@ -303,13 +301,13 @@ DWORD DownloadFile(const char* url, const char* file, HWND hProgressDialog)
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\n", WinInetErrorString());
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\n", UrlParts.lpszHostName, UrlParts.nPort, WinInetErrorString());
uprintf("Could not connect to server %s:%d: %s", UrlParts.lpszHostName, UrlParts.nPort, WinInetErrorString());
goto out;
}
@ -318,84 +316,97 @@ DWORD DownloadFile(const char* url, const char* file, HWND hProgressDialog)
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\n", url, WinInetErrorString());
uprintf("Could not open URL %s: %s", url, WinInetErrorString());
goto out;
}
if (!pfHttpSendRequestA(hRequest, NULL, 0, NULL, 0)) {
uprintf("Unable to send request: %s\n", WinInetErrorString());
uprintf("Unable to send request: %s", WinInetErrorString());
goto out;
}
// Get the file size
dwSize = sizeof(DownloadStatus);
DownloadStatus = 404;
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\n", DownloadStatus);
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\n", WinInetErrorString());
uprintf("Unable to retrieve file length: %s", WinInetErrorString());
goto out;
}
uprintf("File length: %d bytes\n", dwTotalSize);
if (hProgressDialog != NULL)
uprintf("File length: %d bytes", dwTotalSize);
hFile = CreateFileU(file, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
uprintf("Unable to create file '%s': %s\n", &file[last_slash], WinInetErrorString());
goto out;
if (file != NULL) {
hFile = CreateFileU(file, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
uprintf("Unable to create file '%s': %s", short_name, WinInetErrorString());
goto out;
}
} else {
if (buffer == NULL) {
uprintf("No buffer pointer provided for download");
goto out;
}
*buffer = malloc(dwTotalSize);
if (*buffer == NULL) {
uprintf("Could not allocate buffer for download");
goto out;
}
}
// Keep checking for data until there is nothing left.
dwSize = 0;
while (1) {
// User may have cancelled the download
if (IS_ERROR(FormatStatus))
goto out;
if (!pfInternetReadFile(hRequest, buf, sizeof(buf), &dwDownloaded) || (dwDownloaded == 0))
break;
dwSize += dwDownloaded;
SendMessage(hProgressBar, PBM_SETPOS, (WPARAM)(MAX_PROGRESS*((1.0f*dwSize)/(1.0f*dwTotalSize))), 0);
PrintInfo(0, MSG_241, (100.0f*dwSize)/(1.0f*dwTotalSize));
if (!WriteFile(hFile, buf, dwDownloaded, &dwWritten, NULL)) {
uprintf("Error writing file '%s': %s\n", &file[last_slash], WinInetErrorString());
goto out;
} else if (dwDownloaded != dwWritten) {
uprintf("Error writing file '%s': Only %d/%d bytes written\n", dwWritten, dwDownloaded);
goto out;
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));
}
if (file != NULL) {
if (!WriteFile(hFile, buf, dwDownloaded, &dwWritten, NULL)) {
uprintf("Error writing file '%s': %s", short_name, WinInetErrorString());
goto out;
} else if (dwDownloaded != dwWritten) {
uprintf("Error writing file '%s': Only %d/%d bytes written", short_name, dwWritten, dwDownloaded);
goto out;
}
} else {
memcpy(&(*buffer)[dwSize], buf, dwDownloaded);
}
dwSize += dwDownloaded;
}
if (dwSize != dwTotalSize) {
uprintf("Could not download complete file - read: %d bytes, expected: %d bytes\n", dwSize, dwTotalSize);
uprintf("Could not download complete file - read: %d bytes, expected: %d bytes", dwSize, dwTotalSize);
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT;
goto out;
} else {
DownloadStatus = 200;
r = TRUE;
uprintf("Successfully downloaded '%s'\n", &file[last_slash]);
if (hProgressDialog != NULL) {
uprintf("Successfully downloaded '%s'", short_name);
SendMessage(hProgressBar, PBM_SETPOS, (WPARAM)MAX_PROGRESS, 0);
PrintInfo(0, MSG_241, 100.0f);
}
}
out:
if (hProgressDialog != NULL)
SendMessage(hProgressDialog, UM_PROGRESS_EXIT, (WPARAM)r, 0);
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) {
if (file != NULL)
_unlinkU(file);
if (PromptOnError) {
PrintInfo(0, MSG_242);
SetLastError(error_code);
MessageBoxExU(hMainDialog, IS_ERROR(FormatStatus)?StrError(FormatStatus, FALSE):WinInetErrorString(),
lmprintf(MSG_044), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid);
}
}
if ((!r) && (file != NULL))
_unlinkU(file);
if (hRequest)
pfInternetCloseHandle(hRequest);
if (hConnection)
@ -403,23 +414,95 @@ out:
if (hSession)
pfInternetCloseHandle(hSession);
return r?dwSize:0;
return r ? dwSize : 0;
}
// Download and validate a signed file. The file must have a corresponding '.sig' on the server.
DWORD DownloadSignedFile(const char* url, const char* file, HWND hProgressDialog, BOOL bPromptOnError)
{
char* url_sig = NULL;
BYTE *buf = NULL, *sig = NULL;
DWORD buf_len = 0, sig_len = 0;
DWORD ret = 0;
HANDLE hFile = INVALID_HANDLE_VALUE;
assert(url != NULL);
url_sig = malloc(strlen(url) + 5);
if (url_sig == NULL) {
uprintf("Could not allocate signature URL");
goto out;
}
strcpy(url_sig, url);
strcat(url_sig, ".sig");
buf_len = DownloadToFileOrBuffer(url, NULL, &buf, hProgressDialog);
if (buf_len == 0)
goto out;
sig_len = 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
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_BAD_SIGNATURE);
goto out;
}
uprintf("Download signature is valid ✓");
DownloadStatus = 206; // Partial content
hFile = CreateFileU(file, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
uprintf("Unable to create file '%s': %s", PathFindFileNameU(file), WinInetErrorString());
goto out;
}
if (!WriteFile(hFile, buf, buf_len, &ret, NULL)) {
uprintf("Error writing file '%s': %s", PathFindFileNameU(file), WinInetErrorString());
ret = 0;
goto out;
} else if (ret != buf_len) {
uprintf("Error writing file '%s': Only %d/%d bytes written", PathFindFileNameU(file), ret, buf_len);
ret = 0;
goto out;
}
DownloadStatus = 200; // Full content
out:
if (hProgressDialog != NULL)
SendMessage(hProgressDialog, UM_PROGRESS_EXIT, (WPARAM)ret, 0);
if ((bPromptOnError) && (DownloadStatus != 200)) {
PrintInfo(0, MSG_242);
SetLastError(error_code);
MessageBoxExU(hMainDialog, IS_ERROR(FormatStatus) ? StrError(FormatStatus, FALSE) : WinInetErrorString(),
lmprintf(MSG_044), MB_OK | MB_ICONERROR | MB_IS_RTL, selected_langid);
}
safe_closehandle(hFile);
free(url_sig);
free(buf);
free(sig);
return ret;
}
/* Threaded download */
static const char *_url, *_file;
static HWND _hProgressDialog;
static DWORD WINAPI _DownloadFileThread(LPVOID param)
typedef struct {
const char* url;
const char* file;
HWND hProgressDialog;
BOOL bPromptOnError;
} DownloadSignedFileThreadArgs;
static DWORD WINAPI DownloadSignedFileThread(LPVOID param)
{
ExitThread(DownloadFile(_url, _file, _hProgressDialog) != 0);
DownloadSignedFileThreadArgs* args = (DownloadSignedFileThreadArgs*)param;
ExitThread(DownloadSignedFile(args->url, args->file, args->hProgressDialog, args->bPromptOnError));
}
HANDLE DownloadFileThreaded(const char* url, const char* file, HWND hProgressDialog)
HANDLE DownloadSignedFileThreaded(const char* url, const char* file, HWND hProgressDialog, BOOL bPromptOnError)
{
_url = url;
_file = file;
_hProgressDialog = hProgressDialog;
return CreateThread(NULL, 0, _DownloadFileThread, NULL, 0, NULL);
static DownloadSignedFileThreadArgs args;
args.url = url;
args.file = file;
args.hProgressDialog = hProgressDialog;
args.bPromptOnError = bPromptOnError;
return CreateThread(NULL, 0, DownloadSignedFileThread, &args, 0, NULL);
}
static __inline uint64_t to_uint64_t(uint16_t x[4]) {
@ -443,8 +526,9 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
static const char* channel[] = {"release", "beta", "test"}; // release channel
const char* accept_types[] = {"*/*\0", NULL};
DWORD dwFlags, dwSize, dwDownloaded, dwTotalSize, dwStatus;
BYTE *sig = NULL;
char* buf = NULL;
char agent[64], hostname[64], urlpath[128], mime[32];
char agent[64], hostname[64], urlpath[128], sigpath[256], mime[32];
OSVERSIONINFOA os_version = {sizeof(OSVERSIONINFOA), 0, 0, 0, 0, ""};
HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL;
URL_COMPONENTSA UrlParts = {sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0,
@ -487,7 +571,7 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
} while ((!force_update_check) && ((iso_op_in_progress || format_op_in_progress || (dialog_showing>0))));
if (!force_update_check) {
if ((ReadSetting32(SETTING_UPDATE_INTERVAL) == -1)) {
vuprintf("Check for updates disabled, as per settings.\n");
vuprintf("Check for updates disabled, as per settings.");
goto out;
}
reg_time = ReadSetting64(SETTING_LAST_UPDATE);
@ -500,9 +584,9 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
if (!SystemTimeToFileTime(&LocalTime, &FileTime))
goto out;
local_time = ((((int64_t)FileTime.dwHighDateTime)<<32) + FileTime.dwLowDateTime) / 10000000;
vvuprintf("Local time: %" PRId64 "\n", local_time);
vvuprintf("Local time: %" PRId64, local_time);
if (local_time < reg_time + update_interval) {
vuprintf("Next update check in %" PRId64 " seconds.\n", reg_time + update_interval - local_time);
vuprintf("Next update check in %" PRId64 " seconds.", reg_time + update_interval - local_time);
goto out;
}
}
@ -512,7 +596,7 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
status++; // 1
if (!GetVersionExA(&os_version)) {
uprintf("Could not read Windows version - Check for updates cancelled.\n");
uprintf("Could not read Windows version - Check for updates cancelled.");
goto out;
}
@ -540,7 +624,7 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
max_channel = releases_only ? 1 : (int)ARRAYSIZE(channel) - 1;
#endif
for (k=0; (k<max_channel) && (!found_new_version); k++) {
uprintf("Checking %s channel...\n", channel[k]);
uprintf("Checking %s channel...", channel[k]);
// At this stage we can query the server for various update version files.
// We first try to lookup for "<appname>_<os_arch>_<os_version_major>_<os_version_minor>.ver"
// and then remove each each of the <os_> components until we find our match. For instance, we may first
@ -548,21 +632,18 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
// This allows sunsetting OS versions (eg XP) or providing different downloads for different archs/groups.
static_sprintf(urlpath, "%s%s%s_%s_%lu.%lu.ver", APPLICATION_NAME, (k==0)?"":"_",
(k==0)?"":channel[k], archname[is_x64()?1:0], os_version.dwMajorVersion, os_version.dwMinorVersion);
vuprintf("Base update check: %s\n", urlpath);
vuprintf("Base update check: %s", urlpath);
for (i=0, j=(int)safe_strlen(urlpath)-5; (j>0)&&(i<ARRAYSIZE(verpos)); j--) {
if ((urlpath[j] == '.') || (urlpath[j] == '_')) {
verpos[i++] = j;
}
}
if (i != ARRAYSIZE(verpos)) {
uprintf("Broken code in CheckForUpdatesThread()!\n");
goto out;
}
assert(i == ARRAYSIZE(verpos));
UrlParts.lpszUrlPath = urlpath;
UrlParts.dwUrlPathLength = sizeof(urlpath);
for (i=0; i<ARRAYSIZE(verpos); i++) {
vvuprintf("Trying %s\n", UrlParts.lpszUrlPath);
vvuprintf("Trying %s", UrlParts.lpszUrlPath);
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|
@ -607,7 +688,7 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
|| (!SystemTimeToFileTime(&ServerTime, &FileTime)) )
goto out;
server_time = ((((int64_t)FileTime.dwHighDateTime)<<32) + FileTime.dwLowDateTime) / 10000000;
vvuprintf("Server time: %" PRId64 "\n", server_time);
vvuprintf("Server time: %" PRId64, server_time);
// Always store the server response time - the only clock we trust!
WriteSetting64(SETTING_LAST_UPDATE, server_time);
// Might as well let the user know
@ -625,29 +706,39 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
safe_free(buf);
// Make sure the file is NUL terminated
buf = (char*)calloc(dwTotalSize+1, 1);
if (buf == NULL) goto out;
if (buf == NULL)
goto out;
// This is a version file - we should be able to gulp it down in one go
if (!pfInternetReadFile(hRequest, buf, dwTotalSize, &dwDownloaded) || (dwDownloaded != dwTotalSize))
goto out;
vuprintf("Successfully downloaded version file (%d bytes)", dwTotalSize);
// Now download the signature file
static_sprintf(sigpath, "%s/%s.sig", server_url, urlpath);
dwDownloaded = DownloadToFileOrBuffer(sigpath, NULL, &sig, NULL);
if ((dwDownloaded != RSA_SIGNATURE_SIZE) || (!ValidateOpensslSignature(buf, dwTotalSize, sig, dwDownloaded))) {
uprintf("FATAL: Version signature is invalid!");
goto out;
}
vuprintf("Version signature is valid");
status++;
vuprintf("Successfully downloaded version file (%d bytes)\n", dwTotalSize);
parse_update(buf, dwTotalSize+1);
vuprintf("UPDATE DATA:\n");
vuprintf(" version: %d.%d.%d (%s)\n", update.version[0], update.version[1], update.version[2], channel[k]);
vuprintf(" platform_min: %d.%d\n", update.platform_min[0], update.platform_min[1]);
vuprintf(" url: %s\n", update.download_url);
vuprintf("UPDATE DATA:");
vuprintf(" version: %d.%d.%d (%s)", update.version[0], update.version[1], update.version[2], channel[k]);
vuprintf(" platform_min: %d.%d", update.platform_min[0], update.platform_min[1]);
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\n", found_new_version?"":"o n", channel[k], found_new_version?'!':'.');
uprintf("N%sew %s version found%c", found_new_version?"":"o n", channel[k], found_new_version?'!':'.');
}
out:
safe_free(buf);
safe_free(sig);
if (hRequest)
pfInternetCloseHandle(hRequest);
if (hConnection)

146
src/pki.c
View file

@ -27,6 +27,7 @@
#include <stdio.h>
#include <wincrypt.h>
#include <wintrust.h>
#include <assert.h>
#include "rufus.h"
#include "resource.h"
@ -52,6 +53,63 @@ typedef struct {
LPWSTR lpszMoreInfoLink;
} SPROG_PUBLISHERINFO, *PSPROG_PUBLISHERINFO;
// https://msdn.microsoft.com/en-us/library/ee442238.aspx
typedef struct {
BLOBHEADER BlobHeader;
RSAPUBKEY RsaHeader;
BYTE Modulus[256]; // 2048 bit modulus
} RSA_2048_PUBKEY;
// The RSA public key modulus for the private key we use to sign the files on the server.
// NOTE 1: This openssl modulus must be *REVERSED* to be usable with Microsoft APIs
// NOTE 2: Also, this modulus is 2052 bits, and not 2048, because openssl adds an extra
// 0x00 at the beginning to force an integer sign. These extra 8 bits *MUST* be removed.
static uint8_t rsa_pubkey_modulus[] = {
/*
$ openssl genrsa -aes256 -out private.pem 2048
$ openssl rsa -in private.pem -pubout -out public.pem
$ openssl rsa -pubin -inform PEM -text -noout < public.pem
Public-Key: (2048 bit)
Modulus:
00:b6:40:7d:d1:98:7b:81:9e:be:23:0f:32:5d:55:
60:c6:bf:b4:41:bb:43:1b:f1:e1:e6:f9:2b:d6:dd:
11:50:e8:b9:3f:19:97:5e:a7:8b:4a:30:c6:76:58:
72:1c:ac:ff:a1:f8:96:6c:51:5d:13:11:e3:5b:11:
82:f5:9a:69:e4:28:97:0f:ca:1f:02:ea:1f:7d:dc:
f9:fc:79:2f:61:ff:8e:45:60:65:ba:37:9b:de:49:
05:6a:a8:fd:70:d0:0c:79:b6:d7:81:aa:54:c3:c6:
4a:87:a0:45:ee:ca:d5:d5:c5:c2:ac:86:42:b3:58:
27:d2:43:b9:37:f2:e6:75:66:17:53:d0:38:d0:c6:
57:c2:55:36:a2:43:87:ea:24:f0:96:ec:34:dd:79:
4d:80:54:9d:84:81:a7:cf:0c:a5:7c:d6:63:fa:7a:
66:30:a9:50:ee:f0:e5:f8:a2:2d:ac:fc:24:21:fe:
ef:e8:d3:6f:0e:27:b0:64:22:95:3e:6d:a6:66:97:
c6:98:c2:47:b3:98:69:4d:b1:b5:d3:6f:43:f5:d7:
a5:13:5e:8c:28:4f:62:4e:01:48:0a:63:89:e7:ca:
34:aa:7d:2f:bb:70:e0:31:bb:39:49:a3:d2:c9:2e:
a6:30:54:9a:5c:4d:58:17:d9:fc:3a:43:e6:8e:2a:
18:e9
Exponent: 65537 (0x10001)
*/
0x00, 0xb6, 0x40, 0x7d, 0xd1, 0x98, 0x7b, 0x81, 0x9e, 0xbe, 0x23, 0x0f, 0x32, 0x5d, 0x55,
0x60, 0xc6, 0xbf, 0xb4, 0x41, 0xbb, 0x43, 0x1b, 0xf1, 0xe1, 0xe6, 0xf9, 0x2b, 0xd6, 0xdd,
0x11, 0x50, 0xe8, 0xb9, 0x3f, 0x19, 0x97, 0x5e, 0xa7, 0x8b, 0x4a, 0x30, 0xc6, 0x76, 0x58,
0x72, 0x1c, 0xac, 0xff, 0xa1, 0xf8, 0x96, 0x6c, 0x51, 0x5d, 0x13, 0x11, 0xe3, 0x5b, 0x11,
0x82, 0xf5, 0x9a, 0x69, 0xe4, 0x28, 0x97, 0x0f, 0xca, 0x1f, 0x02, 0xea, 0x1f, 0x7d, 0xdc,
0xf9, 0xfc, 0x79, 0x2f, 0x61, 0xff, 0x8e, 0x45, 0x60, 0x65, 0xba, 0x37, 0x9b, 0xde, 0x49,
0x05, 0x6a, 0xa8, 0xfd, 0x70, 0xd0, 0x0c, 0x79, 0xb6, 0xd7, 0x81, 0xaa, 0x54, 0xc3, 0xc6,
0x4a, 0x87, 0xa0, 0x45, 0xee, 0xca, 0xd5, 0xd5, 0xc5, 0xc2, 0xac, 0x86, 0x42, 0xb3, 0x58,
0x27, 0xd2, 0x43, 0xb9, 0x37, 0xf2, 0xe6, 0x75, 0x66, 0x17, 0x53, 0xd0, 0x38, 0xd0, 0xc6,
0x57, 0xc2, 0x55, 0x36, 0xa2, 0x43, 0x87, 0xea, 0x24, 0xf0, 0x96, 0xec, 0x34, 0xdd, 0x79,
0x4d, 0x80, 0x54, 0x9d, 0x84, 0x81, 0xa7, 0xcf, 0x0c, 0xa5, 0x7c, 0xd6, 0x63, 0xfa, 0x7a,
0x66, 0x30, 0xa9, 0x50, 0xee, 0xf0, 0xe5, 0xf8, 0xa2, 0x2d, 0xac, 0xfc, 0x24, 0x21, 0xfe,
0xef, 0xe8, 0xd3, 0x6f, 0x0e, 0x27, 0xb0, 0x64, 0x22, 0x95, 0x3e, 0x6d, 0xa6, 0x66, 0x97,
0xc6, 0x98, 0xc2, 0x47, 0xb3, 0x98, 0x69, 0x4d, 0xb1, 0xb5, 0xd3, 0x6f, 0x43, 0xf5, 0xd7,
0xa5, 0x13, 0x5e, 0x8c, 0x28, 0x4f, 0x62, 0x4e, 0x01, 0x48, 0x0a, 0x63, 0x89, 0xe7, 0xca,
0x34, 0xaa, 0x7d, 0x2f, 0xbb, 0x70, 0xe0, 0x31, 0xbb, 0x39, 0x49, 0xa3, 0xd2, 0xc9, 0x2e,
0xa6, 0x30, 0x54, 0x9a, 0x5c, 0x4d, 0x58, 0x17, 0xd9, 0xfc, 0x3a, 0x43, 0xe6, 0x8e, 0x2a,
0x18, 0xe9
};
/*
* FormatMessage does not handle PKI errors
@ -65,8 +123,19 @@ const char* WinPKIErrorString(void)
return WindowsErrorString();
switch (error_code) {
// See also https://docs.microsoft.com/en-gb/windows/desktop/com/com-error-codes-4
case NTE_BAD_UID:
return "Bad UID.";
case NTE_NO_KEY:
return "Key does not exist.";
case NTE_BAD_KEYSET:
return "Keyset does not exist.";
case NTE_BAD_ALGID:
return "Invalid algorithm specified.";
case NTE_BAD_VER:
return "Bad version of provider.";
case NTE_BAD_SIGNATURE:
return "Invalid Signature.";
case CRYPT_E_MSG_ERROR:
return "An error occurred while performing an operation on a cryptographic message.";
case CRYPT_E_UNKNOWN_ALGO:
@ -581,3 +650,80 @@ LONG ValidateSignature(HWND hDlg, const char* path)
return r;
}
// Why-oh-why am I the only one on github doing this openssl vs MS signature validation?!?
// For once, I'd like to find code samples from *OTHER PEOPLE* who went through this ordeal first...
BOOL ValidateOpensslSignature(BYTE* pbBuffer, DWORD dwBufferLen, BYTE* pbSignature, DWORD dwSigLen)
{
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
HCRYPTKEY hPubKey;
// We could load and convert an openssl PEM, but since we know what we need...
RSA_2048_PUBKEY pbMyPubKey = {
{ PUBLICKEYBLOB, CUR_BLOB_VERSION, 0, CALG_RSA_KEYX },
// $ openssl genrsa -aes256 -out private.pem 2048
// Generating RSA private key, 2048 bit long modulus
// e is 65537 (0x010001)
// => 0x010001 below. Also 0x31415352 = "RSA1"
{ 0x31415352, sizeof(pbMyPubKey.Modulus) * 8, 0x010001 },
{ 0 } // Modulus is initialized below
};
USHORT dwMyPubKeyLen = sizeof(pbMyPubKey);
BOOL r;
BYTE t;
int i, j;
// Get a handle to the default PROV_RSA_AES provider (AES so we get SHA-256 support).
// 2 passes in case we need to create a new container.
r = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_NEWKEYSET | CRYPT_VERIFYCONTEXT);
if (!r) {
uprintf("PKI: Could not create the default key container: %s", WinPKIErrorString());
goto out;
}
// Reverse the modulus bytes from openssl (and also remove the extra unwanted 0x00)
assert(sizeof(rsa_pubkey_modulus) >= sizeof(pbMyPubKey.Modulus));
for (i = 0; i < sizeof(pbMyPubKey.Modulus); i++)
pbMyPubKey.Modulus[i] = rsa_pubkey_modulus[sizeof(rsa_pubkey_modulus) -1 - i];
// Import our RSA public key so that the MS API can use it
r = CryptImportKey(hProv, (BYTE*)&pbMyPubKey.BlobHeader, dwMyPubKeyLen, 0, 0, &hPubKey);
if (!r) {
uprintf("Could not import public key: %s", WinPKIErrorString());
goto out;
}
// Create the hash object.
r = CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash);
if (!r) {
uprintf("Could not create empty hash: %s", WinPKIErrorString());
goto out;
}
// Compute the cryptographic hash of the buffer.
r = CryptHashData(hHash, pbBuffer, dwBufferLen, 0);
if (!r) {
uprintf("Could not hash data: %s", WinPKIErrorString());
goto out;
}
// Reverse the signature bytes
for (i = 0, j = dwSigLen - 1; i < j; i++, j--) {
t = pbSignature[i];
pbSignature[i] = pbSignature[j];
pbSignature[j] = t;
}
// Now that we have all of the public key, hash and signature data in a
// format that Microsoft can handle, we can call CryptVerifySignature().
r = CryptVerifySignature(hHash, pbSignature, dwSigLen, hPubKey, NULL, 0);
if (!r)
uprintf("Signature validation failed: %s", WinPKIErrorString());
out:
if (hHash)
CryptDestroyHash(hHash);
if (hProv)
CryptReleaseContext(hProv, 0);
return r;
}

View file

@ -35,6 +35,7 @@
#include <dbt.h>
#include <io.h>
#include <getopt.h>
#include <assert.h>
#include "rufus.h"
#include "missing.h"
@ -51,6 +52,7 @@
static const char* cmdline_hogger = "rufus.com";
static const char* FileSystemLabel[FS_MAX] = { "FAT", "FAT32", "NTFS", "UDF", "exFAT", "ReFS" };
static const char* flash_type[BADLOCKS_PATTERN_TYPES] = { "SLC", "MLC", "TLC" };
static const char* ep_reg = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer";
static const char* vs_reg = "Software\\Microsoft\\VisualStudio";
// Number of steps for each FS for FCC_STRUCTURE_PROGRESS
@ -1165,9 +1167,12 @@ static __inline void MoveCtrlY(HWND hDlg, int nID, int vertical_shift) {
static void SetPassesTooltip(void)
{
const unsigned char pattern[] = BADBLOCK_PATTERNS;
CreateTooltip(hNBPasses, lmprintf(MSG_153 + ComboBox_GetCurSel(hNBPasses),
pattern[0], pattern[1], pattern[2], pattern[3]), -1);
const unsigned int pattern[BADLOCKS_PATTERN_TYPES][BADBLOCK_PATTERN_COUNT] =
{ BADBLOCK_PATTERN_SLC, BADCLOCK_PATTERN_MLC, BADBLOCK_PATTERN_TLC };
int sel = ComboBox_GetCurSel(hNBPasses);
int type = (sel < 2) ? 0 : sel - 2;
CreateTooltip(hNBPasses, lmprintf(MSG_153 + ((sel >= 2) ? 3 : sel),
pattern[type][0], pattern[type][1], pattern[type][2], pattern[type][3]), -1);
}
static void ResizeDialogs(int shift)
@ -1341,14 +1346,13 @@ static void UpdateImage(void)
}
}
if (image_path != NULL) {
ComboBox_DeleteString(hBootType, index);
ComboBox_InsertStringU(hBootType, index, short_image_path);
ComboBox_SetItemData(hBootType, index, BT_IMAGE);
IGNORE_RETVAL(ComboBox_SetCurSel(hBootType, index));
bt = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType));
SetBootTypeDropdownWidth();
}
ComboBox_DeleteString(hBootType, index);
ComboBox_InsertStringU(hBootType, index,
(image_path == NULL) ? lmprintf(MSG_281, lmprintf(MSG_280)) : short_image_path);
ComboBox_SetItemData(hBootType, index, BT_IMAGE);
IGNORE_RETVAL(ComboBox_SetCurSel(hBootType, index));
bt = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType));
SetBootTypeDropdownWidth();
}
// The scanning process can be blocking for message processing => use a thread
@ -1358,6 +1362,7 @@ DWORD WINAPI ISOScanThread(LPVOID param)
if (image_path == NULL)
goto out;
format_op_in_progress = TRUE;
PrintInfoDebug(0, MSG_202);
user_notified = FALSE;
EnableControls(FALSE);
@ -1365,15 +1370,16 @@ DWORD WINAPI ISOScanThread(LPVOID param)
img_report.is_iso = (BOOLEAN)ExtractISO(image_path, "", TRUE);
img_report.is_bootable_img = (BOOLEAN)IsBootableImage(image_path);
if ((img_report.image_size == 0) || (!img_report.is_iso && !img_report.is_bootable_img)) {
if (IS_ERROR(FormatStatus) || (img_report.image_size == 0) || (!img_report.is_iso && !img_report.is_bootable_img)) {
// Failed to scan image
SendMessage(hMainDialog, UM_PROGRESS_EXIT, 0, 0);
safe_free(image_path);
EnableControls(TRUE);
UpdateImage();
SetMBRProps();
PopulateProperties();
PrintInfoDebug(0, MSG_203);
PrintStatus(0, MSG_203);
EnableControls(TRUE);
goto out;
}
@ -1435,15 +1441,18 @@ DWORD WINAPI ISOScanThread(LPVOID param)
out:
dont_display_image_name = FALSE;
format_op_in_progress = FALSE;
PrintInfo(0, MSG_210);
ExitThread(0);
}
static BOOL BootCheck(void)
// Likewise, boot check will block message processing => use a thread
static DWORD WINAPI BootCheckThread(LPVOID param)
{
int i, r;
FILE *fd;
DWORD len;
WPARAM ret = -1;
BOOL in_files_dir = FALSE;
const char* grub = "grub";
const char* core_img = "core.img";
@ -1454,34 +1463,42 @@ static BOOL BootCheck(void)
syslinux_ldlinux_len[0] = 0; syslinux_ldlinux_len[1] = 0;
safe_free(grub2_buf);
if (ComboBox_GetCurSel(hDeviceList) == CB_ERR)
goto out;
if ((zero_drive) || (bt == BT_NON_BOOTABLE)) {
// Nothing to check
ret = 0;
goto out;
}
if (bt == BT_IMAGE) {
// We should never be there
if (image_path == NULL) {
uprintf("Spock gone crazy error in %s:%d", __FILE__, __LINE__);
MessageBoxExU(hMainDialog, "image_path is NULL. Please report this error to the author of this application", "Logic error", MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid);
return FALSE;
}
assert(image_path != NULL);
if (image_path == NULL)
goto out;
if ((size_check) && (img_report.projected_size > (uint64_t)SelectedDrive.DiskSize)) {
// This ISO image is too big for the selected target
MessageBoxExU(hMainDialog, lmprintf(MSG_089), lmprintf(MSG_088), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid);
return FALSE;
goto out;
}
if (IS_DD_BOOTABLE(img_report) && !img_report.is_iso) {
// Pure DD images are fine at this stage
return TRUE;
ret = 0;
goto out;
}
if ((display_togo_option) && (ComboBox_GetCurSel(GetDlgItem(hMainDialog, IDC_IMAGE_OPTION)) == 1)) {
if (fs != FS_NTFS) {
// Windows To Go only works for NTFS
MessageBoxExU(hMainDialog, lmprintf(MSG_097, "Windows To Go"), lmprintf(MSG_092), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid);
return FALSE;
goto out;
}
if (SelectedDrive.MediaType != FixedMedia) {
if ((tt == TT_UEFI) && (pt == PARTITION_STYLE_GPT) && (nWindowsBuildNumber < 15000)) {
// Up to Windows 10 Creators Update, we were screwed, since we need access to 2 partitions at the same time.
// Thankfully, the newer Windows allow mounting multiple partitions on the same REMOVABLE drive.
MessageBoxExU(hMainDialog, lmprintf(MSG_198), lmprintf(MSG_190), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid);
return FALSE;
goto out;
}
}
// If multiple versions are available, asks the user to select one before we commit to format the drive
@ -1490,7 +1507,7 @@ static BOOL BootCheck(void)
MessageBoxExU(hMainDialog, lmprintf(MSG_073), lmprintf(MSG_291), MB_OK | MB_ICONERROR | MB_IS_RTL, selected_langid);
// fall through
case -2:
return FALSE;
goto out;
default:
break;
}
@ -1498,13 +1515,13 @@ static BOOL BootCheck(void)
if (!IS_EFI_BOOTABLE(img_report)) {
// Unsupported ISO
MessageBoxExU(hMainDialog, lmprintf(MSG_091), lmprintf(MSG_090), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid);
return FALSE;
goto out;
}
if (HAS_WIN7_EFI(img_report) && (!WimExtractCheck())) {
// Your platform cannot extract files from WIM archives => download 7-zip?
if (MessageBoxExU(hMainDialog, lmprintf(MSG_102), lmprintf(MSG_101), MB_YESNO|MB_ICONERROR|MB_IS_RTL, selected_langid) == IDYES)
ShellExecuteA(hMainDialog, "open", SEVENZIP_URL, NULL, NULL, SW_SHOWNORMAL);
return FALSE;
goto out;
}
} else if ( ((fs == FS_NTFS) && !HAS_WINDOWS(img_report) && !HAS_GRUB(img_report) &&
(!HAS_SYSLINUX(img_report) || (SL_MAJOR(img_report.sl_version) <= 5)))
@ -1513,16 +1530,16 @@ static BOOL BootCheck(void)
|| ((IS_FAT(fs)) && (HAS_WINDOWS(img_report) || HAS_INSTALL_WIM(img_report)) && (!allow_dual_uefi_bios)) ) {
// Incompatible FS and ISO
MessageBoxExU(hMainDialog, lmprintf(MSG_096), lmprintf(MSG_092), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid);
return FALSE;
goto out;
} else if ((fs == FS_FAT16) && HAS_KOLIBRIOS(img_report)) {
// KolibriOS doesn't support FAT16
MessageBoxExU(hMainDialog, lmprintf(MSG_189), lmprintf(MSG_099), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid);
return FALSE;
goto out;
}
if ((IS_FAT(fs)) && (img_report.has_4GB_file)) {
// This ISO image contains a file larger than 4GB file (FAT32)
MessageBoxExU(hMainDialog, lmprintf(MSG_100), lmprintf(MSG_099), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid);
return FALSE;
goto out;
}
// If the selected target doesn't include include BIOS, skip file downloads for GRUB/Syslinux
@ -1557,15 +1574,13 @@ static BOOL BootCheck(void)
r = MessageBoxExU(hMainDialog, lmprintf(MSG_116, img_report.grub2_version, GRUB2_PACKAGE_VERSION),
lmprintf(MSG_115), MB_YESNOCANCEL|MB_ICONWARNING|MB_IS_RTL, selected_langid);
if (r == IDCANCEL)
return FALSE;
goto out;
else if (r == IDYES) {
static_sprintf(tmp, "%s-%s", grub, img_report.grub2_version);
IGNORE_RETVAL(_mkdir(tmp));
IGNORE_RETVAL(_chdir(tmp));
static_sprintf(tmp, "%s/%s-%s/%s", FILES_URL, grub, img_report.grub2_version, core_img);
PromptOnError = FALSE;
grub2_len = (long)DownloadFile(tmp, core_img, hMainDialog);
PromptOnError = TRUE;
grub2_len = (long)DownloadSignedFile(tmp, core_img, hMainDialog, FALSE);
if ((grub2_len == 0) && (DownloadStatus == 404)) {
// Couldn't locate the file on the server => try to download without the version extra
uprintf("Extended version was not found, trying main version...");
@ -1574,9 +1589,7 @@ static BOOL BootCheck(void)
for (i = 0; ((tmp2[i] >= '0') && (tmp2[i] <= '9')) || (tmp2[i] == '.'); i++);
tmp2[i] = 0;
static_sprintf(tmp, "%s/%s-%s/%s", FILES_URL, grub, tmp2, core_img);
PromptOnError = FALSE;
grub2_len = (long)DownloadFile(tmp, core_img, hMainDialog);
PromptOnError = TRUE;
grub2_len = (long)DownloadSignedFile(tmp, core_img, hMainDialog, FALSE);
static_sprintf(tmp, "%s/%s-%s/%s", FILES_URL, grub, img_report.grub2_version, core_img);
}
if (grub2_len <= 0) {
@ -1621,10 +1634,10 @@ static BOOL BootCheck(void)
static_sprintf(tmp, "%s-%s", syslinux, embedded_sl_version_str[0]);
IGNORE_RETVAL(_mkdir(tmp));
static_sprintf(tmp, "%s/%s-%s/%s", FILES_URL, syslinux, embedded_sl_version_str[0], old_c32_name[i]);
len = DownloadFile(tmp, &tmp[sizeof(FILES_URL)], hMainDialog);
len = DownloadSignedFile(tmp, &tmp[sizeof(FILES_URL)], hMainDialog, TRUE);
if (len == 0) {
uprintf("Could not download file - cancelling");
return FALSE;
goto out;
}
use_own_c32[i] = TRUE;
}
@ -1657,7 +1670,7 @@ static BOOL BootCheck(void)
embedded_sl_version_str[1], embedded_sl_version_ext[1]),
lmprintf(MSG_115), MB_YESNO|MB_ICONWARNING|MB_IS_RTL, selected_langid);
if (r != IDYES)
return FALSE;
goto out;
for (i=0; i<2; i++) {
static_sprintf(tmp, "%s-%s", syslinux, img_report.sl_version_str);
IGNORE_RETVAL(_mkdir(tmp));
@ -1668,15 +1681,15 @@ static BOOL BootCheck(void)
}
static_sprintf(tmp, "%s/%s-%s%s/%s.%s", FILES_URL, syslinux, img_report.sl_version_str,
img_report.sl_version_ext, ldlinux, ldlinux_ext[i]);
PromptOnError = (*img_report.sl_version_ext == 0);
syslinux_ldlinux_len[i] = DownloadFile(tmp, &tmp[sizeof(FILES_URL)], hMainDialog);
PromptOnError = TRUE;
syslinux_ldlinux_len[i] = DownloadSignedFile(tmp, &tmp[sizeof(FILES_URL)],
hMainDialog, (*img_report.sl_version_ext == 0));
if ((syslinux_ldlinux_len[i] == 0) && (DownloadStatus == 404) && (*img_report.sl_version_ext != 0)) {
// Couldn't locate the file on the server => try to download without the version extra
uprintf("Extended version was not found, trying main version...");
static_sprintf(tmp, "%s/%s-%s/%s.%s", FILES_URL, syslinux, img_report.sl_version_str,
ldlinux, ldlinux_ext[i]);
syslinux_ldlinux_len[i] = DownloadFile(tmp, &tmp[sizeof(FILES_URL)], hMainDialog);
syslinux_ldlinux_len[i] = DownloadSignedFile(tmp, &tmp[sizeof(FILES_URL)],
hMainDialog, (*img_report.sl_version_ext == 0));
if (syslinux_ldlinux_len[i] != 0) {
// Duplicate the file so that the user won't be prompted to download again
static_sprintf(tmp, "%s-%s\\%s.%s", syslinux, img_report.sl_version_str, ldlinux, ldlinux_ext[i]);
@ -1691,7 +1704,7 @@ static BOOL BootCheck(void)
uprintf("Could not download the file - will try to use embedded %s version instead", img_report.sl_version_str);
} else {
uprintf("Could not download the file - cancelling");
return FALSE;
goto out;
}
}
}
@ -1714,20 +1727,20 @@ static BOOL BootCheck(void)
r = MessageBoxExU(hMainDialog, lmprintf(MSG_104, "Syslinux v5.0", tmp, "Syslinux v5+", tmp),
lmprintf(MSG_103, tmp), MB_YESNOCANCEL|MB_ICONWARNING|MB_IS_RTL, selected_langid);
if (r == IDCANCEL)
return FALSE;
goto out;
if (r == IDYES) {
static_sprintf(tmp, "%s-%s", syslinux, embedded_sl_version_str[1]);
IGNORE_RETVAL(_mkdir(tmp));
static_sprintf(tmp, "%s/%s-%s/%s.%s", FILES_URL, syslinux, embedded_sl_version_str[1], ldlinux, ldlinux_ext[2]);
if (DownloadFile(tmp, &tmp[sizeof(FILES_URL)], hMainDialog) == 0)
return FALSE;
if (DownloadSignedFile(tmp, &tmp[sizeof(FILES_URL)], hMainDialog, TRUE) == 0)
goto out;
}
}
} else if (bt == BT_MSDOS) {
if ((size_check) && (ComboBox_GetItemData(hClusterSize, ComboBox_GetCurSel(hClusterSize)) >= 65536)) {
// MS-DOS cannot boot from a drive using a 64 kilobytes Cluster size
MessageBoxExU(hMainDialog, lmprintf(MSG_110), lmprintf(MSG_111), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid);
return FALSE;
goto out;
}
} else if (bt == BT_GRUB4DOS) {
IGNORE_RETVAL(_chdirU(app_dir));
@ -1744,13 +1757,13 @@ static BOOL BootCheck(void)
r = MessageBoxExU(hMainDialog, lmprintf(MSG_104, "Grub4DOS 0.4", tmp, "Grub4DOS", tmp),
lmprintf(MSG_103, tmp), MB_YESNOCANCEL|MB_ICONWARNING|MB_IS_RTL, selected_langid);
if (r == IDCANCEL)
return FALSE;
goto out;
if (r == IDYES) {
static_sprintf(tmp, "grub4dos-%s", GRUB4DOS_VERSION);
IGNORE_RETVAL(_mkdir(tmp));
static_sprintf(tmp, "%s/grub4dos-%s/grldr", FILES_URL, GRUB4DOS_VERSION);
if (DownloadFile(tmp, &tmp[sizeof(FILES_URL)], hMainDialog) == 0)
return FALSE;
if (DownloadSignedFile(tmp, &tmp[sizeof(FILES_URL)], hMainDialog, TRUE) == 0)
goto out;
}
}
}
@ -1760,10 +1773,14 @@ uefi_target:
fs = (int)ComboBox_GetItemData(hFileSystem, ComboBox_GetCurSel(hFileSystem));
if (fs != FS_NTFS) {
MessageBoxExU(hMainDialog, lmprintf(MSG_097, "UEFI:NTFS"), lmprintf(MSG_092), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid);
return FALSE;
goto out;
}
}
return TRUE;
ret = 0;
out:
PostMessage(hMainDialog, UM_FORMAT_START, ret, 0);
ExitThread((DWORD)ret);
}
static __inline const char* IsAlphaOrBeta(void)
@ -2197,9 +2214,10 @@ static void GetHalfDropwdownWidth(HWND hDlg)
hw = max(hw, GetTextSize(GetDlgItem(hDlg, IDC_TARGET_SYSTEM), lmprintf(msg_id)).cx);
// Just in case, we also do the number of passes
for (i = 1; i <= 4; i++)
hw = max(hw, GetTextSize(GetDlgItem(hDlg, IDC_TARGET_SYSTEM),
lmprintf((i == 1) ? MSG_034 : MSG_035, i)).cx);
for (i = 1; i <= 5; i++) {
char* msg = (i == 1) ? lmprintf(MSG_034, 1) : lmprintf(MSG_035, (i == 2) ? 2 : 4, (i == 2) ? "" : lmprintf(MSG_087, flash_type[i - 3]));
hw = max(hw, GetTextSize(GetDlgItem(hDlg, IDC_TARGET_SYSTEM), msg).cx);
}
// Finally, we must ensure that we'll have enough space for the 2 checkbox controls
// that end up with a half dropdown
@ -2529,7 +2547,7 @@ static void InitDialog(HWND hDlg)
DWORD len;
HDC hDC;
int i, lfHeight;
char tmp[128], *token, *buf, *ext;
char tmp[128], *token, *buf, *ext, *msg;
static char* resource[2] = { MAKEINTRESOURCEA(IDR_SL_LDLINUX_V4_SYS), MAKEINTRESOURCEA(IDR_SL_LDLINUX_V6_SYS) };
#ifdef RUFUS_TEST
@ -2635,8 +2653,9 @@ static void InitDialog(HWND hDlg)
SendMessage(hProgress, PBM_SETRANGE, 0, (MAX_PROGRESS<<16) & 0xFFFF0000);
// Fill up the passes
for (i=0; i<4; i++) {
IGNORE_RETVAL(ComboBox_AddStringU(hNBPasses, lmprintf((i==0)?MSG_034:MSG_035, i+1)));
for (i = 1; i <= 5; i++) {
msg = (i == 1) ? lmprintf(MSG_034, 1) : lmprintf(MSG_035, (i == 2) ? 2 : 4, (i == 2) ? "" : lmprintf(MSG_087, flash_type[i - 3]));
IGNORE_RETVAL(ComboBox_AddStringU(hNBPasses, msg));
}
IGNORE_RETVAL(ComboBox_SetCurSel(hNBPasses, 0));
SetPassesTooltip();
@ -2973,7 +2992,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
case WM_COMMAND:
#ifdef RUFUS_TEST
if (LOWORD(wParam) == IDC_TEST) {
Notification(MSG_ERROR, NULL, lmprintf(MSG_042), lmprintf(MSG_043, lmprintf(MSG_055)));
DownloadSignedFile(FILES_URL "/gendb.sh", "C:\\Downloads\\gendb.sh", hProgress);
break;
}
#endif
@ -3020,6 +3039,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
// User might be trying to cancel during preliminary checks
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANCELLED;
PrintInfo(0, MSG_201);
EnableWindow(GetDlgItem(hDlg, IDCANCEL), TRUE);
return (INT_PTR)TRUE;
}
if (ulRegister != 0)
@ -3217,6 +3237,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
}
}
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);
@ -3254,86 +3275,13 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
SetTaskbarProgressValue(0, MAX_PROGRESS);
SendMessage(hProgress, PBM_SETPOS, 0, 0);
selection_default = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType));
nDeviceIndex = ComboBox_GetCurSel(hDeviceList);
if (nDeviceIndex != CB_ERR) {
if (!zero_drive) {
if ((bt != BT_NON_BOOTABLE) && (!BootCheck()))
goto aborted_start;
// Display a warning about UDF formatting times
if (fs == FS_UDF) {
dur_secs = (uint32_t)(((double)SelectedDrive.DiskSize) / 1073741824.0f / UDF_FORMAT_SPEED);
if (dur_secs > UDF_FORMAT_WARN) {
dur_mins = dur_secs / 60;
dur_secs -= dur_mins * 60;
MessageBoxExU(hMainDialog, lmprintf(MSG_112, dur_mins, dur_secs), lmprintf(MSG_113),
MB_OK | MB_ICONASTERISK | MB_IS_RTL, selected_langid);
} else {
dur_secs = 0;
dur_mins = 0;
}
}
if ((bt == BT_IMAGE) && IS_DD_BOOTABLE(img_report)) {
if (img_report.is_iso) {
// Ask users how they want to write ISOHybrid images
char* iso_image = lmprintf(MSG_036);
char* dd_image = lmprintf(MSG_095);
char* choices[2] = { lmprintf(MSG_276, iso_image), lmprintf(MSG_277, dd_image) };
i = SelectionDialog(lmprintf(MSG_274), lmprintf(MSG_275, iso_image, dd_image, iso_image, dd_image),
choices, 2);
if (i < 0) // Cancel
goto aborted_start;
else if (i == 2)
write_as_image = TRUE;
} else {
write_as_image = TRUE;
}
}
}
if (!CheckDriveAccess(2000))
goto aborted_start;
GetWindowTextU(hDeviceList, tmp, ARRAYSIZE(tmp));
if (MessageBoxExU(hMainDialog, lmprintf(MSG_003, tmp),
APPLICATION_NAME, MB_OKCANCEL|MB_ICONWARNING|MB_IS_RTL, selected_langid) == IDCANCEL)
goto aborted_start;
if ((SelectedDrive.nPartitions > 1) && (MessageBoxExU(hMainDialog, lmprintf(MSG_093),
lmprintf(MSG_094), MB_OKCANCEL|MB_ICONWARNING|MB_IS_RTL, selected_langid) == IDCANCEL))
goto aborted_start;
if ((!zero_drive) && (bt != BT_NON_BOOTABLE) && (SelectedDrive.SectorSize != 512) &&
(MessageBoxExU(hMainDialog, lmprintf(MSG_196, SelectedDrive.SectorSize),
lmprintf(MSG_197), MB_OKCANCEL|MB_ICONWARNING|MB_IS_RTL, selected_langid) == IDCANCEL))
goto aborted_start;
DeviceNum = (DWORD)ComboBox_GetItemData(hDeviceList, nDeviceIndex);
InitProgress(zero_drive || write_as_image);
format_thid = CreateThread(NULL, 0, FormatThread, (LPVOID)(uintptr_t)DeviceNum, 0, NULL);
if (format_thid == NULL) {
uprintf("Unable to start formatting thread");
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_START_THREAD);
PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)FALSE, 0);
} else {
uprintf("\r\nFormat operation started");
PrintInfo(0, -1);
timer = 0;
static_sprintf(szTimer, "00:00:00");
SendMessageA(hStatus, SB_SETTEXTA, SBT_OWNERDRAW | SB_SECTION_RIGHT, (LPARAM)szTimer);
SetTimer(hMainDialog, TID_APP_TIMER, 1000, ClockTimer);
// Set focus to the Cancel button
SendMessage(hMainDialog, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hMainDialog, IDCANCEL), TRUE);
}
// Create a thread to validate options and download files as needed (so that we can update the UI).
// On exit, this thread sends message UM_FORMAT_START back to this dialog.
if (CreateThread(NULL, 0, BootCheckThread, NULL, 0, NULL) == NULL) {
uprintf("Unable to start boot check thread");
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_CANT_START_THREAD);
PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)FALSE, 0);
}
if (format_thid != NULL)
break;
aborted_start:
format_op_in_progress = FALSE;
EnableControls(TRUE);
zero_drive = FALSE;
if (queued_hotplug_event)
SendMessage(hDlg, UM_MEDIA_CHANGE, 0, 0);
EnableWindow(GetDlgItem(hDlg, IDCANCEL), TRUE);
break;
case IDC_LANG:
// Show the language menu such that it doesn't overlap the button
@ -3610,6 +3558,87 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
SendMessage(hUpdatesDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hUpdatesDlg, IDC_CHECK_NOW), TRUE);
break;
case UM_FORMAT_START:
if (wParam != 0)
goto aborted_start;
if (!zero_drive) {
// Display a warning about UDF formatting times
if (fs == FS_UDF) {
dur_secs = (uint32_t)(((double)SelectedDrive.DiskSize) / 1073741824.0f / UDF_FORMAT_SPEED);
if (dur_secs > UDF_FORMAT_WARN) {
dur_mins = dur_secs / 60;
dur_secs -= dur_mins * 60;
MessageBoxExU(hMainDialog, lmprintf(MSG_112, dur_mins, dur_secs), lmprintf(MSG_113),
MB_OK | MB_ICONASTERISK | MB_IS_RTL, selected_langid);
} else {
dur_secs = 0;
dur_mins = 0;
}
}
if ((bt == BT_IMAGE) && IS_DD_BOOTABLE(img_report)) {
if (img_report.is_iso) {
// Ask users how they want to write ISOHybrid images
char* iso_image = lmprintf(MSG_036);
char* dd_image = lmprintf(MSG_095);
char* choices[2] = { lmprintf(MSG_276, iso_image), lmprintf(MSG_277, dd_image) };
i = SelectionDialog(lmprintf(MSG_274), lmprintf(MSG_275, iso_image, dd_image, iso_image, dd_image),
choices, 2);
if (i < 0) // Cancel
goto aborted_start;
else if (i == 2)
write_as_image = TRUE;
} else {
write_as_image = TRUE;
}
}
}
if (!CheckDriveAccess(2000))
goto aborted_start;
GetWindowTextU(hDeviceList, tmp, ARRAYSIZE(tmp));
if (MessageBoxExU(hMainDialog, lmprintf(MSG_003, tmp),
APPLICATION_NAME, MB_OKCANCEL | MB_ICONWARNING | MB_IS_RTL, selected_langid) == IDCANCEL)
goto aborted_start;
if ((SelectedDrive.nPartitions > 1) && (MessageBoxExU(hMainDialog, lmprintf(MSG_093),
lmprintf(MSG_094), MB_OKCANCEL | MB_ICONWARNING | MB_IS_RTL, selected_langid) == IDCANCEL))
goto aborted_start;
if ((!zero_drive) && (bt != BT_NON_BOOTABLE) && (SelectedDrive.SectorSize != 512) &&
(MessageBoxExU(hMainDialog, lmprintf(MSG_196, SelectedDrive.SectorSize),
lmprintf(MSG_197), MB_OKCANCEL | MB_ICONWARNING | MB_IS_RTL, selected_langid) == IDCANCEL))
goto aborted_start;
nDeviceIndex = ComboBox_GetCurSel(hDeviceList);
DeviceNum = (DWORD)ComboBox_GetItemData(hDeviceList, nDeviceIndex);
InitProgress(zero_drive || write_as_image);
format_thid = CreateThread(NULL, 0, FormatThread, (LPVOID)(uintptr_t)DeviceNum, 0, NULL);
if (format_thid == NULL) {
uprintf("Unable to start formatting thread");
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_CANT_START_THREAD);
PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)FALSE, 0);
} else {
uprintf("\r\nFormat operation started");
PrintInfo(0, -1);
timer = 0;
static_sprintf(szTimer, "00:00:00");
SendMessageA(hStatus, SB_SETTEXTA, SBT_OWNERDRAW | SB_SECTION_RIGHT, (LPARAM)szTimer);
SetTimer(hMainDialog, TID_APP_TIMER, 1000, ClockTimer);
// Set focus to the Cancel button
SendMessage(hMainDialog, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hMainDialog, IDCANCEL), TRUE);
}
if (format_thid != NULL)
break;
aborted_start:
format_op_in_progress = FALSE;
EnableControls(TRUE);
zero_drive = FALSE;
if (queued_hotplug_event)
SendMessage(hDlg, UM_MEDIA_CHANGE, 0, 0);
EnableWindow(GetDlgItem(hDlg, IDCANCEL), TRUE);
break;
case UM_FORMAT_COMPLETED:
format_thid = NULL;
// Stop the timer

View file

@ -67,7 +67,12 @@
#define MARQUEE_TIMER_REFRESH 10 // Time between progress bar marquee refreshes, in ms
#define FS_DEFAULT FS_FAT32
#define SINGLE_CLUSTERSIZE_DEFAULT 0x00000100
#define BADBLOCK_PATTERNS {0xaa, 0x55, 0xff, 0x00}
#define BADLOCKS_PATTERN_TYPES 3
#define BADBLOCK_PATTERN_COUNT 4
#define BADBLOCK_PATTERN_SLC {0x00, 0xff, 0x55, 0xaa}
#define BADCLOCK_PATTERN_MLC {0x00, 0xff, 0x33, 0xcc}
#define BADBLOCK_PATTERN_TLC {0x00, 0xff, 0x1c71c7, 0xe38e38}
#define BADBLOCK_BLOCK_SIZE (128 * 1024)
#define LARGE_FAT32_SIZE (32*1073741824LL) // Size at which we need to use fat32format
#define UDF_FORMAT_SPEED 3.1f // Speed estimate at which we expect UDF drives to be formatted (GB/s)
#define UDF_FORMAT_WARN 20 // Duration (in seconds) above which we warn about long UDF formatting times
@ -75,6 +80,7 @@
#define FAT32_CLUSTER_THRESHOLD 1.011f // For FAT32, cluster size changes don't occur at power of 2 boundaries but sligthly above
#define DD_BUFFER_SIZE 65536 // Minimum size of the buffer we use for DD operations
#define UBUFFER_SIZE 2048
#define RSA_SIGNATURE_SIZE 256
#define CBN_SELCHANGE_INTERNAL (CBN_SELCHANGE + 256)
#define RUFUS_URL "https://rufus.ie"
#define DOWNLOAD_URL RUFUS_URL "/downloads"
@ -157,6 +163,7 @@ enum user_message_type {
UM_NO_UPDATE,
UM_UPDATE_CSM_TOOLTIP,
UM_RESIZE_BUTTONS,
UM_FORMAT_START,
// Start of the WM IDs for the language menu items
UM_LANGUAGE_MENU = WM_APP + 0x100
};
@ -394,7 +401,6 @@ extern float fScale;
extern char szFolderPath[MAX_PATH], app_dir[MAX_PATH], temp_dir[MAX_PATH], system_dir[MAX_PATH], sysnative_dir[MAX_PATH];
extern char* image_path;
extern DWORD FormatStatus, DownloadStatus, MainThreadId;
extern BOOL PromptOnError;
extern unsigned long syslinux_ldlinux_len[2];
extern const int nb_steps[FS_MAX];
extern BOOL use_own_c32[NB_OLD_C32], detect_fakes, iso_op_in_progress, format_op_in_progress, right_to_left_mode;
@ -470,8 +476,8 @@ extern BOOL ResetDevice(int index);
extern BOOL GetOpticalMedia(IMG_SAVE* img_save);
extern BOOL SetLGP(BOOL bRestore, BOOL* bExistingKey, const char* szPath, const char* szPolicy, DWORD dwValue);
extern LONG GetEntryWidth(HWND hDropDown, const char* entry);
extern DWORD DownloadFile(const char* url, const char* file, HWND hProgressDialog);
extern HANDLE DownloadFileThreaded(const char* url, const char* file, HWND hProgressDialog);
extern DWORD DownloadSignedFile(const char* url, const char* file, HWND hProgressDialog, BOOL PromptOnError);
extern HANDLE DownloadSignedFileThreaded(const char* url, const char* file, HWND hProgressDialog, BOOL bPromptOnError);
extern INT_PTR CALLBACK UpdateCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
extern BOOL SetUpdateCheck(void);
extern BOOL CheckForUpdates(BOOL force);
@ -498,6 +504,7 @@ extern int IsHDD(DWORD DriveIndex, uint16_t vid, uint16_t pid, const char* strid
extern char* GetSignatureName(const char* path, const char* country_code);
extern uint64_t GetSignatureTimeStamp(const char* path);
extern LONG ValidateSignature(HWND hDlg, const char* path);
extern BOOL ValidateOpensslSignature(BYTE* pbBuffer, DWORD dwBufferLen, BYTE* pbSignature, DWORD dwSigLen);
extern BOOL IsFontAvailable(const char* font_name);
extern BOOL WriteFileWithRetry(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten, DWORD nNumRetries);
@ -607,3 +614,4 @@ static __inline HMODULE GetLibraryHandle(char* szLibraryName) {
#define ERROR_CANT_PATCH 0x120A
#define ERROR_CANT_ASSIGN_LETTER 0x120B
#define ERROR_CANT_MOUNT_VOLUME 0x120C
#define ERROR_BAD_SIGNATURE 0x120D

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.1.1323"
CAPTION "Rufus 3.2.1328"
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
BEGIN
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
@ -389,8 +389,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,1,1323,0
PRODUCTVERSION 3,1,1323,0
FILEVERSION 3,2,1328,0
PRODUCTVERSION 3,2,1328,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -407,13 +407,13 @@ BEGIN
BEGIN
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "3.1.1323"
VALUE "FileVersion", "3.2.1328"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2018 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
VALUE "OriginalFilename", "rufus.exe"
VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "3.1.1323"
VALUE "ProductVersion", "3.2.1328"
END
END
BLOCK "VarFileInfo"

View file

@ -315,6 +315,8 @@ const char* _StrError(DWORD error_code)
return lmprintf(MSG_078);
case ERROR_NOT_READY:
return lmprintf(MSG_079);
case ERROR_BAD_SIGNATURE:
return lmprintf(MSG_172);
default:
SetLastError(error_code);
return WindowsErrorString();

View file

@ -1558,8 +1558,9 @@ INT_PTR CALLBACK NewVersionCallback(HWND hDlg, UINT message, WPARAM wParam, LPAR
static char* filepath = NULL;
static int download_status = 0;
static HFONT hyperlink_font = NULL;
LONG i;
static HANDLE hThread = NULL;
HWND hNotes;
DWORD exit_code;
STARTUPINFOA si;
PROCESS_INFORMATION pi;
EXT_DECL(dl_ext, NULL, __VA_GROUP__("*.exe"), __VA_GROUP__(lmprintf(MSG_037)));
@ -1614,8 +1615,16 @@ INT_PTR CALLBACK NewVersionCallback(HWND hDlg, UINT message, WPARAM wParam, LPAR
case 1: // Abort
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANCELLED;
download_status = 0;
hThread = NULL;
break;
case 2: // Launch newer version and close this one
if ((hThread == NULL) || (!GetExitCodeThread(hThread, &exit_code)) || (exit_code == 0)) {
hThread = NULL;
EnableWindow(GetDlgItem(hDlg, IDC_DOWNLOAD), FALSE);
break;
}
hThread = NULL;
Sleep(1000); // Add a delay on account of antivirus scanners
if (ValidateSignature(hDlg, filepath) != NO_ERROR) {
@ -1630,7 +1639,7 @@ INT_PTR CALLBACK NewVersionCallback(HWND hDlg, UINT message, WPARAM wParam, LPAR
si.cb = sizeof(si);
if (!CreateProcessU(filepath, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
PrintInfo(0, MSG_214);
uprintf("Failed to launch new application: %s\n", WindowsErrorString());
uprintf("Failed to launch new application: %s", WindowsErrorString());
} else {
PrintInfo(0, MSG_213);
PostMessage(hDlg, WM_COMMAND, (WPARAM)IDCLOSE, 0);
@ -1639,19 +1648,18 @@ INT_PTR CALLBACK NewVersionCallback(HWND hDlg, UINT message, WPARAM wParam, LPAR
break;
default: // Download
if (update.download_url == NULL) {
uprintf("Could not get download URL\n");
uprintf("Could not get download URL");
break;
}
for (i=(int)strlen(update.download_url); (i>0)&&(update.download_url[i]!='/'); i--);
dl_ext.filename = &update.download_url[i+1];
dl_ext.filename = PathFindFileNameU(update.download_url);
filepath = FileDialog(TRUE, app_dir, &dl_ext, OFN_NOCHANGEDIR);
if (filepath == NULL) {
uprintf("Could not get save path\n");
uprintf("Could not get save path");
break;
}
// Opening the File Dialog will make us lose tabbing focus - set it back
SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, IDC_DOWNLOAD), TRUE);
DownloadFileThreaded(update.download_url, filepath, hDlg);
hThread = DownloadSignedFileThreaded(update.download_url, filepath, hDlg, TRUE);
break;
}
return (INT_PTR)TRUE;
@ -1665,11 +1673,14 @@ INT_PTR CALLBACK NewVersionCallback(HWND hDlg, UINT message, WPARAM wParam, LPAR
return (INT_PTR)TRUE;
case UM_PROGRESS_EXIT:
EnableWindow(GetDlgItem(hDlg, IDCANCEL), TRUE);
if (wParam) {
if (wParam != 0) {
SetWindowTextU(GetDlgItem(hDlg, IDC_DOWNLOAD), lmprintf(MSG_039));
download_status = 2;
} else {
SetWindowTextU(GetDlgItem(hDlg, IDC_DOWNLOAD), lmprintf(MSG_040));
// Disable the download button if we found an invalid signature
EnableWindow(GetDlgItem(hDlg, IDC_DOWNLOAD),
FormatStatus != (ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_BAD_SIGNATURE)));
download_status = 0;
}
return (INT_PTR)TRUE;