[dos] reinstate MS-DOS boot disk creation for Windows 10 and later platforms

* The BlackLotus malware shows that it is possible to download individual
  executables and DLLs straight from Microsoft's symbol servers, so we use
  that capability to download the missing Windows 8.1 'diskcopy.dll', that
  contains the flat floppy disk image with MS-DOS files we need. See:
  https://randomascii.wordpress.com/2013/03/09/symbols-the-microsoft-way/
* Also reorder entries in the "Boot selection" dropdown.
* Also use CreateFileWithTimeout() in GetLogicalName().
This commit is contained in:
Pete Batard 2023-05-24 17:52:25 +01:00
parent 3a0f7d3813
commit 3afa139d7a
No known key found for this signature in database
GPG Key ID: 38E0CF5E69EDD671
8 changed files with 71 additions and 60 deletions

View File

@ -5,6 +5,9 @@ To edit a translation, please make sure to follow:
https://github.com/pbatard/rufus/wiki/Localization#Editing_an_existing_translation
Or simply download https://files.akeo.ie/pollock/pollock-1.5.exe and follow its directions.
o v4.?? (202?.??.??)
- *NEW* MSG_337 "An additional file ('diskcopy.dll') must be downloaded from Microsoft to install MS-DOS (...)"
o v3.22 (2023.??.??)
// MSG_144 is aimed the the ISO download feature
- *UPDATED* MSG_144 "Temporarily banned by Microsoft for requesting too many downloads (...)" -> "Download of Windows ISOs is unavailable due to Microsoft having altered their website to prevent it."

View File

@ -593,6 +593,11 @@ t MSG_333 "Create a local account with username:"
t MSG_334 "Set regional options to the same values as this user's"
t MSG_335 "Disable BitLocker automatic device encryption"
t MSG_336 "Persistent log"
t MSG_337 "An additional file ('diskcopy.dll') must be downloaded from Microsoft to install MS-DOS:\n"
"- Select 'Yes' to connect to the Internet and download it\n"
"- Select 'No' to cancel the operation\n\n"
"Note: The file will be downloaded in the current application directory and will be reused "
"automatically if present."
# 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"

View File

@ -33,6 +33,7 @@
#include "rufus.h"
#include "missing.h"
#include "resource.h"
#include "msapi_utf8.h"
#include "dos.h"
@ -289,8 +290,9 @@ static BOOL ExtractMSDOS(const char* path)
{
int i, j;
BOOL r = FALSE;
HMODULE hDLL = NULL;
uint8_t* diskcopy_buffer = NULL;
char locale_path[MAX_PATH];
char diskcopy_dll_path[MAX_PATH];
char* extractlist[] = { "MSDOS SYS", "COMMAND COM", "IO SYS", "MODE COM",
"KEYB COM", "KEYBOARDSYS", "KEYBRD2 SYS", "KEYBRD3 SYS", "KEYBRD4 SYS",
"DISPLAY SYS", "EGA CPI", "EGA2 CPI", "EGA3 CPI" };
@ -298,28 +300,22 @@ static BOOL ExtractMSDOS(const char* path)
if (path == NULL)
return FALSE;
// There should be a diskcopy.dll in the user's AppData directory.
// Since we're working with a known copy of diskcopy.dll, just load it
// in memory and point to the known disk image resource buffer.
static_sprintf(diskcopy_dll_path, "%s\\%s\\diskcopy.dll", app_data_dir, FILES_DIR);
if (read_file(diskcopy_dll_path, &diskcopy_buffer) != DISKCOPY_SIZE) {
uprintf("'diskcopy.dll' was either not found or is invalid");
goto out;
}
DiskImage = &diskcopy_buffer[DISKCOPY_IMAGE_OFFSET];
DiskImageSize = DISKCOPY_IMAGE_SIZE;
// Reduce the visible mess by placing all the locale files into a subdir
static_strcpy(locale_path, path);
static_strcat(locale_path, "LOCALE\\");
CreateDirectoryA(locale_path, NULL);
hDLL = GetLibraryHandle("diskcopy");
if (hDLL == NULL) {
uprintf("Unable to open 'diskcopy.dll': %s", WindowsErrorString());
goto out;
}
DiskImageSize = 0;
DiskImage = (BYTE*)GetResource(hDLL, MAKEINTRESOURCEA(1), "BINFILE", "disk image", &DiskImageSize, TRUE);
if (DiskImage == NULL)
goto out;
// Sanity check
if (DiskImageSize < 700*KB) {
uprintf("MS-DOS disk image is too small (%d bytes)", DiskImageSize);
goto out;
}
for (i = 0, r = TRUE; r && i < FAT_FN_DIR_ENTRY_LAST; i++) {
if (DiskImage[FAT12_ROOTDIR_OFFSET + i * FAT_BYTES_PER_DIRENT] == FAT_DIRENT_DELETED)
continue;
@ -335,7 +331,7 @@ static BOOL ExtractMSDOS(const char* path)
r = SetDOSLocale(path, FALSE);
out:
safe_free(DiskImage);
safe_free(diskcopy_buffer);
return r;
}

View File

@ -307,8 +307,8 @@ char* GetLogicalName(DWORD DriveIndex, uint64_t PartitionOffset, BOOL bKeepTrail
continue;
}
hDrive = CreateFileA(volume_name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
hDrive = CreateFileWithTimeout(volume_name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL, 3000);
if (hDrive == INVALID_HANDLE_VALUE) {
suprintf("Could not open GUID volume '%s': %s", volume_name, WindowsErrorString());
continue;

View File

@ -273,10 +273,10 @@ static __inline BOOL is_WOW64(void)
}
// Open an Internet session
static HINTERNET GetInternetSession(BOOL bRetry)
static HINTERNET GetInternetSession(const char* user_agent, BOOL bRetry)
{
int i;
char agent[64];
char default_agent[64];
BOOL decodingSupport = TRUE;
VARIANT_BOOL InternetConnection = VARIANT_FALSE;
DWORD dwFlags, dwTimeout = NET_SESSION_TIMEOUT, dwProtocolSupport = HTTP_PROTOCOL_FLAG_HTTP2;
@ -314,10 +314,11 @@ static HINTERNET GetInternetSession(BOOL bRetry)
SetLastError(ERROR_INTERNET_DISCONNECTED);
goto out;
}
static_sprintf(agent, APPLICATION_NAME "/%d.%d.%d (Windows NT %lu.%lu%s)",
static_sprintf(default_agent, APPLICATION_NAME "/%d.%d.%d (Windows NT %lu.%lu%s)",
rufus_version[0], rufus_version[1], rufus_version[2],
WindowsVersion.Major, WindowsVersion.Minor, is_WOW64() ? "; WOW64" : "");
hSession = pfInternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
hSession = pfInternetOpenA((user_agent == NULL) ? default_agent : user_agent,
INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
// Set the timeouts
pfInternetSetOptionA(hSession, INTERNET_OPTION_CONNECT_TIMEOUT, (LPVOID)&dwTimeout, sizeof(dwTimeout));
pfInternetSetOptionA(hSession, INTERNET_OPTION_SEND_TIMEOUT, (LPVOID)&dwTimeout, sizeof(dwTimeout));
@ -341,7 +342,8 @@ out:
* Note that when a buffer is used, the actual size of the buffer is one more than its reported
* size (with the extra byte set to 0) to accommodate for calls that need a NUL-terminated buffer.
*/
uint64_t DownloadToFileOrBuffer(const char* url, const char* file, BYTE** buffer, HWND hProgressDialog, BOOL bTaskBarProgress)
uint64_t DownloadToFileOrBufferEx(const char* url, const char* file, const char* user_agent,
BYTE** buffer, HWND hProgressDialog, BOOL bTaskBarProgress)
{
const char* accept_types[] = {"*/*\0", NULL};
const char* short_name;
@ -395,7 +397,7 @@ uint64_t DownloadToFileOrBuffer(const char* url, const char* file, BYTE** buffer
}
hostname[sizeof(hostname)-1] = 0;
hSession = GetInternetSession(TRUE);
hSession = GetInternetSession(user_agent, TRUE);
if (hSession == NULL) {
uprintf("Could not open Internet session: %s", WinInetErrorString());
goto out;
@ -427,7 +429,7 @@ uint64_t DownloadToFileOrBuffer(const char* url, const char* file, BYTE** buffer
if (DownloadStatus != 200) {
error_code = ERROR_INTERNET_ITEM_NOT_FOUND;
SetLastError(ERROR_SEVERITY_ERROR | FAC(FACILITY_HTTP) | error_code);
uprintf("Unable to access file: %d", DownloadStatus);
uprintf("%s: %d", (DownloadStatus == 404) ? "File not found" : "Unable to access file", DownloadStatus);
goto out;
}
dwSize = sizeof(strsize);
@ -705,7 +707,7 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
static_sprintf(agent, APPLICATION_NAME "/%d.%d.%d (Windows NT %lu.%lu%s)",
rufus_version[0], rufus_version[1], rufus_version[2],
WindowsVersion.Major, WindowsVersion.Minor, is_WOW64() ? "; WOW64" : "");
hSession = GetInternetSession(FALSE);
hSession = GetInternetSession(NULL, FALSE);
if (hSession == NULL)
goto out;
hConnection = pfInternetConnectA(hSession, UrlParts.lpszHostName, UrlParts.nPort,
@ -1125,7 +1127,7 @@ BOOL IsDownloadable(const char* url)
hostname[sizeof(hostname) - 1] = 0;
// Open an Internet session
hSession = GetInternetSession(FALSE);
hSession = GetInternetSession(NULL, FALSE);
if (hSession == NULL)
goto out;

View File

@ -226,12 +226,11 @@ static void SetBootOptions(void)
IGNORE_RETVAL(ComboBox_ResetContent(hBootType));
IGNORE_RETVAL(ComboBox_SetItemData(hBootType, ComboBox_AddStringU(hBootType, lmprintf(MSG_279)), BT_NON_BOOTABLE));
if (WindowsVersion.Version < WINDOWS_10) // The diskcopy.dll along with its MS-DOS floppy image was removed in Windows 10
IGNORE_RETVAL(ComboBox_SetItemData(hBootType, ComboBox_AddStringU(hBootType, "MS-DOS"), BT_MSDOS));
IGNORE_RETVAL(ComboBox_SetItemData(hBootType, ComboBox_AddStringU(hBootType, "FreeDOS"), BT_FREEDOS));
image_index = (WindowsVersion.Version < WINDOWS_10) ? 3 : 2;
IGNORE_RETVAL(ComboBox_SetItemData(hBootType, ComboBox_AddStringU(hBootType,
(image_path == NULL) ? lmprintf(MSG_281, lmprintf(MSG_280)) : short_image_path), BT_IMAGE));
image_index = 1;
IGNORE_RETVAL(ComboBox_SetItemData(hBootType, ComboBox_AddStringU(hBootType, "MS-DOS"), BT_MSDOS));
IGNORE_RETVAL(ComboBox_SetItemData(hBootType, ComboBox_AddStringU(hBootType, "FreeDOS"), BT_FREEDOS));
if (advanced_mode_device) {
static_sprintf(tmp, "Syslinux %s", embedded_sl_version_str[0]);
@ -1824,9 +1823,25 @@ static DWORD WINAPI BootCheckThread(LPVOID param)
} else if (boot_type == BT_MSDOS) {
if ((size_check) && (ComboBox_GetCurItemData(hClusterSize) >= 65536)) {
// MS-DOS cannot boot from a drive using a 64 kilobytes Cluster size
MessageBoxExU(hMainDialog, lmprintf(MSG_110), lmprintf(MSG_111), MB_OK|MB_ICONERROR|MB_IS_RTL, selected_langid);
MessageBoxExU(hMainDialog, lmprintf(MSG_110), lmprintf(MSG_111), MB_OK | MB_ICONERROR | MB_IS_RTL, selected_langid);
goto out;
}
static_sprintf(tmp, "%s\\%s\\diskcopy.dll", app_data_dir, FILES_DIR);
if (_accessU(tmp, 0) != -1) {
uprintf("Will reuse '%s' for MS-DOS installation", tmp);
} else {
r = MessageBoxExU(hMainDialog, lmprintf(MSG_337), lmprintf(MSG_115),
MB_YESNOCANCEL | MB_ICONWARNING | MB_IS_RTL, selected_langid);
if (r != IDYES)
goto out;
IGNORE_RETVAL(_chdirU(app_data_dir));
IGNORE_RETVAL(_mkdir(FILES_DIR));
IGNORE_RETVAL(_chdir(FILES_DIR));
if (DownloadToFileOrBufferEx(DISKCOPY_URL, tmp, DISKCOPY_USER_AGENT, NULL, hMainDialog, FALSE) != DISKCOPY_SIZE) {
ret = BOOTCHECK_DOWNLOAD_ERROR;
goto out;
}
}
} else if (boot_type == BT_GRUB4DOS) {
IGNORE_RETVAL(_chdirU(app_data_dir));
IGNORE_RETVAL(_mkdir(FILES_DIR));
@ -3823,25 +3838,7 @@ extern int TestChecksum(void);
// Ctrl-T => Alternate Test mode that doesn't require a full rebuild
if ((ctrl_without_focus || ((GetKeyState(VK_CONTROL) & 0x8000) && (msg.message == WM_KEYDOWN)))
&& (msg.wParam == 'T')) {
char tmp[256], c;
char label[256] = "2.06-blah-bli-ubutnu.23.2.1-blo";
size_t i;
for (i = strlen(label); i > 0; i--) {
c = label[i];
if (c != 0 && c != '.' && c != '-')
continue;
label[i] = 0;
static_sprintf(tmp, "%s/%s-%s/core.img", FILES_URL, "grub", label);
uprintf(tmp);
label[i] = c;
}
// TestChecksum();
//FILE* fd = fopen("D:\\ISOs\\vol.txt", "r");
//while (fgets(label, 256, fd) != NULL) {
// sanitize_label(label);
// uprintf(label);
//}
//fclose(fd);
TestChecksum();
continue;
}
#endif

View File

@ -120,6 +120,11 @@
#define SECURE_BOOT_MORE_INFO_URL "https://github.com/pbatard/rufus/wiki/FAQ#Why_do_I_need_to_disable_Secure_Boot_to_use_UEFINTFS"
#define WPPRECORDER_MORE_INFO_URL "https://github.com/pbatard/rufus/wiki/FAQ#BSODs_with_Windows_To_Go_drives_created_from_Windows_10_1809_ISOs"
#define SEVENZIP_URL "https://www.7-zip.org"
#define DISKCOPY_URL "https://msdl.microsoft.com/download/symbols/diskcopy.dll/54505118173000/diskcopy.dll"
#define DISKCOPY_USER_AGENT "Microsoft-Symbol-Server/10.0.22621.755"
#define DISKCOPY_SIZE 0x16ee00
#define DISKCOPY_IMAGE_OFFSET 0x66d8
#define DISKCOPY_IMAGE_SIZE 0x168000
#define DEFAULT_ESP_MOUNT_POINT "S:\\"
#define IS_POWER_OF_2(x) ((x != 0) && (((x) & ((x) - 1)) == 0))
#define IGNORE_RETVAL(expr) do { (void)(expr); } while(0)
@ -654,7 +659,10 @@ extern BOOL MountRegistryHive(const HKEY key, const char* pszHiveName, const cha
extern BOOL UnmountRegistryHive(const HKEY key, const char* pszHiveName);
extern BOOL SetLGP(BOOL bRestore, BOOL* bExistingKey, const char* szPath, const char* szPolicy, DWORD dwValue);
extern LONG GetEntryWidth(HWND hDropDown, const char* entry);
extern uint64_t DownloadToFileOrBuffer(const char* url, const char* file, BYTE** buffer, HWND hProgressDialog, BOOL bTaskBarProgress);
extern uint64_t DownloadToFileOrBufferEx(const char* url, const char* file, const char* user_agent,
BYTE** buffer, HWND hProgressDialog, BOOL bTaskBarProgress);
#define DownloadToFileOrBuffer(url, file, buffer, hProgressDialog, bTaskBarProgress) \
DownloadToFileOrBufferEx(url, file, NULL, buffer, hProgressDialog, bTaskBarProgress)
extern DWORD DownloadSignedFile(const char* url, const char* file, HWND hProgressDialog, BOOL PromptOnError);
extern HANDLE DownloadSignedFileThreaded(const char* url, const char* file, HWND hProgressDialog, BOOL bPromptOnError);
extern INT_PTR CALLBACK UpdateCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);

View File

@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 232, 326
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_ACCEPTFILES
CAPTION "Rufus 4.0.2039"
CAPTION "Rufus 4.0.2040"
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
BEGIN
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
@ -392,8 +392,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,0,2039,0
PRODUCTVERSION 4,0,2039,0
FILEVERSION 4,0,2040,0
PRODUCTVERSION 4,0,2040,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -411,13 +411,13 @@ BEGIN
VALUE "Comments", "https://rufus.ie"
VALUE "CompanyName", "Akeo Consulting"
VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "4.0.2039"
VALUE "FileVersion", "4.0.2040"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2023 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
VALUE "OriginalFilename", "rufus-4.0.exe"
VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "4.0.2039"
VALUE "ProductVersion", "4.0.2040"
END
END
BLOCK "VarFileInfo"