[misc] further Windows version and arch detection improvements

* Now also populate the underlying Windows arch in the version struct
* Also fix MinGW warnings
This commit is contained in:
Pete Batard 2023-04-18 17:21:21 +01:00
parent 4dd40bba2f
commit a6451c6fc7
No known key found for this signature in database
GPG Key ID: 38E0CF5E69EDD671
5 changed files with 127 additions and 108 deletions

View File

@ -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

View File

@ -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");

View File

@ -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);

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 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"

View File

@ -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);
}
}