From a6451c6fc7f45bf17dc783ce5f9e4b4919bad6fc Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Tue, 18 Apr 2023 17:21:21 +0100 Subject: [PATCH] [misc] further Windows version and arch detection improvements * Now also populate the underlying Windows arch in the version struct * Also fix MinGW warnings --- src/net.c | 24 ++++++++----- src/rufus.c | 43 +++++------------------ src/rufus.h | 62 +++++++++++++++++++++++++-------- src/rufus.rc | 10 +++--- src/stdfn.c | 96 +++++++++++++++++++++++++++------------------------- 5 files changed, 127 insertions(+), 108 deletions(-) diff --git a/src/net.c b/src/net.c index e216d65e..bb903ac8 100644 --- a/src/net.c +++ b/src/net.c @@ -265,6 +265,13 @@ static char* GetShortName(const char* url) return short_name; } +static __inline BOOL is_WOW64(void) +{ + BOOL ret = FALSE; + IsWow64Process(GetCurrentProcess(), &ret); + return ret; +} + // Open an Internet session static HINTERNET GetInternetSession(BOOL bRetry) { @@ -307,9 +314,9 @@ static HINTERNET GetInternetSession(BOOL bRetry) SetLastError(ERROR_INTERNET_DISCONNECTED); 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 %lu.%lu%s)", rufus_version[0], rufus_version[1], rufus_version[2], - WindowsVersion.Major, WindowsVersion.Minor, is_x64() ? "; WOW64" : ""); + WindowsVersion.Major, WindowsVersion.Minor, is_WOW64() ? "; WOW64" : ""); hSession = pfInternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); // Set the timeouts pfInternetSetOptionA(hSession, INTERNET_OPTION_CONNECT_TIMEOUT, (LPVOID)&dwTimeout, sizeof(dwTimeout)); @@ -695,9 +702,9 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) goto out; hostname[sizeof(hostname)-1] = 0; - static_sprintf(agent, APPLICATION_NAME "/%d.%d.%d (Windows NT %d.%d%s)", + 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_x64() ? "; WOW64" : ""); + WindowsVersion.Major, WindowsVersion.Minor, is_WOW64() ? "; WOW64" : ""); hSession = GetInternetSession(FALSE); if (hSession == NULL) goto out; @@ -763,7 +770,7 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) } if (dwStatus != 200) { vuprintf("Could not find a %s version file on server %s", channel[k], server_url); - if ((releases_only) || (k+1 >= ARRAYSIZE(channel))) + if ((releases_only) || (k + 1 >= ARRAYSIZE(channel))) goto out; continue; } @@ -777,14 +784,15 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) if ( (!pfHttpQueryInfoA(hRequest, HTTP_QUERY_DATE|HTTP_QUERY_FLAG_SYSTEMTIME, (LPVOID)&ServerTime, &dwSize, NULL)) || (!SystemTimeToFileTime(&ServerTime, &FileTime)) ) 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, server_time); // Always store the server response time - the only clock we trust! WriteSetting64(SETTING_LAST_UPDATE, server_time); // Might as well let the user know if (!force_update_check) { if ((local_time > server_time + 600) || (local_time < server_time - 600)) { - uprintf("IMPORTANT: Your local clock is more than 10 minutes in the %s. Unless you fix this, " APPLICATION_NAME " may not be able to check for updates...", + uprintf("IMPORTANT: Your local clock is more than 10 minutes in the %s. Unless you fix this, " + APPLICATION_NAME " may not be able to check for updates...", (local_time > server_time + 600)?"future":"past"); } } @@ -794,7 +802,7 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) goto out; // Make sure the file is NUL terminated - buf = (char*)calloc(dwTotalSize+1, 1); + buf = (char*)calloc(dwTotalSize + 1, 1); if (buf == NULL) goto out; // This is a version file - we should be able to gulp it down in one go diff --git a/src/rufus.c b/src/rufus.c index 0733a062..0942bf71 100755 --- a/src/rufus.c +++ b/src/rufus.c @@ -1891,37 +1891,6 @@ static __inline const char* IsAlphaOrBeta(void) #endif } -static __inline DWORD GetApplicationArch(void) -{ -#if defined(_M_AMD64) - return IMAGE_FILE_MACHINE_AMD64; -#elif defined(_M_IX86) - return IMAGE_FILE_MACHINE_I386; -#elif defined(_M_ARM64) - return IMAGE_FILE_MACHINE_ARM64; -#elif defined(_M_ARM) - return IMAGE_FILE_MACHINE_ARM; -#else - return IMAGE_FILE_MACHINE_UNKNOWN; -#endif -} - -static const char* GetArchName(USHORT uArch) -{ - switch (uArch) { - case IMAGE_FILE_MACHINE_AMD64: - return "x64"; - case IMAGE_FILE_MACHINE_I386: - return "x86"; - case IMAGE_FILE_MACHINE_ARM64: - return "Arm64"; - case IMAGE_FILE_MACHINE_ARM: - return "Arm"; - default: - return "(Unknown Arch)"; - } -} - static void InitDialog(HWND hDlg) { DWORD len; @@ -2023,8 +1992,13 @@ static void InitDialog(HWND hDlg) // Oh, and https://devblogs.microsoft.com/oldnewthing/20220209-00/?p=106239 is *WRONG*: // Get­Native­System­Info() will not tell you what the native system architecture is when // running x86 code on ARM64. Instead you have to use IsWow64Process2(), which is only - // available on Windows 10 1511 or later... + // available on Windows 10 1709 or later... if ((pfIsWow64Process2 != NULL) && pfIsWow64Process2(GetCurrentProcess(), &ProcessMachine, &NativeMachine)) { + // x64 running emulated on ARM64 returns IMAGE_FILE_MACHINE_UNKNOWN for ProcessMachine + // because Microsoft does not consider it a WOW64 process. So we need to fix + // ProcessMachine ourselves to *ACTUALLY* return the bloody process machine... + if (ProcessMachine == IMAGE_FILE_MACHINE_UNKNOWN) + ProcessMachine = GetApplicationArch(); if ((NativeMachine == IMAGE_FILE_MACHINE_ARM || NativeMachine == IMAGE_FILE_MACHINE_ARM64) && (ProcessMachine == IMAGE_FILE_MACHINE_I386 || ProcessMachine == IMAGE_FILE_MACHINE_AMD64)) uprintf("Notice: Running emulated on %s platform", GetArchName(NativeMachine)); @@ -3354,7 +3328,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine FILE* fd; BOOL attached_console = FALSE, external_loc_file = FALSE, lgp_set = FALSE, automount = TRUE; BOOL disable_hogger = FALSE, previous_enable_HDDs = FALSE, vc = IsRegistryNode(REGKEY_HKCU, vs_reg); - BOOL alt_pressed = FALSE, alt_command = FALSE; + BOOL alt_pressed = FALSE, alt_command = FALSE, is_WOW64 = FALSE; BYTE *loc_data; DWORD loc_size, u = 0, size = sizeof(u); char tmp_path[MAX_PATH] = "", loc_file[MAX_PATH] = "", ini_path[MAX_PATH] = "", ini_flags[] = "rb"; @@ -3440,7 +3414,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine static_strcpy(sysnative_dir, system_dir); // But if the app is 32 bit and the OS is 64 bit, Sysnative must differ from System32 #if (!defined(_WIN64) && !defined(BUILD64)) - if (is_x64()) { + IsWow64Process(GetCurrentProcess(), &is_WOW64); + if (is_WOW64) { if (GetSystemWindowsDirectoryU(sysnative_dir, sizeof(sysnative_dir)) == 0) { uprintf("Could not get Windows directory: %s", WindowsErrorString()); static_strcpy(sysnative_dir, "C:\\Windows"); diff --git a/src/rufus.h b/src/rufus.h index 679ca217..fa8455a9 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -476,6 +476,52 @@ typedef enum TASKBAR_PROGRESS_FLAGS TASKBAR_PAUSED = 0x8 } TASKBAR_PROGRESS_FLAGS; +/* We can't use the Microsoft enums as we want to have RISC-V */ +enum ArchType { + ARCH_UNKNOWN = 0, + ARCH_X86_32, + ARCH_X86_64, + ARCH_ARM_32, + ARCH_ARM_64, + ARCH_IA_64, + ARCH_RISCV_32, + ARCH_RISCV_64, + ARCH_RISCV_128, + ARCH_EBC, + ARCH_MAX +}; + +static __inline USHORT GetApplicationArch(void) +{ +#if defined(_M_AMD64) + return IMAGE_FILE_MACHINE_AMD64; +#elif defined(_M_IX86) + return IMAGE_FILE_MACHINE_I386; +#elif defined(_M_ARM64) + return IMAGE_FILE_MACHINE_ARM64; +#elif defined(_M_ARM) + return IMAGE_FILE_MACHINE_ARM; +#else + return IMAGE_FILE_MACHINE_UNKNOWN; +#endif +} + +static __inline const char* GetArchName(USHORT uArch) +{ + switch (uArch) { + case IMAGE_FILE_MACHINE_AMD64: + return "x64"; + case IMAGE_FILE_MACHINE_I386: + return "x86"; + case IMAGE_FILE_MACHINE_ARM64: + return "Arm64"; + case IMAGE_FILE_MACHINE_ARM: + return "Arm"; + default: + return "(Unknown Arch)"; + } +} + /* Windows versions */ enum WindowsVersion { WINDOWS_UNDEFINED = 0, @@ -491,26 +537,13 @@ enum WindowsVersion { WINDOWS_MAX = 0xFFFF, }; -enum ArchType { - ARCH_UNKNOWN = 0, - ARCH_X86_32, - ARCH_X86_64, - ARCH_ARM_32, - ARCH_ARM_64, - ARCH_IA_64, - ARCH_RISCV_32, - ARCH_RISCV_64, - ARCH_RISCV_128, - ARCH_EBC, - ARCH_MAX -}; - typedef struct { DWORD Version; DWORD Major; DWORD Minor; DWORD BuildNumber; DWORD Edition; + USHORT Arch; char VersionStr[128]; } windows_version_t; @@ -564,7 +597,6 @@ extern char app_data_dir[MAX_PATH], *image_path, *fido_url; * Shared prototypes */ extern void GetWindowsVersion(windows_version_t* WindowsVersion); -extern BOOL is_x64(void); extern const char* GetAppArchName(void); extern const char* WindowsErrorString(void); extern void DumpBufferHex(void *buf, size_t size); diff --git a/src/rufus.rc b/src/rufus.rc index d41bcf6e..234ce82c 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.23.2023" +CAPTION "Rufus 3.23.2024" 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 3,23,2023,0 - PRODUCTVERSION 3,23,2023,0 + FILEVERSION 3,23,2024,0 + PRODUCTVERSION 3,23,2024,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", "3.23.2023" + VALUE "FileVersion", "3.23.2024" 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-3.23.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "3.23.2023" + VALUE "ProductVersion", "3.23.2024" END END BLOCK "VarFileInfo" diff --git a/src/stdfn.c b/src/stdfn.c index 6fff4602..96a8b239 100644 --- a/src/stdfn.c +++ b/src/stdfn.c @@ -204,22 +204,6 @@ uint32_t htab_hash(char* str, htab_table* htab) return idx; } -BOOL is_x64(void) -{ - BOOL ret = FALSE; - PF_TYPE_DECL(WINAPI, BOOL, IsWow64Process, (HANDLE, PBOOL)); - // Detect if we're running a 32 or 64 bit system - if (sizeof(uintptr_t) < 8) { - PF_INIT(IsWow64Process, Kernel32); - if (pfIsWow64Process != NULL) { - (*pfIsWow64Process)(GetCurrentProcess(), &ret); - } - } else { - ret = TRUE; - } - return ret; -} - const char* GetAppArchName(void) { #if defined(_M_AMD64) return "x64"; @@ -230,7 +214,8 @@ const char* GetAppArchName(void) { #elif defined(_M_ARM) return "arm"; #else - return "unknown"; + // Keep in line with what we were doing in 3.x + return "none"; #endif } @@ -336,20 +321,24 @@ static const char* GetEdition(DWORD ProductType) /* * Modified from smartmontools' os_win32.cpp */ -void GetWindowsVersion(windows_version_t* WindowsVersion) +void GetWindowsVersion(windows_version_t* windows_version) { OSVERSIONINFOEXA vi, vi2; DWORD dwProductType = 0; - const char* w = 0; - const char* w64 = "32 bit"; + const char* w = NULL; + const char* arch_name; char *vptr; size_t vlen; DWORD major = 0, minor = 0; + USHORT ProcessMachine = IMAGE_FILE_MACHINE_UNKNOWN, NativeMachine = IMAGE_FILE_MACHINE_UNKNOWN; ULONGLONG major_equal, minor_equal; - BOOL ws; + BOOL ws, is_wow64 = FALSE; - memset(WindowsVersion, 0, sizeof(windows_version_t)); - static_strcpy(WindowsVersion->VersionStr, "Windows Undefined"); + PF_TYPE_DECL(WINAPI, BOOL, IsWow64Process2, (HANDLE, USHORT*, USHORT*)); + PF_INIT(IsWow64Process2, Kernel32); + + memset(windows_version, 0, sizeof(windows_version_t)); + static_strcpy(windows_version->VersionStr, "Windows Undefined"); memset(&vi, 0, sizeof(vi)); vi.dwOSVersionInfoSize = sizeof(vi); @@ -394,8 +383,8 @@ void GetWindowsVersion(windows_version_t* WindowsVersion) if (vi.dwMajorVersion <= 0xf && vi.dwMinorVersion <= 0xf) { ws = (vi.wProductType <= VER_NT_WORKSTATION); - WindowsVersion->Version = vi.dwMajorVersion << 4 | vi.dwMinorVersion; - switch (WindowsVersion->Version) { + windows_version->Version = vi.dwMajorVersion << 4 | vi.dwMinorVersion; + switch (windows_version->Version) { case WINDOWS_XP: w = "XP"; break; case WINDOWS_2003: w = (ws ? "XP_64" : (!GetSystemMetrics(89) ? "Server 2003" : "Server 2003_R2")); @@ -416,52 +405,67 @@ void GetWindowsVersion(windows_version_t* WindowsVersion) w = (ws ? "10" : ((vi.dwBuildNumber < 17763) ? "Server 2016" : "Server 2019")); break; } - WindowsVersion->Version = WINDOWS_11; + windows_version->Version = WINDOWS_11; major = 11; // Fall through case WINDOWS_11: w = (ws ? "11" : "Server 2022"); break; default: - if (WindowsVersion->Version < WINDOWS_XP) - WindowsVersion->Version = WINDOWS_UNDEFINED; + if (windows_version->Version < WINDOWS_XP) + windows_version->Version = WINDOWS_UNDEFINED; else w = "12 or later"; break; } } } - WindowsVersion->Major = major; - WindowsVersion->Minor = minor; + windows_version->Major = major; + windows_version->Minor = minor; - if (is_x64()) - w64 = "64-bit"; + if ((pfIsWow64Process2 != NULL) && pfIsWow64Process2(GetCurrentProcess(), &ProcessMachine, &NativeMachine)) { + windows_version->Arch = NativeMachine; + } else { + // Assume same arch as the app + windows_version->Arch = GetApplicationArch(); + // Fix the Arch if we have a 32-bit app running under WOW64 + if ((sizeof(uintptr_t) < 8) && IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64) { + if (windows_version->Arch == IMAGE_FILE_MACHINE_I386) + windows_version->Arch = IMAGE_FILE_MACHINE_AMD64; + else if (windows_version->Arch == IMAGE_FILE_MACHINE_ARM) + windows_version->Arch = IMAGE_FILE_MACHINE_ARM64; + else // I sure wanna be made aware of this scenario... + assert(FALSE); + } + uprintf("Note: Underlying Windows architecture was guessed and may be incorrect..."); + } + arch_name = GetArchName(windows_version->Arch); GetProductInfo(vi.dwMajorVersion, vi.dwMinorVersion, vi.wServicePackMajor, vi.wServicePackMinor, &dwProductType); - vptr = &WindowsVersion->VersionStr[sizeof("Windows ") - 1]; - vlen = sizeof(WindowsVersion->VersionStr) - sizeof("Windows ") - 1; + vptr = &windows_version->VersionStr[sizeof("Windows ") - 1]; + vlen = sizeof(windows_version->VersionStr) - sizeof("Windows ") - 1; if (!w) safe_sprintf(vptr, vlen, "%s %u.%u %s", (vi.dwPlatformId == VER_PLATFORM_WIN32_NT ? "NT" : "??"), - (unsigned)vi.dwMajorVersion, (unsigned)vi.dwMinorVersion, w64); + (unsigned)vi.dwMajorVersion, (unsigned)vi.dwMinorVersion, arch_name); else if (vi.wServicePackMinor) - safe_sprintf(vptr, vlen, "%s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, w64); + safe_sprintf(vptr, vlen, "%s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, arch_name); else if (vi.wServicePackMajor) - safe_sprintf(vptr, vlen, "%s SP%u %s", w, vi.wServicePackMajor, w64); + safe_sprintf(vptr, vlen, "%s SP%u %s", w, vi.wServicePackMajor, arch_name); else - safe_sprintf(vptr, vlen, "%s%s%s, %s", - w, (dwProductType != 0) ? " " : "", GetEdition(dwProductType), w64); + safe_sprintf(vptr, vlen, "%s%s%s %s", + w, (dwProductType != 0) ? " " : "", GetEdition(dwProductType), arch_name); - WindowsVersion->Edition = (int)dwProductType; + windows_version->Edition = (int)dwProductType; // Add the build number (including UBR if available) for Windows 8.0 and later - WindowsVersion->BuildNumber = vi.dwBuildNumber; - if (WindowsVersion->Version >= WINDOWS_8) { + windows_version->BuildNumber = vi.dwBuildNumber; + if (windows_version->Version >= WINDOWS_8) { int nUbr = ReadRegistryKey32(REGKEY_HKLM, "Software\\Microsoft\\Windows NT\\CurrentVersion\\UBR"); - vptr = &WindowsVersion->VersionStr[safe_strlen(WindowsVersion->VersionStr)]; - vlen = sizeof(WindowsVersion->VersionStr) - safe_strlen(WindowsVersion->VersionStr) - 1; + vptr = &windows_version->VersionStr[safe_strlen(windows_version->VersionStr)]; + vlen = sizeof(windows_version->VersionStr) - safe_strlen(windows_version->VersionStr) - 1; if (nUbr > 0) - safe_sprintf(vptr, vlen, " (Build %d.%d)", WindowsVersion->BuildNumber, nUbr); + safe_sprintf(vptr, vlen, " (Build %lu.%d)", windows_version->BuildNumber, nUbr); else - safe_sprintf(vptr, vlen, " (Build %d)", WindowsVersion->BuildNumber); + safe_sprintf(vptr, vlen, " (Build %lu)", windows_version->BuildNumber); } }