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 #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # 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>. # Report bugs to <https://github.com/pbatard/rufus/issues>.
# #
@ -580,8 +580,8 @@ MAKEFLAGS=
# Identity of this package. # Identity of this package.
PACKAGE_NAME='rufus' PACKAGE_NAME='rufus'
PACKAGE_TARNAME='rufus' PACKAGE_TARNAME='rufus'
PACKAGE_VERSION='3.1' PACKAGE_VERSION='3.2'
PACKAGE_STRING='rufus 3.1' PACKAGE_STRING='rufus 3.2'
PACKAGE_BUGREPORT='https://github.com/pbatard/rufus/issues' PACKAGE_BUGREPORT='https://github.com/pbatard/rufus/issues'
PACKAGE_URL='https://rufus.akeo.ie' 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. # 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. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF 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]... Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1294,7 +1294,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of rufus 3.1:";; short | recursive ) echo "Configuration of rufus 3.2:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@ -1385,7 +1385,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
rufus configure 3.1 rufus configure 3.2
generated by GNU Autoconf 2.69 generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc. Copyright (C) 2012 Free Software Foundation, Inc.
@ -1440,7 +1440,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. 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 generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@ $ $0 $@
@ -2303,7 +2303,7 @@ fi
# Define the identity of the package. # Define the identity of the package.
PACKAGE='rufus' PACKAGE='rufus'
VERSION='3.1' VERSION='3.2'
cat >>confdefs.h <<_ACEOF 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 # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" 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 generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@ -4535,7 +4535,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\ ac_cs_version="\\
rufus config.status 3.1 rufus config.status 3.2
configured by $0, generated by GNU Autoconf 2.69, configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\" 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]) AM_INIT_AUTOMAKE([-Wno-portability foreign no-dist no-dependencies])
AC_CONFIG_SRCDIR([src/rufus.c]) AC_CONFIG_SRCDIR([src/rufus.c])
AC_CONFIG_MACRO_DIR([m4]) 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... --> for an interesting struggle, when you also happen to have a comma in one of the fields... -->
<Identity <Identity
Name="Rufus" Name="Rufus"
Version="3.1.1320.0" Version="3.2.1320.0"
ProcessorArchitecture="x86" ProcessorArchitecture="x86"
Publisher='CN=Akeo Consulting, O=Akeo Consulting, STREET=24 Grey Rock, L=Milford, S=Co. Donegal, PostalCode=F92 D667, C=IE' /> Publisher='CN=Akeo Consulting, O=Akeo Consulting, STREET=24 Grey Rock, L=Milford, S=Co. Donegal, PostalCode=F92 D667, C=IE' />
<Properties> <Properties>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -25,6 +25,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <assert.h>
#include "rufus.h" #include "rufus.h"
#include "missing.h" #include "missing.h"
@ -110,10 +111,8 @@ BOOL GetAutoMount(BOOL* enabled)
* the specific range [DRIVE_INDEX_MIN; DRIVE_INDEX_MAX]. * the specific range [DRIVE_INDEX_MIN; DRIVE_INDEX_MAX].
*/ */
#define CheckDriveIndex(DriveIndex) do { \ #define CheckDriveIndex(DriveIndex) do { \
if ((DriveIndex < DRIVE_INDEX_MIN) || (DriveIndex > DRIVE_INDEX_MAX)) { \ assert((DriveIndex >= DRIVE_INDEX_MIN) && (DriveIndex <= DRIVE_INDEX_MAX)); \
uprintf("ERROR: Bad index value %d. Please check the code!", DriveIndex); \ if ((DriveIndex < DRIVE_INDEX_MIN) || (DriveIndex > DRIVE_INDEX_MAX)) goto out; \
goto out; \
} \
DriveIndex -= DRIVE_INDEX_MIN; } while (0) DriveIndex -= DRIVE_INDEX_MIN; } while (0)
/* /*

View file

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

View file

@ -512,6 +512,22 @@ static __inline int PathGetDriveNumberU(char* lpPath)
return ret; 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 // 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) static __inline BOOL GetTextExtentPointU(HDC hdc, const char* lpString, LPSIZE lpSize)
{ {

241
src/net.c
View file

@ -29,6 +29,7 @@
#include <malloc.h> #include <malloc.h>
#include <string.h> #include <string.h>
#include <inttypes.h> #include <inttypes.h>
#include <assert.h>
#include "rufus.h" #include "rufus.h"
#include "missing.h" #include "missing.h"
@ -44,7 +45,6 @@
#define DEFAULT_UPDATE_INTERVAL (24*3600) #define DEFAULT_UPDATE_INTERVAL (24*3600)
DWORD DownloadStatus; DWORD DownloadStatus;
BOOL PromptOnError = TRUE;
extern BOOL force_update; extern BOOL force_update;
static DWORD error_code; 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 * 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 * 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 * 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 * 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; HWND hProgressBar = NULL;
BOOL r = FALSE; BOOL r = FALSE;
@ -234,8 +235,8 @@ DWORD DownloadFile(const char* url, const char* file, HWND hProgressDialog)
HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL; HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL;
URL_COMPONENTSA UrlParts = {sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0, URL_COMPONENTSA UrlParts = {sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0,
hostname, sizeof(hostname), 0, NULL, 1, urlpath, sizeof(urlpath), NULL, 1}; hostname, sizeof(hostname), 0, NULL, 1, urlpath, sizeof(urlpath), NULL, 1};
size_t last_slash; const char* short_name;
int i; size_t i;
// Can't link with wininet.lib because of sideloading issues // Can't link with wininet.lib because of sideloading issues
PF_TYPE_DECL(WINAPI, BOOL, InternetCrackUrlA, (LPCSTR, DWORD, DWORD, LPURL_COMPONENTSA)); 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(HttpSendRequestA, WinInet);
PF_INIT_OR_OUT(HttpQueryInfoA, WinInet); PF_INIT_OR_OUT(HttpQueryInfoA, WinInet);
DownloadStatus = 0; FormatStatus = 0;
DownloadStatus = 404;
if (hProgressDialog != NULL) { if (hProgressDialog != NULL) {
// Use the progress control provided, if any // Use the progress control provided, if any
hProgressBar = GetDlgItem(hProgressDialog, IDC_PROGRESS); 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); SendMessage(hProgressDialog, UM_PROGRESS_INIT, 0, 0);
} }
if (file == NULL) assert(url != NULL);
goto out;
for (last_slash = safe_strlen(file); last_slash != 0; last_slash--) { short_name = (file != NULL) ? PathFindFileNameU(file) : PathFindFileNameU(url);
if ((file[last_slash] == '/') || (file[last_slash] == '\\')) {
last_slash++;
break;
}
}
PrintInfo(0, MSG_085, &file[last_slash]); if (hProgressDialog != NULL) {
uprintf("Downloading '%s' from %s\n", &file[last_slash], url); PrintInfo(0, MSG_085, short_name);
uprintf("Downloading %s", url);
}
if ( (!pfInternetCrackUrlA(url, (DWORD)safe_strlen(url), 0, &UrlParts)) if ( (!pfInternetCrackUrlA(url, (DWORD)safe_strlen(url), 0, &UrlParts))
|| (UrlParts.lpszHostName == NULL) || (UrlParts.lpszUrlPath == NULL)) { || (UrlParts.lpszHostName == NULL) || (UrlParts.lpszUrlPath == NULL)) {
uprintf("Unable to decode URL: %s\n", WinInetErrorString()); uprintf("Unable to decode URL: %s", WinInetErrorString());
goto out; goto out;
} }
hostname[sizeof(hostname)-1] = 0; hostname[sizeof(hostname)-1] = 0;
@ -295,7 +293,7 @@ DWORD DownloadFile(const char* url, const char* file, HWND hProgressDialog)
if (i <= 0) { if (i <= 0) {
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa384702.aspx is wrong... // http://msdn.microsoft.com/en-us/library/windows/desktop/aa384702.aspx is wrong...
SetLastError(ERROR_INTERNET_NOT_INITIALIZED); SetLastError(ERROR_INTERNET_NOT_INITIALIZED);
uprintf("Network is unavailable: %s\n", WinInetErrorString()); uprintf("Network is unavailable: %s", WinInetErrorString());
goto out; goto out;
} }
static_sprintf(agent, APPLICATION_NAME "/%d.%d.%d (Windows NT %d.%d%s)", 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":""); nWindowsVersion>>4, nWindowsVersion&0x0F, is_x64()?"; WOW64":"");
hSession = pfInternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); hSession = pfInternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (hSession == NULL) { if (hSession == NULL) {
uprintf("Could not open Internet session: %s\n", WinInetErrorString()); uprintf("Could not open Internet session: %s", WinInetErrorString());
goto out; goto out;
} }
hConnection = pfInternetConnectA(hSession, UrlParts.lpszHostName, UrlParts.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)NULL); hConnection = pfInternetConnectA(hSession, UrlParts.lpszHostName, UrlParts.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)NULL);
if (hConnection == 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; 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| 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); ((UrlParts.nScheme==INTERNET_SCHEME_HTTPS)?INTERNET_FLAG_SECURE:0), (DWORD_PTR)NULL);
if (hRequest == 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; goto out;
} }
if (!pfHttpSendRequestA(hRequest, NULL, 0, NULL, 0)) { if (!pfHttpSendRequestA(hRequest, NULL, 0, NULL, 0)) {
uprintf("Unable to send request: %s\n", WinInetErrorString()); uprintf("Unable to send request: %s", WinInetErrorString());
goto out; goto out;
} }
// Get the file size // Get the file size
dwSize = sizeof(DownloadStatus); dwSize = sizeof(DownloadStatus);
DownloadStatus = 404;
pfHttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&DownloadStatus, &dwSize, NULL); pfHttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&DownloadStatus, &dwSize, NULL);
if (DownloadStatus != 200) { if (DownloadStatus != 200) {
error_code = ERROR_INTERNET_ITEM_NOT_FOUND; error_code = ERROR_INTERNET_ITEM_NOT_FOUND;
uprintf("Unable to access file: %d\n", DownloadStatus); uprintf("Unable to access file: %d", DownloadStatus);
goto out; goto out;
} }
dwSize = sizeof(dwTotalSize); dwSize = sizeof(dwTotalSize);
if (!pfHttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwTotalSize, &dwSize, NULL)) { 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; goto out;
} }
uprintf("File length: %d bytes\n", dwTotalSize); if (hProgressDialog != NULL)
uprintf("File length: %d bytes", dwTotalSize);
if (file != NULL) {
hFile = CreateFileU(file, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); hFile = CreateFileU(file, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) { if (hFile == INVALID_HANDLE_VALUE) {
uprintf("Unable to create file '%s': %s\n", &file[last_slash], WinInetErrorString()); uprintf("Unable to create file '%s': %s", short_name, WinInetErrorString());
goto out; 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. // Keep checking for data until there is nothing left.
dwSize = 0; dwSize = 0;
while (1) { while (1) {
// User may have cancelled the download
if (IS_ERROR(FormatStatus)) if (IS_ERROR(FormatStatus))
goto out; goto out;
if (!pfInternetReadFile(hRequest, buf, sizeof(buf), &dwDownloaded) || (dwDownloaded == 0)) if (!pfInternetReadFile(hRequest, buf, sizeof(buf), &dwDownloaded) || (dwDownloaded == 0))
break; break;
dwSize += dwDownloaded; if (hProgressDialog != NULL) {
SendMessage(hProgressBar, PBM_SETPOS, (WPARAM)(MAX_PROGRESS*((1.0f*dwSize) / (1.0f*dwTotalSize))), 0); SendMessage(hProgressBar, PBM_SETPOS, (WPARAM)(MAX_PROGRESS*((1.0f*dwSize) / (1.0f*dwTotalSize))), 0);
PrintInfo(0, MSG_241, (100.0f*dwSize) / (1.0f*dwTotalSize)); PrintInfo(0, MSG_241, (100.0f*dwSize) / (1.0f*dwTotalSize));
}
if (file != NULL) {
if (!WriteFile(hFile, buf, dwDownloaded, &dwWritten, NULL)) { if (!WriteFile(hFile, buf, dwDownloaded, &dwWritten, NULL)) {
uprintf("Error writing file '%s': %s\n", &file[last_slash], WinInetErrorString()); uprintf("Error writing file '%s': %s", short_name, WinInetErrorString());
goto out; goto out;
} else if (dwDownloaded != dwWritten) { } else if (dwDownloaded != dwWritten) {
uprintf("Error writing file '%s': Only %d/%d bytes written\n", dwWritten, dwDownloaded); uprintf("Error writing file '%s': Only %d/%d bytes written", short_name, dwWritten, dwDownloaded);
goto out; goto out;
} }
} else {
memcpy(&(*buffer)[dwSize], buf, dwDownloaded);
}
dwSize += dwDownloaded;
} }
if (dwSize != dwTotalSize) { 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; FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT;
goto out; goto out;
} else { } else {
DownloadStatus = 200;
r = TRUE; 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: out:
if (hProgressDialog != NULL)
SendMessage(hProgressDialog, UM_PROGRESS_EXIT, (WPARAM)r, 0);
if (hFile != INVALID_HANDLE_VALUE) { if (hFile != INVALID_HANDLE_VALUE) {
// Force a flush - May help with the PKI API trying to process downloaded updates too early... // Force a flush - May help with the PKI API trying to process downloaded updates too early...
FlushFileBuffers(hFile); FlushFileBuffers(hFile);
CloseHandle(hFile); CloseHandle(hFile);
} }
if (!r) { if ((!r) && (file != NULL))
if (file != NULL)
_unlinkU(file); _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 (hRequest) if (hRequest)
pfInternetCloseHandle(hRequest); pfInternetCloseHandle(hRequest);
if (hConnection) if (hConnection)
@ -406,20 +417,92 @@ out:
return r ? dwSize : 0; return r ? dwSize : 0;
} }
/* Threaded download */ // Download and validate a signed file. The file must have a corresponding '.sig' on the server.
static const char *_url, *_file; DWORD DownloadSignedFile(const char* url, const char* file, HWND hProgressDialog, BOOL bPromptOnError)
static HWND _hProgressDialog;
static DWORD WINAPI _DownloadFileThread(LPVOID param)
{ {
ExitThread(DownloadFile(_url, _file, _hProgressDialog) != 0); 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;
} }
HANDLE DownloadFileThreaded(const char* url, const char* file, HWND hProgressDialog) 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 */
typedef struct {
const char* url;
const char* file;
HWND hProgressDialog;
BOOL bPromptOnError;
} DownloadSignedFileThreadArgs;
static DWORD WINAPI DownloadSignedFileThread(LPVOID param)
{ {
_url = url; DownloadSignedFileThreadArgs* args = (DownloadSignedFileThreadArgs*)param;
_file = file; ExitThread(DownloadSignedFile(args->url, args->file, args->hProgressDialog, args->bPromptOnError));
_hProgressDialog = hProgressDialog; }
return CreateThread(NULL, 0, _DownloadFileThread, NULL, 0, NULL);
HANDLE DownloadSignedFileThreaded(const char* url, const char* file, HWND hProgressDialog, BOOL bPromptOnError)
{
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]) { 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 static const char* channel[] = {"release", "beta", "test"}; // release channel
const char* accept_types[] = {"*/*\0", NULL}; const char* accept_types[] = {"*/*\0", NULL};
DWORD dwFlags, dwSize, dwDownloaded, dwTotalSize, dwStatus; DWORD dwFlags, dwSize, dwDownloaded, dwTotalSize, dwStatus;
BYTE *sig = NULL;
char* buf = 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, ""}; OSVERSIONINFOA os_version = {sizeof(OSVERSIONINFOA), 0, 0, 0, 0, ""};
HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL; HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL;
URL_COMPONENTSA UrlParts = {sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0, 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)))); } while ((!force_update_check) && ((iso_op_in_progress || format_op_in_progress || (dialog_showing>0))));
if (!force_update_check) { if (!force_update_check) {
if ((ReadSetting32(SETTING_UPDATE_INTERVAL) == -1)) { 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; goto out;
} }
reg_time = ReadSetting64(SETTING_LAST_UPDATE); reg_time = ReadSetting64(SETTING_LAST_UPDATE);
@ -500,9 +584,9 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
if (!SystemTimeToFileTime(&LocalTime, &FileTime)) if (!SystemTimeToFileTime(&LocalTime, &FileTime))
goto out; goto out;
local_time = ((((int64_t)FileTime.dwHighDateTime)<<32) + FileTime.dwLowDateTime) / 10000000; 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) { 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; goto out;
} }
} }
@ -512,7 +596,7 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
status++; // 1 status++; // 1
if (!GetVersionExA(&os_version)) { 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; goto out;
} }
@ -540,7 +624,7 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
max_channel = releases_only ? 1 : (int)ARRAYSIZE(channel) - 1; max_channel = releases_only ? 1 : (int)ARRAYSIZE(channel) - 1;
#endif #endif
for (k=0; (k<max_channel) && (!found_new_version); k++) { 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. // 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" // 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 // 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. // 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)?"":"_", 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); (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--) { for (i=0, j=(int)safe_strlen(urlpath)-5; (j>0)&&(i<ARRAYSIZE(verpos)); j--) {
if ((urlpath[j] == '.') || (urlpath[j] == '_')) { if ((urlpath[j] == '.') || (urlpath[j] == '_')) {
verpos[i++] = j; verpos[i++] = j;
} }
} }
if (i != ARRAYSIZE(verpos)) { assert(i == ARRAYSIZE(verpos));
uprintf("Broken code in CheckForUpdatesThread()!\n");
goto out;
}
UrlParts.lpszUrlPath = urlpath; UrlParts.lpszUrlPath = urlpath;
UrlParts.dwUrlPathLength = sizeof(urlpath); UrlParts.dwUrlPathLength = sizeof(urlpath);
for (i=0; i<ARRAYSIZE(verpos); i++) { 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, hRequest = pfHttpOpenRequestA(hConnection, "GET", UrlParts.lpszUrlPath, NULL, NULL, accept_types,
INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS| 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| 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)) ) || (!SystemTimeToFileTime(&ServerTime, &FileTime)) )
goto out; goto out;
server_time = ((((int64_t)FileTime.dwHighDateTime)<<32) + FileTime.dwLowDateTime) / 10000000; 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! // Always store the server response time - the only clock we trust!
WriteSetting64(SETTING_LAST_UPDATE, server_time); WriteSetting64(SETTING_LAST_UPDATE, server_time);
// Might as well let the user know // Might as well let the user know
@ -625,29 +706,39 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
safe_free(buf); safe_free(buf);
// Make sure the file is NUL terminated // Make sure the file is NUL terminated
buf = (char*)calloc(dwTotalSize+1, 1); 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 // This is a version file - we should be able to gulp it down in one go
if (!pfInternetReadFile(hRequest, buf, dwTotalSize, &dwDownloaded) || (dwDownloaded != dwTotalSize)) if (!pfInternetReadFile(hRequest, buf, dwTotalSize, &dwDownloaded) || (dwDownloaded != dwTotalSize))
goto out; 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++; status++;
vuprintf("Successfully downloaded version file (%d bytes)\n", dwTotalSize);
parse_update(buf, dwTotalSize+1); parse_update(buf, dwTotalSize+1);
vuprintf("UPDATE DATA:\n"); vuprintf("UPDATE DATA:");
vuprintf(" version: %d.%d.%d (%s)\n", update.version[0], update.version[1], update.version[2], channel[k]); vuprintf(" version: %d.%d.%d (%s)", 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(" platform_min: %d.%d", update.platform_min[0], update.platform_min[1]);
vuprintf(" url: %s\n", update.download_url); vuprintf(" url: %s", update.download_url);
found_new_version = ((to_uint64_t(update.version) > to_uint64_t(rufus_version)) || (force_update)) 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.dwMajorVersion == update.platform_min[0]) && (os_version.dwMinorVersion >= update.platform_min[1])) ); || ( (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: out:
safe_free(buf); safe_free(buf);
safe_free(sig);
if (hRequest) if (hRequest)
pfInternetCloseHandle(hRequest); pfInternetCloseHandle(hRequest);
if (hConnection) if (hConnection)

146
src/pki.c
View file

@ -27,6 +27,7 @@
#include <stdio.h> #include <stdio.h>
#include <wincrypt.h> #include <wincrypt.h>
#include <wintrust.h> #include <wintrust.h>
#include <assert.h>
#include "rufus.h" #include "rufus.h"
#include "resource.h" #include "resource.h"
@ -52,6 +53,63 @@ typedef struct {
LPWSTR lpszMoreInfoLink; LPWSTR lpszMoreInfoLink;
} SPROG_PUBLISHERINFO, *PSPROG_PUBLISHERINFO; } 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 * FormatMessage does not handle PKI errors
@ -65,8 +123,19 @@ const char* WinPKIErrorString(void)
return WindowsErrorString(); return WindowsErrorString();
switch (error_code) { switch (error_code) {
// See also https://docs.microsoft.com/en-gb/windows/desktop/com/com-error-codes-4
case NTE_BAD_UID: case NTE_BAD_UID:
return "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: case CRYPT_E_MSG_ERROR:
return "An error occurred while performing an operation on a cryptographic message."; return "An error occurred while performing an operation on a cryptographic message.";
case CRYPT_E_UNKNOWN_ALGO: case CRYPT_E_UNKNOWN_ALGO:
@ -581,3 +650,80 @@ LONG ValidateSignature(HWND hDlg, const char* path)
return r; 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 <dbt.h>
#include <io.h> #include <io.h>
#include <getopt.h> #include <getopt.h>
#include <assert.h>
#include "rufus.h" #include "rufus.h"
#include "missing.h" #include "missing.h"
@ -51,6 +52,7 @@
static const char* cmdline_hogger = "rufus.com"; static const char* cmdline_hogger = "rufus.com";
static const char* FileSystemLabel[FS_MAX] = { "FAT", "FAT32", "NTFS", "UDF", "exFAT", "ReFS" }; 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* ep_reg = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer";
static const char* vs_reg = "Software\\Microsoft\\VisualStudio"; static const char* vs_reg = "Software\\Microsoft\\VisualStudio";
// Number of steps for each FS for FCC_STRUCTURE_PROGRESS // 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) static void SetPassesTooltip(void)
{ {
const unsigned char pattern[] = BADBLOCK_PATTERNS; const unsigned int pattern[BADLOCKS_PATTERN_TYPES][BADBLOCK_PATTERN_COUNT] =
CreateTooltip(hNBPasses, lmprintf(MSG_153 + ComboBox_GetCurSel(hNBPasses), { BADBLOCK_PATTERN_SLC, BADCLOCK_PATTERN_MLC, BADBLOCK_PATTERN_TLC };
pattern[0], pattern[1], pattern[2], pattern[3]), -1); 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) static void ResizeDialogs(int shift)
@ -1341,15 +1346,14 @@ static void UpdateImage(void)
} }
} }
if (image_path != NULL) {
ComboBox_DeleteString(hBootType, index); ComboBox_DeleteString(hBootType, index);
ComboBox_InsertStringU(hBootType, index, short_image_path); ComboBox_InsertStringU(hBootType, index,
(image_path == NULL) ? lmprintf(MSG_281, lmprintf(MSG_280)) : short_image_path);
ComboBox_SetItemData(hBootType, index, BT_IMAGE); ComboBox_SetItemData(hBootType, index, BT_IMAGE);
IGNORE_RETVAL(ComboBox_SetCurSel(hBootType, index)); IGNORE_RETVAL(ComboBox_SetCurSel(hBootType, index));
bt = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType)); bt = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType));
SetBootTypeDropdownWidth(); SetBootTypeDropdownWidth();
} }
}
// The scanning process can be blocking for message processing => use a thread // The scanning process can be blocking for message processing => use a thread
DWORD WINAPI ISOScanThread(LPVOID param) DWORD WINAPI ISOScanThread(LPVOID param)
@ -1358,6 +1362,7 @@ DWORD WINAPI ISOScanThread(LPVOID param)
if (image_path == NULL) if (image_path == NULL)
goto out; goto out;
format_op_in_progress = TRUE;
PrintInfoDebug(0, MSG_202); PrintInfoDebug(0, MSG_202);
user_notified = FALSE; user_notified = FALSE;
EnableControls(FALSE); EnableControls(FALSE);
@ -1365,15 +1370,16 @@ DWORD WINAPI ISOScanThread(LPVOID param)
img_report.is_iso = (BOOLEAN)ExtractISO(image_path, "", TRUE); img_report.is_iso = (BOOLEAN)ExtractISO(image_path, "", TRUE);
img_report.is_bootable_img = (BOOLEAN)IsBootableImage(image_path); 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 // Failed to scan image
SendMessage(hMainDialog, UM_PROGRESS_EXIT, 0, 0); SendMessage(hMainDialog, UM_PROGRESS_EXIT, 0, 0);
safe_free(image_path); safe_free(image_path);
EnableControls(TRUE); UpdateImage();
SetMBRProps(); SetMBRProps();
PopulateProperties(); PopulateProperties();
PrintInfoDebug(0, MSG_203); PrintInfoDebug(0, MSG_203);
PrintStatus(0, MSG_203); PrintStatus(0, MSG_203);
EnableControls(TRUE);
goto out; goto out;
} }
@ -1435,15 +1441,18 @@ DWORD WINAPI ISOScanThread(LPVOID param)
out: out:
dont_display_image_name = FALSE; dont_display_image_name = FALSE;
format_op_in_progress = FALSE;
PrintInfo(0, MSG_210); PrintInfo(0, MSG_210);
ExitThread(0); 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; int i, r;
FILE *fd; FILE *fd;
DWORD len; DWORD len;
WPARAM ret = -1;
BOOL in_files_dir = FALSE; BOOL in_files_dir = FALSE;
const char* grub = "grub"; const char* grub = "grub";
const char* core_img = "core.img"; const char* core_img = "core.img";
@ -1454,34 +1463,42 @@ static BOOL BootCheck(void)
syslinux_ldlinux_len[0] = 0; syslinux_ldlinux_len[1] = 0; syslinux_ldlinux_len[0] = 0; syslinux_ldlinux_len[1] = 0;
safe_free(grub2_buf); safe_free(grub2_buf);
if (bt == BT_IMAGE) {
// We should never be there if (ComboBox_GetCurSel(hDeviceList) == CB_ERR)
if (image_path == NULL) { goto out;
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); if ((zero_drive) || (bt == BT_NON_BOOTABLE)) {
return FALSE; // Nothing to check
ret = 0;
goto out;
} }
if (bt == BT_IMAGE) {
assert(image_path != NULL);
if (image_path == NULL)
goto out;
if ((size_check) && (img_report.projected_size > (uint64_t)SelectedDrive.DiskSize)) { if ((size_check) && (img_report.projected_size > (uint64_t)SelectedDrive.DiskSize)) {
// This ISO image is too big for the selected target // 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); 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) { if (IS_DD_BOOTABLE(img_report) && !img_report.is_iso) {
// Pure DD images are fine at this stage // 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 ((display_togo_option) && (ComboBox_GetCurSel(GetDlgItem(hMainDialog, IDC_IMAGE_OPTION)) == 1)) {
if (fs != FS_NTFS) { if (fs != FS_NTFS) {
// Windows To Go only works for 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); 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 (SelectedDrive.MediaType != FixedMedia) {
if ((tt == TT_UEFI) && (pt == PARTITION_STYLE_GPT) && (nWindowsBuildNumber < 15000)) { 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. // 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. // 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); 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 // 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); MessageBoxExU(hMainDialog, lmprintf(MSG_073), lmprintf(MSG_291), MB_OK | MB_ICONERROR | MB_IS_RTL, selected_langid);
// fall through // fall through
case -2: case -2:
return FALSE; goto out;
default: default:
break; break;
} }
@ -1498,13 +1515,13 @@ static BOOL BootCheck(void)
if (!IS_EFI_BOOTABLE(img_report)) { if (!IS_EFI_BOOTABLE(img_report)) {
// Unsupported ISO // Unsupported ISO
MessageBoxExU(hMainDialog, lmprintf(MSG_091), lmprintf(MSG_090), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid); 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())) { if (HAS_WIN7_EFI(img_report) && (!WimExtractCheck())) {
// Your platform cannot extract files from WIM archives => download 7-zip? // 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) 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); 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) && } else if ( ((fs == FS_NTFS) && !HAS_WINDOWS(img_report) && !HAS_GRUB(img_report) &&
(!HAS_SYSLINUX(img_report) || (SL_MAJOR(img_report.sl_version) <= 5))) (!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)) ) { || ((IS_FAT(fs)) && (HAS_WINDOWS(img_report) || HAS_INSTALL_WIM(img_report)) && (!allow_dual_uefi_bios)) ) {
// Incompatible FS and ISO // Incompatible FS and ISO
MessageBoxExU(hMainDialog, lmprintf(MSG_096), lmprintf(MSG_092), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid); 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)) { } else if ((fs == FS_FAT16) && HAS_KOLIBRIOS(img_report)) {
// KolibriOS doesn't support FAT16 // KolibriOS doesn't support FAT16
MessageBoxExU(hMainDialog, lmprintf(MSG_189), lmprintf(MSG_099), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid); 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)) { if ((IS_FAT(fs)) && (img_report.has_4GB_file)) {
// This ISO image contains a file larger than 4GB file (FAT32) // 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); 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 // 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), 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); lmprintf(MSG_115), MB_YESNOCANCEL|MB_ICONWARNING|MB_IS_RTL, selected_langid);
if (r == IDCANCEL) if (r == IDCANCEL)
return FALSE; goto out;
else if (r == IDYES) { else if (r == IDYES) {
static_sprintf(tmp, "%s-%s", grub, img_report.grub2_version); static_sprintf(tmp, "%s-%s", grub, img_report.grub2_version);
IGNORE_RETVAL(_mkdir(tmp)); IGNORE_RETVAL(_mkdir(tmp));
IGNORE_RETVAL(_chdir(tmp)); IGNORE_RETVAL(_chdir(tmp));
static_sprintf(tmp, "%s/%s-%s/%s", FILES_URL, grub, img_report.grub2_version, core_img); static_sprintf(tmp, "%s/%s-%s/%s", FILES_URL, grub, img_report.grub2_version, core_img);
PromptOnError = FALSE; grub2_len = (long)DownloadSignedFile(tmp, core_img, hMainDialog, FALSE);
grub2_len = (long)DownloadFile(tmp, core_img, hMainDialog);
PromptOnError = TRUE;
if ((grub2_len == 0) && (DownloadStatus == 404)) { if ((grub2_len == 0) && (DownloadStatus == 404)) {
// Couldn't locate the file on the server => try to download without the version extra // Couldn't locate the file on the server => try to download without the version extra
uprintf("Extended version was not found, trying main version..."); 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++); for (i = 0; ((tmp2[i] >= '0') && (tmp2[i] <= '9')) || (tmp2[i] == '.'); i++);
tmp2[i] = 0; tmp2[i] = 0;
static_sprintf(tmp, "%s/%s-%s/%s", FILES_URL, grub, tmp2, core_img); static_sprintf(tmp, "%s/%s-%s/%s", FILES_URL, grub, tmp2, core_img);
PromptOnError = FALSE; grub2_len = (long)DownloadSignedFile(tmp, core_img, hMainDialog, FALSE);
grub2_len = (long)DownloadFile(tmp, core_img, hMainDialog);
PromptOnError = TRUE;
static_sprintf(tmp, "%s/%s-%s/%s", FILES_URL, grub, img_report.grub2_version, core_img); static_sprintf(tmp, "%s/%s-%s/%s", FILES_URL, grub, img_report.grub2_version, core_img);
} }
if (grub2_len <= 0) { if (grub2_len <= 0) {
@ -1621,10 +1634,10 @@ static BOOL BootCheck(void)
static_sprintf(tmp, "%s-%s", syslinux, embedded_sl_version_str[0]); static_sprintf(tmp, "%s-%s", syslinux, embedded_sl_version_str[0]);
IGNORE_RETVAL(_mkdir(tmp)); IGNORE_RETVAL(_mkdir(tmp));
static_sprintf(tmp, "%s/%s-%s/%s", FILES_URL, syslinux, embedded_sl_version_str[0], old_c32_name[i]); 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) { if (len == 0) {
uprintf("Could not download file - cancelling"); uprintf("Could not download file - cancelling");
return FALSE; goto out;
} }
use_own_c32[i] = TRUE; use_own_c32[i] = TRUE;
} }
@ -1657,7 +1670,7 @@ static BOOL BootCheck(void)
embedded_sl_version_str[1], embedded_sl_version_ext[1]), embedded_sl_version_str[1], embedded_sl_version_ext[1]),
lmprintf(MSG_115), MB_YESNO|MB_ICONWARNING|MB_IS_RTL, selected_langid); lmprintf(MSG_115), MB_YESNO|MB_ICONWARNING|MB_IS_RTL, selected_langid);
if (r != IDYES) if (r != IDYES)
return FALSE; goto out;
for (i=0; i<2; i++) { for (i=0; i<2; i++) {
static_sprintf(tmp, "%s-%s", syslinux, img_report.sl_version_str); static_sprintf(tmp, "%s-%s", syslinux, img_report.sl_version_str);
IGNORE_RETVAL(_mkdir(tmp)); 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, 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]); img_report.sl_version_ext, ldlinux, ldlinux_ext[i]);
PromptOnError = (*img_report.sl_version_ext == 0); syslinux_ldlinux_len[i] = DownloadSignedFile(tmp, &tmp[sizeof(FILES_URL)],
syslinux_ldlinux_len[i] = DownloadFile(tmp, &tmp[sizeof(FILES_URL)], hMainDialog); hMainDialog, (*img_report.sl_version_ext == 0));
PromptOnError = TRUE;
if ((syslinux_ldlinux_len[i] == 0) && (DownloadStatus == 404) && (*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 // Couldn't locate the file on the server => try to download without the version extra
uprintf("Extended version was not found, trying main version..."); 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, static_sprintf(tmp, "%s/%s-%s/%s.%s", FILES_URL, syslinux, img_report.sl_version_str,
ldlinux, ldlinux_ext[i]); 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) { if (syslinux_ldlinux_len[i] != 0) {
// Duplicate the file so that the user won't be prompted to download again // 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]); 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); uprintf("Could not download the file - will try to use embedded %s version instead", img_report.sl_version_str);
} else { } else {
uprintf("Could not download the file - cancelling"); 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), 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); lmprintf(MSG_103, tmp), MB_YESNOCANCEL|MB_ICONWARNING|MB_IS_RTL, selected_langid);
if (r == IDCANCEL) if (r == IDCANCEL)
return FALSE; goto out;
if (r == IDYES) { if (r == IDYES) {
static_sprintf(tmp, "%s-%s", syslinux, embedded_sl_version_str[1]); static_sprintf(tmp, "%s-%s", syslinux, embedded_sl_version_str[1]);
IGNORE_RETVAL(_mkdir(tmp)); IGNORE_RETVAL(_mkdir(tmp));
static_sprintf(tmp, "%s/%s-%s/%s.%s", FILES_URL, syslinux, embedded_sl_version_str[1], ldlinux, ldlinux_ext[2]); 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) if (DownloadSignedFile(tmp, &tmp[sizeof(FILES_URL)], hMainDialog, TRUE) == 0)
return FALSE; goto out;
} }
} }
} else if (bt == BT_MSDOS) { } else if (bt == BT_MSDOS) {
if ((size_check) && (ComboBox_GetItemData(hClusterSize, ComboBox_GetCurSel(hClusterSize)) >= 65536)) { if ((size_check) && (ComboBox_GetItemData(hClusterSize, ComboBox_GetCurSel(hClusterSize)) >= 65536)) {
// MS-DOS cannot boot from a drive using a 64 kilobytes Cluster size // 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); 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) { } else if (bt == BT_GRUB4DOS) {
IGNORE_RETVAL(_chdirU(app_dir)); 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), 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); lmprintf(MSG_103, tmp), MB_YESNOCANCEL|MB_ICONWARNING|MB_IS_RTL, selected_langid);
if (r == IDCANCEL) if (r == IDCANCEL)
return FALSE; goto out;
if (r == IDYES) { if (r == IDYES) {
static_sprintf(tmp, "grub4dos-%s", GRUB4DOS_VERSION); static_sprintf(tmp, "grub4dos-%s", GRUB4DOS_VERSION);
IGNORE_RETVAL(_mkdir(tmp)); IGNORE_RETVAL(_mkdir(tmp));
static_sprintf(tmp, "%s/grub4dos-%s/grldr", FILES_URL, GRUB4DOS_VERSION); static_sprintf(tmp, "%s/grub4dos-%s/grldr", FILES_URL, GRUB4DOS_VERSION);
if (DownloadFile(tmp, &tmp[sizeof(FILES_URL)], hMainDialog) == 0) if (DownloadSignedFile(tmp, &tmp[sizeof(FILES_URL)], hMainDialog, TRUE) == 0)
return FALSE; goto out;
} }
} }
} }
@ -1760,10 +1773,14 @@ uefi_target:
fs = (int)ComboBox_GetItemData(hFileSystem, ComboBox_GetCurSel(hFileSystem)); fs = (int)ComboBox_GetItemData(hFileSystem, ComboBox_GetCurSel(hFileSystem));
if (fs != FS_NTFS) { if (fs != FS_NTFS) {
MessageBoxExU(hMainDialog, lmprintf(MSG_097, "UEFI:NTFS"), lmprintf(MSG_092), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid); 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) 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); hw = max(hw, GetTextSize(GetDlgItem(hDlg, IDC_TARGET_SYSTEM), lmprintf(msg_id)).cx);
// Just in case, we also do the number of passes // Just in case, we also do the number of passes
for (i = 1; i <= 4; i++) for (i = 1; i <= 5; i++) {
hw = max(hw, GetTextSize(GetDlgItem(hDlg, IDC_TARGET_SYSTEM), char* msg = (i == 1) ? lmprintf(MSG_034, 1) : lmprintf(MSG_035, (i == 2) ? 2 : 4, (i == 2) ? "" : lmprintf(MSG_087, flash_type[i - 3]));
lmprintf((i == 1) ? MSG_034 : MSG_035, i)).cx); 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 // Finally, we must ensure that we'll have enough space for the 2 checkbox controls
// that end up with a half dropdown // that end up with a half dropdown
@ -2529,7 +2547,7 @@ static void InitDialog(HWND hDlg)
DWORD len; DWORD len;
HDC hDC; HDC hDC;
int i, lfHeight; 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) }; static char* resource[2] = { MAKEINTRESOURCEA(IDR_SL_LDLINUX_V4_SYS), MAKEINTRESOURCEA(IDR_SL_LDLINUX_V6_SYS) };
#ifdef RUFUS_TEST #ifdef RUFUS_TEST
@ -2635,8 +2653,9 @@ static void InitDialog(HWND hDlg)
SendMessage(hProgress, PBM_SETRANGE, 0, (MAX_PROGRESS<<16) & 0xFFFF0000); SendMessage(hProgress, PBM_SETRANGE, 0, (MAX_PROGRESS<<16) & 0xFFFF0000);
// Fill up the passes // Fill up the passes
for (i=0; i<4; i++) { for (i = 1; i <= 5; i++) {
IGNORE_RETVAL(ComboBox_AddStringU(hNBPasses, lmprintf((i==0)?MSG_034:MSG_035, i+1))); 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)); IGNORE_RETVAL(ComboBox_SetCurSel(hNBPasses, 0));
SetPassesTooltip(); SetPassesTooltip();
@ -2973,7 +2992,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
case WM_COMMAND: case WM_COMMAND:
#ifdef RUFUS_TEST #ifdef RUFUS_TEST
if (LOWORD(wParam) == IDC_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; break;
} }
#endif #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 // User might be trying to cancel during preliminary checks
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANCELLED; FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANCELLED;
PrintInfo(0, MSG_201); PrintInfo(0, MSG_201);
EnableWindow(GetDlgItem(hDlg, IDCANCEL), TRUE);
return (INT_PTR)TRUE; return (INT_PTR)TRUE;
} }
if (ulRegister != 0) if (ulRegister != 0)
@ -3217,6 +3237,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
} }
} }
FormatStatus = 0; FormatStatus = 0;
format_op_in_progress = FALSE;
if (CreateThread(NULL, 0, ISOScanThread, NULL, 0, NULL) == NULL) { if (CreateThread(NULL, 0, ISOScanThread, NULL, 0, NULL) == NULL) {
uprintf("Unable to start ISO scanning thread"); uprintf("Unable to start ISO scanning thread");
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_START_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); SetTaskbarProgressValue(0, MAX_PROGRESS);
SendMessage(hProgress, PBM_SETPOS, 0, 0); SendMessage(hProgress, PBM_SETPOS, 0, 0);
selection_default = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType)); selection_default = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType));
nDeviceIndex = ComboBox_GetCurSel(hDeviceList); // Create a thread to validate options and download files as needed (so that we can update the UI).
if (nDeviceIndex != CB_ERR) { // On exit, this thread sends message UM_FORMAT_START back to this dialog.
if (!zero_drive) { if (CreateThread(NULL, 0, BootCheckThread, NULL, 0, NULL) == NULL) {
if ((bt != BT_NON_BOOTABLE) && (!BootCheck())) uprintf("Unable to start boot check thread");
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); FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | APPERR(ERROR_CANT_START_THREAD);
PostMessage(hMainDialog, UM_FORMAT_COMPLETED, (WPARAM)FALSE, 0); 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; break;
case IDC_LANG: case IDC_LANG:
// Show the language menu such that it doesn't overlap the button // 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); SendMessage(hUpdatesDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hUpdatesDlg, IDC_CHECK_NOW), TRUE);
break; 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: case UM_FORMAT_COMPLETED:
format_thid = NULL; format_thid = NULL;
// Stop the timer // Stop the timer

View file

@ -67,7 +67,12 @@
#define MARQUEE_TIMER_REFRESH 10 // Time between progress bar marquee refreshes, in ms #define MARQUEE_TIMER_REFRESH 10 // Time between progress bar marquee refreshes, in ms
#define FS_DEFAULT FS_FAT32 #define FS_DEFAULT FS_FAT32
#define SINGLE_CLUSTERSIZE_DEFAULT 0x00000100 #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 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_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 #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 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 DD_BUFFER_SIZE 65536 // Minimum size of the buffer we use for DD operations
#define UBUFFER_SIZE 2048 #define UBUFFER_SIZE 2048
#define RSA_SIGNATURE_SIZE 256
#define CBN_SELCHANGE_INTERNAL (CBN_SELCHANGE + 256) #define CBN_SELCHANGE_INTERNAL (CBN_SELCHANGE + 256)
#define RUFUS_URL "https://rufus.ie" #define RUFUS_URL "https://rufus.ie"
#define DOWNLOAD_URL RUFUS_URL "/downloads" #define DOWNLOAD_URL RUFUS_URL "/downloads"
@ -157,6 +163,7 @@ enum user_message_type {
UM_NO_UPDATE, UM_NO_UPDATE,
UM_UPDATE_CSM_TOOLTIP, UM_UPDATE_CSM_TOOLTIP,
UM_RESIZE_BUTTONS, UM_RESIZE_BUTTONS,
UM_FORMAT_START,
// Start of the WM IDs for the language menu items // Start of the WM IDs for the language menu items
UM_LANGUAGE_MENU = WM_APP + 0x100 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 szFolderPath[MAX_PATH], app_dir[MAX_PATH], temp_dir[MAX_PATH], system_dir[MAX_PATH], sysnative_dir[MAX_PATH];
extern char* image_path; extern char* image_path;
extern DWORD FormatStatus, DownloadStatus, MainThreadId; extern DWORD FormatStatus, DownloadStatus, MainThreadId;
extern BOOL PromptOnError;
extern unsigned long syslinux_ldlinux_len[2]; extern unsigned long syslinux_ldlinux_len[2];
extern const int nb_steps[FS_MAX]; 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; 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 GetOpticalMedia(IMG_SAVE* img_save);
extern BOOL SetLGP(BOOL bRestore, BOOL* bExistingKey, const char* szPath, const char* szPolicy, DWORD dwValue); extern BOOL SetLGP(BOOL bRestore, BOOL* bExistingKey, const char* szPath, const char* szPolicy, DWORD dwValue);
extern LONG GetEntryWidth(HWND hDropDown, const char* entry); extern LONG GetEntryWidth(HWND hDropDown, const char* entry);
extern DWORD DownloadFile(const char* url, const char* file, HWND hProgressDialog); extern DWORD DownloadSignedFile(const char* url, const char* file, HWND hProgressDialog, BOOL PromptOnError);
extern HANDLE DownloadFileThreaded(const char* url, const char* file, HWND hProgressDialog); 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 INT_PTR CALLBACK UpdateCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
extern BOOL SetUpdateCheck(void); extern BOOL SetUpdateCheck(void);
extern BOOL CheckForUpdates(BOOL force); 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 char* GetSignatureName(const char* path, const char* country_code);
extern uint64_t GetSignatureTimeStamp(const char* path); extern uint64_t GetSignatureTimeStamp(const char* path);
extern LONG ValidateSignature(HWND hDlg, 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 IsFontAvailable(const char* font_name);
extern BOOL WriteFileWithRetry(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, extern BOOL WriteFileWithRetry(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten, DWORD nNumRetries); LPDWORD lpNumberOfBytesWritten, DWORD nNumRetries);
@ -607,3 +614,4 @@ static __inline HMODULE GetLibraryHandle(char* szLibraryName) {
#define ERROR_CANT_PATCH 0x120A #define ERROR_CANT_PATCH 0x120A
#define ERROR_CANT_ASSIGN_LETTER 0x120B #define ERROR_CANT_ASSIGN_LETTER 0x120B
#define ERROR_CANT_MOUNT_VOLUME 0x120C #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 IDD_DIALOG DIALOGEX 12, 12, 232, 326
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_ACCEPTFILES EXSTYLE WS_EX_ACCEPTFILES
CAPTION "Rufus 3.1.1323" CAPTION "Rufus 3.2.1328"
FONT 9, "Segoe UI Symbol", 400, 0, 0x0 FONT 9, "Segoe UI Symbol", 400, 0, 0x0
BEGIN BEGIN
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
@ -389,8 +389,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,1,1323,0 FILEVERSION 3,2,1328,0
PRODUCTVERSION 3,1,1323,0 PRODUCTVERSION 3,2,1328,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -407,13 +407,13 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
VALUE "FileDescription", "Rufus" VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "3.1.1323" VALUE "FileVersion", "3.2.1328"
VALUE "InternalName", "Rufus" VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2018 Pete Batard (GPL v3)" VALUE "LegalCopyright", "© 2011-2018 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
VALUE "OriginalFilename", "rufus.exe" VALUE "OriginalFilename", "rufus.exe"
VALUE "ProductName", "Rufus" VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "3.1.1323" VALUE "ProductVersion", "3.2.1328"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

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

View file

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