mirror of
https://github.com/pbatard/rufus.git
synced 2025-05-09 12:31:57 -04:00
[misc] improve revoked UEFI bootloader reporting
* Also fix SBAT not being properly parsed for PE32 executables. * Also fix signature truncation in GetIssuerCertificateInfo() and fall back to returning signer data if issuer is not available (which is typically the case for GRUB signed bootloaders). * Also fix status messages on user cancellation/proceeding.
This commit is contained in:
parent
6b5837dbb5
commit
ede52c57e6
7 changed files with 98 additions and 71 deletions
|
@ -610,6 +610,7 @@ t MSG_347 "Expert Mode"
|
|||
t MSG_348 "Extracting archive files: %s"
|
||||
t MSG_349 "Use Rufus MBR"
|
||||
t MSG_350 "Use 'Windows UEFI CA 2023' signed bootloaders [EXPERIMENTAL]"
|
||||
t MSG_351 "Checking for UEFI bootloader revocation..."
|
||||
# The following messages are for the Windows Store listing only and are not used by the application
|
||||
t MSG_900 "Rufus is a utility that helps format and create bootable USB flash drives, such as USB keys/pendrives, memory sticks, etc."
|
||||
t MSG_901 "Official site: %s"
|
||||
|
|
33
src/hash.c
33
src/hash.c
|
@ -117,7 +117,7 @@ StrArray modified_files = { 0 };
|
|||
extern int default_thread_priority;
|
||||
extern const char* efi_archname[ARCH_MAX];
|
||||
extern char* sbat_level_txt;
|
||||
extern BOOL expert_mode;
|
||||
extern BOOL expert_mode, usb_debug;
|
||||
|
||||
/*
|
||||
* Rotate 32 or 64 bit integers by n bytes.
|
||||
|
@ -2081,7 +2081,7 @@ BOOL IsFileInDB(const char* path)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL IsRevokedBySbat(uint8_t* buf, uint32_t len)
|
||||
static BOOL IsRevokedBySbat(uint8_t* buf, uint32_t len)
|
||||
{
|
||||
char* sbat = NULL, *version_str;
|
||||
uint32_t i, j, sbat_len;
|
||||
|
@ -2109,6 +2109,7 @@ BOOL IsRevokedBySbat(uint8_t* buf, uint32_t len)
|
|||
for (; sbat[i] != ',' && sbat[i] != '\0' && sbat[i] != '\n'; i++);
|
||||
sbat[i++] = '\0';
|
||||
entry.version = atoi(version_str);
|
||||
uuprintf(" SBAT: %s,%d", entry.product, entry.version);
|
||||
for (; sbat[i] != '\0' && sbat[i] != '\n'; i++);
|
||||
if (entry.version == 0)
|
||||
continue;
|
||||
|
@ -2121,13 +2122,13 @@ BOOL IsRevokedBySbat(uint8_t* buf, uint32_t len)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL IsRevokedBySvn(uint8_t* buf, uint32_t len)
|
||||
static BOOL IsRevokedBySvn(uint8_t* buf, uint32_t len)
|
||||
{
|
||||
wchar_t* rsrc_name = NULL;
|
||||
uint8_t *root;
|
||||
uint32_t i, j, rsrc_rva, rsrc_len, *svn_ver;
|
||||
IMAGE_DOS_HEADER* dos_header = (IMAGE_DOS_HEADER*)buf;
|
||||
IMAGE_NT_HEADERS* pe_header;
|
||||
IMAGE_NT_HEADERS32* pe_header;
|
||||
IMAGE_NT_HEADERS64* pe64_header;
|
||||
IMAGE_DATA_DIRECTORY img_data_dir;
|
||||
|
||||
|
@ -2143,7 +2144,7 @@ BOOL IsRevokedBySvn(uint8_t* buf, uint32_t len)
|
|||
if (rsrc_name == NULL)
|
||||
continue;
|
||||
|
||||
pe_header = (IMAGE_NT_HEADERS*)&buf[dos_header->e_lfanew];
|
||||
pe_header = (IMAGE_NT_HEADERS32*)&buf[dos_header->e_lfanew];
|
||||
if (pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_I386 || pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_ARM) {
|
||||
img_data_dir = pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
|
||||
} else {
|
||||
|
@ -2157,6 +2158,7 @@ BOOL IsRevokedBySvn(uint8_t* buf, uint32_t len)
|
|||
if (rsrc_rva != 0) {
|
||||
if (rsrc_len == sizeof(uint32_t)) {
|
||||
svn_ver = (uint32_t*)RvaToPhysical(buf, rsrc_rva);
|
||||
uuprintf(" SVN version: %d.%d", *svn_ver >> 16, *svn_ver & 0xffff);
|
||||
if (svn_ver != NULL && *svn_ver < sbat_entries[i].version)
|
||||
return TRUE;
|
||||
} else {
|
||||
|
@ -2167,18 +2169,20 @@ BOOL IsRevokedBySvn(uint8_t* buf, uint32_t len)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL IsRevokedByCert(uint8_t* buf, uint32_t len)
|
||||
static BOOL IsRevokedByCert(uint8_t* buf, uint32_t len)
|
||||
{
|
||||
int i;
|
||||
uint8_t* cert;
|
||||
cert_info_t info;
|
||||
|
||||
cert = GetPeSignatureData(buf);
|
||||
if (cert == NULL)
|
||||
return FALSE;
|
||||
if (!GetIssuerCertificateInfo(cert, &info))
|
||||
i = GetIssuerCertificateInfo(cert, &info);
|
||||
if (i == 0)
|
||||
uuprintf(" (Unsigned Bootloader)");
|
||||
if (i <= 0)
|
||||
return FALSE;
|
||||
|
||||
uuprintf(" Signed by: %s", info.name);
|
||||
for (i = 0; i < ARRAYSIZE(certdbx); i += SHA1_HASHSIZE) {
|
||||
if (!expert_mode)
|
||||
continue;
|
||||
|
@ -2195,7 +2199,7 @@ int IsBootloaderRevoked(uint8_t* buf, uint32_t len)
|
|||
uint32_t i;
|
||||
uint8_t hash[SHA256_HASHSIZE];
|
||||
IMAGE_DOS_HEADER* dos_header = (IMAGE_DOS_HEADER*)buf;
|
||||
IMAGE_NT_HEADERS* pe_header;
|
||||
IMAGE_NT_HEADERS32* pe_header;
|
||||
|
||||
// Fall back to embedded sbat_level.txt if we couldn't access remote
|
||||
if (sbat_entries == NULL) {
|
||||
|
@ -2205,11 +2209,15 @@ int IsBootloaderRevoked(uint8_t* buf, uint32_t len)
|
|||
|
||||
if (buf == NULL || len < 0x100 || dos_header->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
return -2;
|
||||
pe_header = (IMAGE_NT_HEADERS*)&buf[dos_header->e_lfanew];
|
||||
pe_header = (IMAGE_NT_HEADERS32*)&buf[dos_header->e_lfanew];
|
||||
if (pe_header->Signature != IMAGE_NT_SIGNATURE)
|
||||
return -2;
|
||||
if (!PE256Buffer(buf, len, hash))
|
||||
return -1;
|
||||
// Check for UEFI DBX certificate revocation
|
||||
// This also displays the name of the signer/issuer cert if available
|
||||
if (IsRevokedByCert(buf, len))
|
||||
return 5;
|
||||
// Check for UEFI DBX revocation
|
||||
for (i = 0; i < ARRAYSIZE(pe256dbx); i += SHA256_HASHSIZE)
|
||||
if (memcmp(hash, &pe256dbx[i], SHA256_HASHSIZE) == 0)
|
||||
|
@ -2224,9 +2232,6 @@ int IsBootloaderRevoked(uint8_t* buf, uint32_t len)
|
|||
// Check for Microsoft SVN revocation
|
||||
if (IsRevokedBySvn(buf, len))
|
||||
return 4;
|
||||
// Check for DBX certificate revocation
|
||||
if (IsRevokedByCert(buf, len))
|
||||
return 5;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
24
src/parser.c
24
src/parser.c
|
@ -1643,12 +1643,12 @@ sbat_entry_t* GetSbatEntries(char* sbatlevel)
|
|||
uint16_t GetPeArch(uint8_t* buf)
|
||||
{
|
||||
IMAGE_DOS_HEADER* dos_header = (IMAGE_DOS_HEADER*)buf;
|
||||
IMAGE_NT_HEADERS* pe_header;
|
||||
IMAGE_NT_HEADERS32* pe_header;
|
||||
|
||||
if (buf == NULL || dos_header->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
return IMAGE_FILE_MACHINE_UNKNOWN;
|
||||
|
||||
pe_header = (IMAGE_NT_HEADERS*)&buf[dos_header->e_lfanew];
|
||||
pe_header = (IMAGE_NT_HEADERS32*)&buf[dos_header->e_lfanew];
|
||||
if (pe_header->Signature != IMAGE_NT_SIGNATURE)
|
||||
return IMAGE_FILE_MACHINE_UNKNOWN;
|
||||
return pe_header->FileHeader.Machine;
|
||||
|
@ -1660,7 +1660,7 @@ uint8_t* GetPeSection(uint8_t* buf, const char* name, uint32_t* len)
|
|||
char section_name[IMAGE_SIZEOF_SHORT_NAME] = { 0 };
|
||||
uint32_t i, nb_sections;
|
||||
IMAGE_DOS_HEADER* dos_header = (IMAGE_DOS_HEADER*)buf;
|
||||
IMAGE_NT_HEADERS* pe_header;
|
||||
IMAGE_NT_HEADERS32* pe_header;
|
||||
IMAGE_NT_HEADERS64* pe64_header;
|
||||
IMAGE_SECTION_HEADER* section_header;
|
||||
|
||||
|
@ -1669,7 +1669,7 @@ uint8_t* GetPeSection(uint8_t* buf, const char* name, uint32_t* len)
|
|||
if (buf == NULL || name == NULL || dos_header->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
return NULL;
|
||||
|
||||
pe_header = (IMAGE_NT_HEADERS*)&buf[dos_header->e_lfanew];
|
||||
pe_header = (IMAGE_NT_HEADERS32*)&buf[dos_header->e_lfanew];
|
||||
if (pe_header->Signature != IMAGE_NT_SIGNATURE)
|
||||
return NULL;
|
||||
if (pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_I386 || pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_ARM) {
|
||||
|
@ -1695,14 +1695,14 @@ uint8_t* RvaToPhysical(uint8_t* buf, uint32_t rva)
|
|||
{
|
||||
uint32_t i, nb_sections;
|
||||
IMAGE_DOS_HEADER* dos_header = (IMAGE_DOS_HEADER*)buf;
|
||||
IMAGE_NT_HEADERS* pe_header;
|
||||
IMAGE_NT_HEADERS32* pe_header;
|
||||
IMAGE_NT_HEADERS64* pe64_header;
|
||||
IMAGE_SECTION_HEADER* section_header;
|
||||
|
||||
if (buf == NULL || dos_header->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
return NULL;
|
||||
|
||||
pe_header = (IMAGE_NT_HEADERS*)&buf[dos_header->e_lfanew];
|
||||
pe_header = (IMAGE_NT_HEADERS32*)&buf[dos_header->e_lfanew];
|
||||
if (pe_header->Signature != IMAGE_NT_SIGNATURE)
|
||||
return NULL;
|
||||
if (pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_I386 || pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_ARM) {
|
||||
|
@ -1767,18 +1767,24 @@ uint32_t FindResourceRva(const wchar_t* name, uint8_t* root, uint8_t* dir, uint3
|
|||
uint8_t* GetPeSignatureData(uint8_t* buf)
|
||||
{
|
||||
IMAGE_DOS_HEADER* dos_header = (IMAGE_DOS_HEADER*)buf;
|
||||
IMAGE_NT_HEADERS* pe_header;
|
||||
IMAGE_NT_HEADERS32* pe_header;
|
||||
IMAGE_NT_HEADERS64* pe64_header;
|
||||
IMAGE_DATA_DIRECTORY sec_dir;
|
||||
WIN_CERTIFICATE* cert;
|
||||
|
||||
if (buf == NULL || dos_header->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
return NULL;
|
||||
|
||||
pe_header = (IMAGE_NT_HEADERS*)&buf[dos_header->e_lfanew];
|
||||
pe_header = (IMAGE_NT_HEADERS32*)&buf[dos_header->e_lfanew];
|
||||
if (pe_header->Signature != IMAGE_NT_SIGNATURE)
|
||||
return NULL;
|
||||
|
||||
sec_dir = pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY];
|
||||
if (pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_I386 || pe_header->FileHeader.Machine == IMAGE_FILE_MACHINE_ARM) {
|
||||
sec_dir = pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY];
|
||||
} else {
|
||||
pe64_header = (IMAGE_NT_HEADERS64*)pe_header;
|
||||
sec_dir = pe64_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY];
|
||||
}
|
||||
if (sec_dir.VirtualAddress == 0 || sec_dir.Size == 0)
|
||||
return NULL;
|
||||
|
||||
|
|
54
src/pki.c
54
src/pki.c
|
@ -384,27 +384,31 @@ out:
|
|||
return p;
|
||||
}
|
||||
|
||||
// Return the issuer certificate's name and thumbprint
|
||||
BOOL GetIssuerCertificateInfo(uint8_t* cert, cert_info_t* info)
|
||||
// Fills the certificate's name and thumbprint.
|
||||
// Tries the issuer first, and if none is available, falls back to current cert.
|
||||
// Returns 0 for unsigned, -1 on error, 1 for signer or 2 for issuer.
|
||||
int GetIssuerCertificateInfo(uint8_t* cert, cert_info_t* info)
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
int ret = 0;
|
||||
DWORD dwSize, dwEncoding, dwContentType, dwFormatType, dwSignerInfoSize = 0;
|
||||
WIN_CERTIFICATE* pWinCert = (WIN_CERTIFICATE*)cert;
|
||||
CRYPT_DATA_BLOB signedDataBlob;
|
||||
HCERTSTORE hStore = NULL;
|
||||
HCRYPTMSG hMsg = NULL;
|
||||
PCMSG_SIGNER_INFO pSignerInfo = NULL;
|
||||
PCCERT_CONTEXT pCertContext = NULL, pIssuerCertContext = NULL;
|
||||
PCCERT_CONTEXT pCertContext[2] = { NULL, NULL };
|
||||
PCCERT_CHAIN_CONTEXT pChainContext = NULL;
|
||||
CERT_CHAIN_PARA chainPara;
|
||||
int CertIndex = 0;
|
||||
|
||||
if (cert == NULL || info == NULL || pWinCert->dwLength == 0)
|
||||
return FALSE;
|
||||
|
||||
signedDataBlob.cbData = pWinCert->dwLength - sizeof(WIN_CERTIFICATE);
|
||||
signedDataBlob.pbData = pWinCert->bCertificate;
|
||||
if (info == NULL)
|
||||
return -1;
|
||||
if (pWinCert == NULL || pWinCert->dwLength == 0)
|
||||
return 0;
|
||||
|
||||
// Get message handle and store handle from the signed file.
|
||||
signedDataBlob.cbData = pWinCert->dwLength;
|
||||
signedDataBlob.pbData = pWinCert->bCertificate;
|
||||
if (!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &signedDataBlob,
|
||||
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED, CERT_QUERY_FORMAT_FLAG_BINARY,
|
||||
0, &dwEncoding, &dwContentType, &dwFormatType, &hStore, &hMsg, NULL)) {
|
||||
|
@ -420,7 +424,7 @@ BOOL GetIssuerCertificateInfo(uint8_t* cert, cert_info_t* info)
|
|||
|
||||
// Allocate memory for signer information.
|
||||
pSignerInfo = (PCMSG_SIGNER_INFO)calloc(dwSignerInfoSize, 1);
|
||||
if (!pSignerInfo) {
|
||||
if (pSignerInfo == NULL) {
|
||||
uprintf("PKI: Could not allocate memory for signer information");
|
||||
goto out;
|
||||
}
|
||||
|
@ -432,8 +436,8 @@ BOOL GetIssuerCertificateInfo(uint8_t* cert, cert_info_t* info)
|
|||
}
|
||||
|
||||
// Search for the signer certificate in the temporary certificate store.
|
||||
pCertContext = CertFindCertificateInStore(hStore, ENCODING, 0, CERT_FIND_SUBJECT_CERT, (PVOID)pSignerInfo, NULL);
|
||||
if (!pCertContext) {
|
||||
pCertContext[0] = CertFindCertificateInStore(hStore, ENCODING, 0, CERT_FIND_SUBJECT_CERT, (PVOID)pSignerInfo, NULL);
|
||||
if (pCertContext[0] == NULL) {
|
||||
uprintf("PKI: Failed to locate signer certificate in store: %s", WinPKIErrorString());
|
||||
goto out;
|
||||
}
|
||||
|
@ -441,21 +445,19 @@ BOOL GetIssuerCertificateInfo(uint8_t* cert, cert_info_t* info)
|
|||
// Build a certificate chain to get the issuer (CA) certificate.
|
||||
memset(&chainPara, 0, sizeof(chainPara));
|
||||
chainPara.cbSize = sizeof(CERT_CHAIN_PARA);
|
||||
if (!CertGetCertificateChain(NULL, pCertContext, NULL, hStore, &chainPara, 0, NULL, &pChainContext)) {
|
||||
if (!CertGetCertificateChain(NULL, pCertContext[0], NULL, hStore, &chainPara, 0, NULL, &pChainContext)) {
|
||||
uprintf("PKI: Failed to build certificate chain. Error code: %s", WinPKIErrorString());
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Get the issuer's certificate (second certificate in the chain)
|
||||
// Try to get the issuer's certificate (second certificate in the chain) if available
|
||||
if (pChainContext->cChain > 0 && pChainContext->rgpChain[0]->cElement > 1) {
|
||||
pIssuerCertContext = pChainContext->rgpChain[0]->rgpElement[1]->pCertContext;
|
||||
} else {
|
||||
uprintf("PKI: Failed to retrieve issuer's certificate: %s", WinPKIErrorString());
|
||||
goto out;
|
||||
pCertContext[1] = pChainContext->rgpChain[0]->rgpElement[1]->pCertContext;
|
||||
CertIndex = 1;
|
||||
}
|
||||
|
||||
// Isolate the signing certificate subject name
|
||||
dwSize = CertGetNameStringA(pIssuerCertContext, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME,
|
||||
dwSize = CertGetNameStringA(pCertContext[CertIndex], CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME,
|
||||
info->name, sizeof(info->name));
|
||||
if (dwSize <= 1) {
|
||||
uprintf("PKI: Failed to get Subject Name");
|
||||
|
@ -463,19 +465,19 @@ BOOL GetIssuerCertificateInfo(uint8_t* cert, cert_info_t* info)
|
|||
}
|
||||
|
||||
dwSize = SHA1_HASHSIZE;
|
||||
if (!CryptHashCertificate(0, CALG_SHA1, 0, pIssuerCertContext->pbCertEncoded,
|
||||
pIssuerCertContext->cbCertEncoded, info->thumbprint, &dwSize)) {
|
||||
if (!CryptHashCertificate(0, CALG_SHA1, 0, pCertContext[CertIndex]->pbCertEncoded,
|
||||
pCertContext[CertIndex]->cbCertEncoded, info->thumbprint, &dwSize)) {
|
||||
uprintf("PKI: Failed to compute the thumbprint: %s", WinPKIErrorString());
|
||||
goto out;
|
||||
}
|
||||
ret = TRUE;
|
||||
ret = CertIndex + 1;
|
||||
|
||||
out:
|
||||
safe_free(pSignerInfo);
|
||||
if (pIssuerCertContext != NULL)
|
||||
CertFreeCertificateContext(pIssuerCertContext);
|
||||
if (pCertContext != NULL)
|
||||
CertFreeCertificateContext(pCertContext);
|
||||
if (pCertContext[1] != NULL)
|
||||
CertFreeCertificateContext(pCertContext[1]);
|
||||
if (pCertContext[0] != NULL)
|
||||
CertFreeCertificateContext(pCertContext[0]);
|
||||
if (hStore != NULL)
|
||||
CertCloseStore(hStore, 0);
|
||||
if (hMsg != NULL)
|
||||
|
|
45
src/rufus.c
45
src/rufus.c
|
@ -1399,7 +1399,7 @@ out:
|
|||
// Likewise, boot check will block message processing => use a thread
|
||||
static DWORD WINAPI BootCheckThread(LPVOID param)
|
||||
{
|
||||
int i, r, username_index = -1;
|
||||
int i, r, rr, username_index = -1;
|
||||
FILE *fd;
|
||||
uint32_t len;
|
||||
uint8_t* buf = NULL;
|
||||
|
@ -1609,33 +1609,43 @@ static DWORD WINAPI BootCheckThread(LPVOID param)
|
|||
|
||||
// Check UEFI bootloaders for revocation
|
||||
if (IS_EFI_BOOTABLE(img_report)) {
|
||||
assert(ARRAYSIZE(img_report.efi_boot_path) > 0);
|
||||
PrintStatus(0, MSG_351);
|
||||
uuprintf("UEFI Secure Boot revocation checks:");
|
||||
rr = 0;
|
||||
for (i = 0; i < ARRAYSIZE(img_report.efi_boot_path) && img_report.efi_boot_path[i][0] != 0; i++) {
|
||||
static const char* revocation_type[] = { "UEFI DBX", "Windows SSP", "Linux SBAT", "Windows SVN", "Cert DBX" };
|
||||
cdio_loglevel_default = CDIO_LOG_WARN;
|
||||
len = ReadISOFileToBuffer(image_path, img_report.efi_boot_path[i], &buf);
|
||||
cdio_loglevel_default = usb_debug ? CDIO_LOG_DEBUG : CDIO_LOG_WARN;
|
||||
if (len == 0) {
|
||||
uprintf("Warning: Failed to extract '%s' to check for UEFI revocation", img_report.efi_boot_path[i]);
|
||||
continue;
|
||||
}
|
||||
uuprintf("• %s", img_report.efi_boot_path[i]);
|
||||
r = IsBootloaderRevoked(buf, len);
|
||||
safe_free(buf);
|
||||
if (r > 0) {
|
||||
assert(r <= ARRAYSIZE(revocation_type));
|
||||
if (rr == 0)
|
||||
rr = r;
|
||||
uprintf("Warning: '%s' has been revoked by %s", img_report.efi_boot_path[i], revocation_type[r - 1]);
|
||||
is_bootloader_revoked = TRUE;
|
||||
switch (r) {
|
||||
case 2:
|
||||
msg = lmprintf(MSG_341, "Error code: 0xc0000428");
|
||||
break;
|
||||
default:
|
||||
msg = lmprintf(MSG_340);
|
||||
break;
|
||||
}
|
||||
r = MessageBoxExU(hMainDialog, lmprintf(MSG_339, msg), lmprintf(MSG_338),
|
||||
MB_OKCANCEL | MB_ICONWARNING | MB_IS_RTL, selected_langid);
|
||||
if (r == IDCANCEL)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (rr > 0) {
|
||||
switch (rr) {
|
||||
case 2:
|
||||
msg = lmprintf(MSG_341, "Error code: 0xc0000428");
|
||||
break;
|
||||
default:
|
||||
msg = lmprintf(MSG_340);
|
||||
break;
|
||||
}
|
||||
r = MessageBoxExU(hMainDialog, lmprintf(MSG_339, msg), lmprintf(MSG_338),
|
||||
MB_OKCANCEL | MB_ICONWARNING | MB_IS_RTL, selected_langid);
|
||||
if (r == IDCANCEL)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1691,7 +1701,6 @@ static DWORD WINAPI BootCheckThread(LPVOID param)
|
|||
IGNORE_RETVAL(_chdir(tmp));
|
||||
// The following loops through the grub2 version (which may have the ISO label appended)
|
||||
// and breaks it according to '.' or '-' until it finds a match on the server.
|
||||
//
|
||||
for (i = (int)strlen(img_report.grub2_version), grub2_len = 0; i > 0 && grub2_len <= 0; i--) {
|
||||
c = img_report.grub2_version[i];
|
||||
if (c != 0 && c != '.' && c != '-')
|
||||
|
@ -1761,7 +1770,7 @@ static DWORD WINAPI BootCheckThread(LPVOID param)
|
|||
IGNORE_RETVAL(_chdirU(app_data_dir));
|
||||
IGNORE_RETVAL(_mkdir(FILES_DIR));
|
||||
IGNORE_RETVAL(_chdir(FILES_DIR));
|
||||
for (i=0; i<2; i++) {
|
||||
for (i = 0; i < 2; i++) {
|
||||
// Check if we already have the relevant ldlinux_v#.##.sys & ldlinux_v#.##.bss files
|
||||
static_sprintf(tmp, "%s-%s%s\\%s.%s", syslinux, img_report.sl_version_str,
|
||||
img_report.sl_version_ext, ldlinux, ldlinux_ext[i]);
|
||||
|
@ -1783,7 +1792,7 @@ static DWORD WINAPI BootCheckThread(LPVOID param)
|
|||
lmprintf(MSG_115), MB_YESNO | MB_ICONWARNING | MB_IS_RTL, selected_langid);
|
||||
if (r != IDYES)
|
||||
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);
|
||||
IGNORE_RETVAL(_mkdir(tmp));
|
||||
if (*img_report.sl_version_ext != 0) {
|
||||
|
@ -2970,6 +2979,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
|||
if (!Notification(MSG_WARNING_QUESTION, NULL, NULL, title, lmprintf(MSG_132)))
|
||||
goto aborted_start;
|
||||
}
|
||||
PrintStatus(0, MSG_142);
|
||||
|
||||
GetWindowTextU(hDeviceList, tmp, ARRAYSIZE(tmp));
|
||||
if (MessageBoxExU(hMainDialog, lmprintf(MSG_003, tmp),
|
||||
|
@ -3005,6 +3015,9 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
|
|||
if (queued_hotplug_event)
|
||||
SendMessage(hDlg, UM_MEDIA_CHANGE, 0, 0);
|
||||
if (wParam == BOOTCHECK_CANCEL) {
|
||||
nb_devices = ComboBox_GetCount(hDeviceList);
|
||||
PrintStatus(0, (nb_devices == 1) ? MSG_208 : MSG_209, nb_devices);
|
||||
PrintStatus(5000, MSG_041);
|
||||
if (unattend_xml_path != NULL) {
|
||||
DeleteFileU(unattend_xml_path);
|
||||
unattend_xml_path = NULL;
|
||||
|
|
|
@ -805,7 +805,7 @@ extern void* get_data_from_asn1(const uint8_t* buf, size_t buf_len, const char*
|
|||
extern int sanitize_label(char* label);
|
||||
extern int IsHDD(DWORD DriveIndex, uint16_t vid, uint16_t pid, const char* strid);
|
||||
extern char* GetSignatureName(const char* path, const char* country_code, BOOL bSilent);
|
||||
extern BOOL GetIssuerCertificateInfo(uint8_t* cert, cert_info_t* info);
|
||||
extern int GetIssuerCertificateInfo(uint8_t* cert, cert_info_t* info);
|
||||
extern uint64_t GetSignatureTimeStamp(const char* path);
|
||||
extern LONG ValidateSignature(HWND hDlg, const char* path);
|
||||
extern BOOL ValidateOpensslSignature(BYTE* pbBuffer, DWORD dwBufferLen, BYTE* pbSignature, DWORD dwSigLen);
|
||||
|
|
10
src/rufus.rc
10
src/rufus.rc
|
@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
|||
IDD_DIALOG DIALOGEX 12, 12, 232, 326
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
EXSTYLE WS_EX_ACCEPTFILES
|
||||
CAPTION "Rufus 4.6.2202"
|
||||
CAPTION "Rufus 4.6.2203"
|
||||
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
||||
|
@ -399,8 +399,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 4,6,2202,0
|
||||
PRODUCTVERSION 4,6,2202,0
|
||||
FILEVERSION 4,6,2203,0
|
||||
PRODUCTVERSION 4,6,2203,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -418,13 +418,13 @@ BEGIN
|
|||
VALUE "Comments", "https://rufus.ie"
|
||||
VALUE "CompanyName", "Akeo Consulting"
|
||||
VALUE "FileDescription", "Rufus"
|
||||
VALUE "FileVersion", "4.6.2202"
|
||||
VALUE "FileVersion", "4.6.2203"
|
||||
VALUE "InternalName", "Rufus"
|
||||
VALUE "LegalCopyright", "© 2011-2024 Pete Batard (GPL v3)"
|
||||
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
|
||||
VALUE "OriginalFilename", "rufus-4.6.exe"
|
||||
VALUE "ProductName", "Rufus"
|
||||
VALUE "ProductVersion", "4.6.2202"
|
||||
VALUE "ProductVersion", "4.6.2203"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue