diff --git a/res/loc/ChangeLog.txt b/res/loc/ChangeLog.txt index c5903005..77f2d980 100644 --- a/res/loc/ChangeLog.txt +++ b/res/loc/ChangeLog.txt @@ -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." diff --git a/res/loc/rufus.loc b/res/loc/rufus.loc index 07008191..cca0f0b4 100644 --- a/res/loc/rufus.loc +++ b/res/loc/rufus.loc @@ -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" diff --git a/src/dos.c b/src/dos.c index 6ffb426c..c5a228ec 100644 --- a/src/dos.c +++ b/src/dos.c @@ -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; } diff --git a/src/drive.c b/src/drive.c index 25067af4..13d21d96 100644 --- a/src/drive.c +++ b/src/drive.c @@ -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; diff --git a/src/net.c b/src/net.c index 1be933ca..e4c64bc7 100644 --- a/src/net.c +++ b/src/net.c @@ -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; diff --git a/src/rufus.c b/src/rufus.c index 8e900dc1..b27cef68 100755 --- a/src/rufus.c +++ b/src/rufus.c @@ -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 diff --git a/src/rufus.h b/src/rufus.h index 05209daf..e56b5165 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -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); diff --git a/src/rufus.rc b/src/rufus.rc index 699cbe40..efe4cebc 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 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"