diff --git a/.vs/ms-sys.vcxproj b/.vs/ms-sys.vcxproj
index ead1e5ac..a24b8efb 100644
--- a/.vs/ms-sys.vcxproj
+++ b/.vs/ms-sys.vcxproj
@@ -70,6 +70,8 @@
+
+
diff --git a/.vs/ms-sys.vcxproj.filters b/.vs/ms-sys.vcxproj.filters
index f469421c..c714b2af 100644
--- a/.vs/ms-sys.vcxproj.filters
+++ b/.vs/ms-sys.vcxproj.filters
@@ -152,6 +152,12 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
diff --git a/ChangeLog.txt b/ChangeLog.txt
index cb604143..351d037d 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -1,12 +1,13 @@
o Version 3.5 (2019.03.??)
- Add a feature to download official retail Windows 8.1 or Windows 10 ISOs from Rufus
+ Add a feature to download official retail Windows 8.1 or Windows 10 ISOs
Add Windows To Go support for MCT generated Windows ISOs
Add a notice about the 'WppRecorder.sys' Microsoft bug for Windows 10 1809 ISOs
Add a notice about trying to format a drive larger than 2 TB in MBR mode
+ Add a notice about Legacy boot when trying to boot UEFI-only media in Legacy mode
Report the full PID and command line of detected blocking processes in the log
Fix a potential silent abort when the drive is in use
Fix 'Quick Format' option always being active
- Fix potentially changing default file system selection after selecting an ISO
+ Fix some unwanted file system changes occurring after an ISO had been selected
o Version 3.4 (2018.12.05)
Set the default image selection directory to Downloads\ instead of My Documents\
diff --git a/res/mbr/gpt.S b/res/mbr/gpt.S
new file mode 100644
index 00000000..4419238e
--- /dev/null
+++ b/res/mbr/gpt.S
@@ -0,0 +1,100 @@
+/********************************************************************************/
+/* GPT - A protective MBR that displays a notice if a user attempts to boot a */
+/* GPT drive in BIOS/Legacy mode. */
+/* */
+/* Copyright (c) 2019 Pete Batard */
+/* */
+/* This program is free software; you can redistribute it and/or modify it */
+/* under the terms of the GNU General Public License as published by the Free */
+/* Software Foundation, either version 3 of the License, or (at your option) */
+/* any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, but WITHOUT */
+/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
+/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */
+/* more details. */
+/* */
+/* You should have received a copy of the GNU General Public License along with */
+/* this program; if not, see . */
+/* */
+/********************************************************************************/
+
+/********************************************************************************/
+/* GNU Assembler Settings: */
+/********************************************************************************/
+.intel_syntax noprefix
+.code16
+/********************************************************************************/
+
+/********************************************************************************/
+/* Constants: */
+/********************************************************************************/
+MBR_ADDR = 0x7c00
+MBR_SIZE = 0x200
+MBR_RESERVED = 0x1b8 # Start of the reserved section (partition table, etc.)
+PT_MAX = 0x04 # Number of partition entries in the partition table
+PT_ENTRY_SIZE = 0x10 # Size of a partition entry in the partition table
+
+/********************************************************************************/
+/* MBR: This section resides at 0x00007c00 and is exactly 512 bytes */
+/********************************************************************************/
+.section main, "ax"
+.globl mbr
+mbr:
+ inc cx
+ dec bx
+ inc bp
+ dec di
+ cld
+ xor ax, ax
+ mov ds, ax
+ mov si, offset sep
+ call print_string
+ mov si, offset hdr
+ call print_string
+ mov si, offset sep
+ call print_string
+ mov si, offset txt
+ call print_string
+ hlt
+
+print_string:
+ lodsb
+ cmp al, 0x00
+ jz 0f
+ mov ah, 0x0e
+ mov bx, 0x0007
+ int 0x10
+ jmp print_string
+0: ret
+
+/********************************************************************************/
+/* Data section */
+/********************************************************************************/
+sep:
+ .string "****************************************\r\n"
+hdr:
+ .string "*** ERROR: LEGACY BOOT OF UEFI MEDIA ***\r\n"
+txt:
+ .ascii "\r\n" \
+ "This drive can only boot in UEFI mode.\r\n" \
+ "It can not boot in BIOS/Legacy mode.\r\n" \
+ "\r\n" \
+ "If you want to boot this drive in BIOS/Legacy mode, you\r\n" \
+ "should recreate it in Rufus using the following settings:\r\n" \
+ "* Partition scheme -> MBR\r\n" \
+ "* Target system -> BIOS...\r\n" \
+ "\0"
+
+/********************************************************************************/
+/* From offset 0x1b8, the MBR contains the partition table and signature data */
+/********************************************************************************/
+ .org MBR_RESERVED
+disk_signature:
+ .space 0x04
+filler:
+ .space 0x02
+partition_table:
+ .space PT_ENTRY_SIZE * PT_MAX
+mbr_signature:
+ .word 0xAA55
diff --git a/res/mbr/gpt.bin b/res/mbr/gpt.bin
new file mode 100644
index 00000000..e3aee1cc
Binary files /dev/null and b/res/mbr/gpt.bin differ
diff --git a/src/format.c b/src/format.c
index 26ee8274..1206213a 100644
--- a/src/format.c
+++ b/src/format.c
@@ -889,6 +889,15 @@ static BOOL WriteMBR(HANDLE hPhysicalDrive)
if (SelectedDrive.SectorSize < 512)
goto out;
+ if (pt == PARTITION_STYLE_GPT) {
+ // Add a notice in the protective MBR
+ fake_fd._handle = (char*)hPhysicalDrive;
+ set_bytes_per_sector(SelectedDrive.SectorSize);
+ uprintf(using_msg, "Rufus protective");
+ r = write_rufus_gpt_mbr(fp);
+ goto notify;
+ }
+
// FormatEx rewrites the MBR and removes the LBA attribute of FAT16
// and FAT32 partitions - we need to correct this in the MBR
buffer = (unsigned char*)_mm_malloc(SelectedDrive.SectorSize, 16);
@@ -1018,6 +1027,9 @@ static BOOL WriteSBR(HANDLE hPhysicalDrive)
FAKE_FD fake_fd = { 0 };
FILE* fp = (FILE*)&fake_fd;
+ if (pt == PARTITION_STYLE_GPT)
+ return TRUE;
+
fake_fd._handle = (char*)hPhysicalDrive;
set_bytes_per_sector(SelectedDrive.SectorSize);
// Ensure that we have sufficient space for the SBR
@@ -1997,7 +2009,7 @@ DWORD WINAPI FormatThread(void* param)
}
// Thanks to Microsoft, we must fix the MBR AFTER the drive has been formatted
- if (pt == PARTITION_STYLE_MBR) {
+ if ((pt == PARTITION_STYLE_MBR) || ((bt != BT_NON_BOOTABLE) && (pt == PARTITION_STYLE_GPT))) {
PrintInfoDebug(0, MSG_228); // "Writing master boot record..."
if ((!WriteMBR(hPhysicalDrive)) || (!WriteSBR(hPhysicalDrive))) {
if (!IS_ERROR(FormatStatus))
diff --git a/src/ms-sys/br.c b/src/ms-sys/br.c
index a6b6318d..ef7ed8bb 100644
--- a/src/ms-sys/br.c
+++ b/src/ms-sys/br.c
@@ -148,6 +148,15 @@ int is_rufus_mbr(FILE *fp)
is_br(fp);
} /* is_rufus_mbr */
+int is_rufus_gpt_mbr(FILE *fp)
+{
+#include "mbr_gpt_rufus.h"
+
+ return
+ contains_data(fp, 0x0, mbr_gpt_rufus_0x0, sizeof(mbr_gpt_rufus_0x0)) &&
+ is_br(fp);
+} /* is_rufus_gpt_mbr */
+
int is_reactos_mbr(FILE *fp)
{
#include "mbr_reactos.h"
@@ -289,6 +298,15 @@ int write_rufus_mbr(FILE *fp)
write_bootmark(fp);
} /* write_rufus_mbr */
+int write_rufus_gpt_mbr(FILE *fp)
+{
+#include "mbr_gpt_rufus.h"
+
+ return
+ write_data(fp, 0x0, mbr_gpt_rufus_0x0, sizeof(mbr_gpt_rufus_0x0)) &&
+ write_bootmark(fp);
+} /* write_rufus_gpt_mbr */
+
int write_reactos_mbr(FILE *fp)
{
#include "mbr_reactos.h"
diff --git a/src/ms-sys/inc/br.h b/src/ms-sys/inc/br.h
index 16cdedb1..a4e3e9d1 100644
--- a/src/ms-sys/inc/br.h
+++ b/src/ms-sys/inc/br.h
@@ -54,6 +54,10 @@ int is_win7_mbr(FILE *fp);
FALSE.The file position will change when this function is called! */
int is_rufus_mbr(FILE *fp);
+/* returns TRUE if the file has a Rufus GPT master boot record, otherwise
+ FALSE.The file position will change when this function is called! */
+int is_rufus_gpt_mbr(FILE *fp);
+
/* returns TRUE if the file has a ReactOS master boot record, otherwise
FALSE.The file position will change when this function is called! */
int is_reactos_mbr(FILE *fp);
@@ -107,6 +111,10 @@ int write_win7_mbr(FILE *fp);
FALSE */
int write_rufus_mbr(FILE *fp);
+/* Writes a Rufus GPT master boot record to a file, returns TRUE on success, otherwise
+ FALSE */
+int write_rufus_gpt_mbr(FILE *fp);
+
/* Writes a ReactOS master boot record to a file, returns TRUE on success, otherwise
FALSE */
int write_reactos_mbr(FILE *fp);
diff --git a/src/ms-sys/inc/mbr_gpt_rufus.h b/src/ms-sys/inc/mbr_gpt_rufus.h
new file mode 100644
index 00000000..2893d263
--- /dev/null
+++ b/src/ms-sys/inc/mbr_gpt_rufus.h
@@ -0,0 +1,41 @@
+/*
+ * Rufus Protective MBR for GPT systems
+ * https://github.com/pbatard/rufus/tree/master/res/mbr
+ * Copyright © 2019 Pete Batard
+ */
+
+unsigned char mbr_gpt_rufus_0x0[] = {
+ 0x41, 0x4B, 0x45, 0x4F, 0xFC, 0x31, 0xC0, 0x8E, 0xD8, 0xBE, 0x31, 0x7C,
+ 0xE8, 0x13, 0x00, 0xBE, 0x5C, 0x7C, 0xE8, 0x0D, 0x00, 0xBE, 0x31, 0x7C,
+ 0xE8, 0x07, 0x00, 0xBE, 0x87, 0x7C, 0xE8, 0x01, 0x00, 0xF4, 0xAC, 0x3C,
+ 0x00, 0x74, 0x09, 0xB4, 0x0E, 0xBB, 0x07, 0x00, 0xCD, 0x10, 0xEB, 0xF2,
+ 0xC3, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
+ 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
+ 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
+ 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x0D, 0x0A, 0x00, 0x2A, 0x2A, 0x2A, 0x20,
+ 0x45, 0x52, 0x52, 0x4F, 0x52, 0x3A, 0x20, 0x4C, 0x45, 0x47, 0x41, 0x43,
+ 0x59, 0x20, 0x42, 0x4F, 0x4F, 0x54, 0x20, 0x4F, 0x46, 0x20, 0x55, 0x45,
+ 0x46, 0x49, 0x20, 0x4D, 0x45, 0x44, 0x49, 0x41, 0x20, 0x2A, 0x2A, 0x2A,
+ 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x54, 0x68, 0x69, 0x73, 0x20, 0x64, 0x72,
+ 0x69, 0x76, 0x65, 0x20, 0x63, 0x61, 0x6E, 0x20, 0x6F, 0x6E, 0x6C, 0x79,
+ 0x20, 0x62, 0x6F, 0x6F, 0x74, 0x20, 0x69, 0x6E, 0x20, 0x55, 0x45, 0x46,
+ 0x49, 0x20, 0x6D, 0x6F, 0x64, 0x65, 0x2E, 0x0D, 0x0A, 0x49, 0x74, 0x20,
+ 0x63, 0x61, 0x6E, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x62, 0x6F, 0x6F, 0x74,
+ 0x20, 0x69, 0x6E, 0x20, 0x42, 0x49, 0x4F, 0x53, 0x2F, 0x4C, 0x65, 0x67,
+ 0x61, 0x63, 0x79, 0x20, 0x6D, 0x6F, 0x64, 0x65, 0x2E, 0x0D, 0x0A, 0x0D,
+ 0x0A, 0x49, 0x66, 0x20, 0x79, 0x6F, 0x75, 0x20, 0x77, 0x61, 0x6E, 0x74,
+ 0x20, 0x74, 0x6F, 0x20, 0x62, 0x6F, 0x6F, 0x74, 0x20, 0x74, 0x68, 0x69,
+ 0x73, 0x20, 0x64, 0x72, 0x69, 0x76, 0x65, 0x20, 0x69, 0x6E, 0x20, 0x42,
+ 0x49, 0x4F, 0x53, 0x2F, 0x4C, 0x65, 0x67, 0x61, 0x63, 0x79, 0x20, 0x6D,
+ 0x6F, 0x64, 0x65, 0x2C, 0x20, 0x79, 0x6F, 0x75, 0x0D, 0x0A, 0x73, 0x68,
+ 0x6F, 0x75, 0x6C, 0x64, 0x20, 0x72, 0x65, 0x63, 0x72, 0x65, 0x61, 0x74,
+ 0x65, 0x20, 0x69, 0x74, 0x20, 0x69, 0x6E, 0x20, 0x52, 0x75, 0x66, 0x75,
+ 0x73, 0x20, 0x75, 0x73, 0x69, 0x6E, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x6F, 0x6C, 0x6C, 0x6F, 0x77, 0x69, 0x6E, 0x67, 0x20, 0x73, 0x65,
+ 0x74, 0x74, 0x69, 0x6E, 0x67, 0x73, 0x3A, 0x0D, 0x0A, 0x2A, 0x20, 0x50,
+ 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x73, 0x63, 0x68,
+ 0x65, 0x6D, 0x65, 0x20, 0x2D, 0x3E, 0x20, 0x4D, 0x42, 0x52, 0x0D, 0x0A,
+ 0x2A, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x20, 0x73, 0x79, 0x73,
+ 0x74, 0x65, 0x6D, 0x20, 0x2D, 0x3E, 0x20, 0x42, 0x49, 0x4F, 0x53, 0x2E,
+ 0x2E, 0x2E, 0x0D, 0x0A, 0x00
+};
diff --git a/src/rufus.rc b/src/rufus.rc
index 88db8349..dd1946eb 100644
--- a/src/rufus.rc
+++ b/src/rufus.rc
@@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 232, 326
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_ACCEPTFILES
-CAPTION "Rufus 3.5.1472"
+CAPTION "Rufus 3.5.1473"
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
BEGIN
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
@@ -394,8 +394,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 3,5,1472,0
- PRODUCTVERSION 3,5,1472,0
+ FILEVERSION 3,5,1473,0
+ PRODUCTVERSION 3,5,1473,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -413,13 +413,13 @@ BEGIN
VALUE "Comments", "https://akeo.ie"
VALUE "CompanyName", "Akeo Consulting"
VALUE "FileDescription", "Rufus"
- VALUE "FileVersion", "3.5.1472"
+ VALUE "FileVersion", "3.5.1473"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2019 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "https://www.gnu.org/copyleft/gpl.html"
VALUE "OriginalFilename", "rufus-3.5.exe"
VALUE "ProductName", "Rufus"
- VALUE "ProductVersion", "3.5.1472"
+ VALUE "ProductVersion", "3.5.1473"
END
END
BLOCK "VarFileInfo"
diff --git a/src/ui.c b/src/ui.c
index f5b297f8..13bf7b87 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -155,8 +155,10 @@ void GetMainButtonsWidth(HWND hDlg)
MapWindowPoints(NULL, hDlg, (POINT*)&rc, 2);
bw = rc.right - rc.left;
- for (i = 0; i < ARRAYSIZE(main_button_ids); i++)
- bw = max(bw, GetTextWidth(hDlg, main_button_ids[i]) + cbw);
+ for (i = 0; i < ARRAYSIZE(main_button_ids); i++) {
+ // Make sure we add extra space for the SELECT split button (i == 0) if Fido is enabled
+ bw = max(bw, GetTextWidth(hDlg, main_button_ids[i]) + ((enable_fido && i == 0) ? (3 * cbw) / 2 : cbw));
+ }
// The 'CLOSE' button is also be used to display 'CANCEL' and we sometimes
// want to add "DOWNLOAD" into the Select split button => measure that too.
bw = max(bw, GetTextSize(GetDlgItem(hDlg, IDCANCEL), lmprintf(MSG_007)).cx + cbw);