[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; return short_name;
} }
static __inline BOOL is_WOW64(void)
{
BOOL ret = FALSE;
IsWow64Process(GetCurrentProcess(), &ret);
return ret;
}
// Open an Internet session // Open an Internet session
static HINTERNET GetInternetSession(BOOL bRetry) static HINTERNET GetInternetSession(BOOL bRetry)
{ {
@ -307,9 +314,9 @@ static HINTERNET GetInternetSession(BOOL bRetry)
SetLastError(ERROR_INTERNET_DISCONNECTED); SetLastError(ERROR_INTERNET_DISCONNECTED);
goto out; 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], 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); hSession = pfInternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
// Set the timeouts // Set the timeouts
pfInternetSetOptionA(hSession, INTERNET_OPTION_CONNECT_TIMEOUT, (LPVOID)&dwTimeout, sizeof(dwTimeout)); pfInternetSetOptionA(hSession, INTERNET_OPTION_CONNECT_TIMEOUT, (LPVOID)&dwTimeout, sizeof(dwTimeout));
@ -695,9 +702,9 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
goto out; goto out;
hostname[sizeof(hostname)-1] = 0; 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], 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); hSession = GetInternetSession(FALSE);
if (hSession == NULL) if (hSession == NULL)
goto out; goto out;
@ -763,7 +770,7 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
} }
if (dwStatus != 200) { if (dwStatus != 200) {
vuprintf("Could not find a %s version file on server %s", channel[k], server_url); 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; goto out;
continue; 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)) if ( (!pfHttpQueryInfoA(hRequest, HTTP_QUERY_DATE|HTTP_QUERY_FLAG_SYSTEMTIME, (LPVOID)&ServerTime, &dwSize, NULL))
|| (!SystemTimeToFileTime(&ServerTime, &FileTime)) ) || (!SystemTimeToFileTime(&ServerTime, &FileTime)) )
goto out; 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); vvuprintf("Server time: %" PRId64, server_time);
// Always store the server response time - the only clock we trust! // Always store the server response time - the only clock we trust!
WriteSetting64(SETTING_LAST_UPDATE, server_time); WriteSetting64(SETTING_LAST_UPDATE, server_time);
// Might as well let the user know // Might as well let the user know
if (!force_update_check) { if (!force_update_check) {
if ((local_time > server_time + 600) || (local_time < server_time - 600)) { 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"); (local_time > server_time + 600)?"future":"past");
} }
} }
@ -794,7 +802,7 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
goto out; goto out;
// Make sure the file is NUL terminated // Make sure the file is NUL terminated
buf = (char*)calloc(dwTotalSize+1, 1); buf = (char*)calloc(dwTotalSize + 1, 1);
if (buf == NULL) if (buf == NULL)
goto out; goto out;
// This is a version file - we should be able to gulp it down in one go // 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 #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) static void InitDialog(HWND hDlg)
{ {
DWORD len; DWORD len;
@ -2023,8 +1992,13 @@ static void InitDialog(HWND hDlg)
// Oh, and https://devblogs.microsoft.com/oldnewthing/20220209-00/?p=106239 is *WRONG*: // 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 // 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 // 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)) { 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) && if ((NativeMachine == IMAGE_FILE_MACHINE_ARM || NativeMachine == IMAGE_FILE_MACHINE_ARM64) &&
(ProcessMachine == IMAGE_FILE_MACHINE_I386 || ProcessMachine == IMAGE_FILE_MACHINE_AMD64)) (ProcessMachine == IMAGE_FILE_MACHINE_I386 || ProcessMachine == IMAGE_FILE_MACHINE_AMD64))
uprintf("Notice: Running emulated on %s platform", GetArchName(NativeMachine)); uprintf("Notice: Running emulated on %s platform", GetArchName(NativeMachine));
@ -3354,7 +3328,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
FILE* fd; FILE* fd;
BOOL attached_console = FALSE, external_loc_file = FALSE, lgp_set = FALSE, automount = TRUE; 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 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; BYTE *loc_data;
DWORD loc_size, u = 0, size = sizeof(u); DWORD loc_size, u = 0, size = sizeof(u);
char tmp_path[MAX_PATH] = "", loc_file[MAX_PATH] = "", ini_path[MAX_PATH] = "", ini_flags[] = "rb"; 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); static_strcpy(sysnative_dir, system_dir);
// But if the app is 32 bit and the OS is 64 bit, Sysnative must differ from System32 // But if the app is 32 bit and the OS is 64 bit, Sysnative must differ from System32
#if (!defined(_WIN64) && !defined(BUILD64)) #if (!defined(_WIN64) && !defined(BUILD64))
if (is_x64()) { IsWow64Process(GetCurrentProcess(), &is_WOW64);
if (is_WOW64) {
if (GetSystemWindowsDirectoryU(sysnative_dir, sizeof(sysnative_dir)) == 0) { if (GetSystemWindowsDirectoryU(sysnative_dir, sizeof(sysnative_dir)) == 0) {
uprintf("Could not get Windows directory: %s", WindowsErrorString()); uprintf("Could not get Windows directory: %s", WindowsErrorString());
static_strcpy(sysnative_dir, "C:\\Windows"); static_strcpy(sysnative_dir, "C:\\Windows");

View File

@ -476,6 +476,52 @@ typedef enum TASKBAR_PROGRESS_FLAGS
TASKBAR_PAUSED = 0x8 TASKBAR_PAUSED = 0x8
} TASKBAR_PROGRESS_FLAGS; } 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 */ /* Windows versions */
enum WindowsVersion { enum WindowsVersion {
WINDOWS_UNDEFINED = 0, WINDOWS_UNDEFINED = 0,
@ -491,26 +537,13 @@ enum WindowsVersion {
WINDOWS_MAX = 0xFFFF, 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 { typedef struct {
DWORD Version; DWORD Version;
DWORD Major; DWORD Major;
DWORD Minor; DWORD Minor;
DWORD BuildNumber; DWORD BuildNumber;
DWORD Edition; DWORD Edition;
USHORT Arch;
char VersionStr[128]; char VersionStr[128];
} windows_version_t; } windows_version_t;
@ -564,7 +597,6 @@ extern char app_data_dir[MAX_PATH], *image_path, *fido_url;
* Shared prototypes * Shared prototypes
*/ */
extern void GetWindowsVersion(windows_version_t* WindowsVersion); extern void GetWindowsVersion(windows_version_t* WindowsVersion);
extern BOOL is_x64(void);
extern const char* GetAppArchName(void); extern const char* GetAppArchName(void);
extern const char* WindowsErrorString(void); extern const char* WindowsErrorString(void);
extern void DumpBufferHex(void *buf, size_t size); 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 IDD_DIALOG DIALOGEX 12, 12, 232, 326
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_ACCEPTFILES EXSTYLE WS_EX_ACCEPTFILES
CAPTION "Rufus 3.23.2023" CAPTION "Rufus 3.23.2024"
FONT 9, "Segoe UI Symbol", 400, 0, 0x0 FONT 9, "Segoe UI Symbol", 400, 0, 0x0
BEGIN BEGIN
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
@ -392,8 +392,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,23,2023,0 FILEVERSION 3,23,2024,0
PRODUCTVERSION 3,23,2023,0 PRODUCTVERSION 3,23,2024,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -411,13 +411,13 @@ BEGIN
VALUE "Comments", "https://rufus.ie" VALUE "Comments", "https://rufus.ie"
VALUE "CompanyName", "Akeo Consulting" VALUE "CompanyName", "Akeo Consulting"
VALUE "FileDescription", "Rufus" VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "3.23.2023" VALUE "FileVersion", "3.23.2024"
VALUE "InternalName", "Rufus" VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2023 Pete Batard (GPL v3)" VALUE "LegalCopyright", "© 2011-2023 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
VALUE "OriginalFilename", "rufus-3.23.exe" VALUE "OriginalFilename", "rufus-3.23.exe"
VALUE "ProductName", "Rufus" VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "3.23.2023" VALUE "ProductVersion", "3.23.2024"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -204,22 +204,6 @@ uint32_t htab_hash(char* str, htab_table* htab)
return idx; 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) { const char* GetAppArchName(void) {
#if defined(_M_AMD64) #if defined(_M_AMD64)
return "x64"; return "x64";
@ -230,7 +214,8 @@ const char* GetAppArchName(void) {
#elif defined(_M_ARM) #elif defined(_M_ARM)
return "arm"; return "arm";
#else #else
return "unknown"; // Keep in line with what we were doing in 3.x
return "none";
#endif #endif
} }
@ -336,20 +321,24 @@ static const char* GetEdition(DWORD ProductType)
/* /*
* Modified from smartmontools' os_win32.cpp * Modified from smartmontools' os_win32.cpp
*/ */
void GetWindowsVersion(windows_version_t* WindowsVersion) void GetWindowsVersion(windows_version_t* windows_version)
{ {
OSVERSIONINFOEXA vi, vi2; OSVERSIONINFOEXA vi, vi2;
DWORD dwProductType = 0; DWORD dwProductType = 0;
const char* w = 0; const char* w = NULL;
const char* w64 = "32 bit"; const char* arch_name;
char *vptr; char *vptr;
size_t vlen; size_t vlen;
DWORD major = 0, minor = 0; DWORD major = 0, minor = 0;
USHORT ProcessMachine = IMAGE_FILE_MACHINE_UNKNOWN, NativeMachine = IMAGE_FILE_MACHINE_UNKNOWN;
ULONGLONG major_equal, minor_equal; ULONGLONG major_equal, minor_equal;
BOOL ws; BOOL ws, is_wow64 = FALSE;
memset(WindowsVersion, 0, sizeof(windows_version_t)); PF_TYPE_DECL(WINAPI, BOOL, IsWow64Process2, (HANDLE, USHORT*, USHORT*));
static_strcpy(WindowsVersion->VersionStr, "Windows Undefined"); PF_INIT(IsWow64Process2, Kernel32);
memset(windows_version, 0, sizeof(windows_version_t));
static_strcpy(windows_version->VersionStr, "Windows Undefined");
memset(&vi, 0, sizeof(vi)); memset(&vi, 0, sizeof(vi));
vi.dwOSVersionInfoSize = sizeof(vi); vi.dwOSVersionInfoSize = sizeof(vi);
@ -394,8 +383,8 @@ void GetWindowsVersion(windows_version_t* WindowsVersion)
if (vi.dwMajorVersion <= 0xf && vi.dwMinorVersion <= 0xf) { if (vi.dwMajorVersion <= 0xf && vi.dwMinorVersion <= 0xf) {
ws = (vi.wProductType <= VER_NT_WORKSTATION); ws = (vi.wProductType <= VER_NT_WORKSTATION);
WindowsVersion->Version = vi.dwMajorVersion << 4 | vi.dwMinorVersion; windows_version->Version = vi.dwMajorVersion << 4 | vi.dwMinorVersion;
switch (WindowsVersion->Version) { switch (windows_version->Version) {
case WINDOWS_XP: w = "XP"; case WINDOWS_XP: w = "XP";
break; break;
case WINDOWS_2003: w = (ws ? "XP_64" : (!GetSystemMetrics(89) ? "Server 2003" : "Server 2003_R2")); 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")); w = (ws ? "10" : ((vi.dwBuildNumber < 17763) ? "Server 2016" : "Server 2019"));
break; break;
} }
WindowsVersion->Version = WINDOWS_11; windows_version->Version = WINDOWS_11;
major = 11; major = 11;
// Fall through // Fall through
case WINDOWS_11: w = (ws ? "11" : "Server 2022"); case WINDOWS_11: w = (ws ? "11" : "Server 2022");
break; break;
default: default:
if (WindowsVersion->Version < WINDOWS_XP) if (windows_version->Version < WINDOWS_XP)
WindowsVersion->Version = WINDOWS_UNDEFINED; windows_version->Version = WINDOWS_UNDEFINED;
else else
w = "12 or later"; w = "12 or later";
break; break;
} }
} }
} }
WindowsVersion->Major = major; windows_version->Major = major;
WindowsVersion->Minor = minor; windows_version->Minor = minor;
if (is_x64()) if ((pfIsWow64Process2 != NULL) && pfIsWow64Process2(GetCurrentProcess(), &ProcessMachine, &NativeMachine)) {
w64 = "64-bit"; 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); GetProductInfo(vi.dwMajorVersion, vi.dwMinorVersion, vi.wServicePackMajor, vi.wServicePackMinor, &dwProductType);
vptr = &WindowsVersion->VersionStr[sizeof("Windows ") - 1]; vptr = &windows_version->VersionStr[sizeof("Windows ") - 1];
vlen = sizeof(WindowsVersion->VersionStr) - sizeof("Windows ") - 1; vlen = sizeof(windows_version->VersionStr) - sizeof("Windows ") - 1;
if (!w) if (!w)
safe_sprintf(vptr, vlen, "%s %u.%u %s", (vi.dwPlatformId == VER_PLATFORM_WIN32_NT ? "NT" : "??"), 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) 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) 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 else
safe_sprintf(vptr, vlen, "%s%s%s, %s", safe_sprintf(vptr, vlen, "%s%s%s %s",
w, (dwProductType != 0) ? " " : "", GetEdition(dwProductType), w64); 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 // Add the build number (including UBR if available) for Windows 8.0 and later
WindowsVersion->BuildNumber = vi.dwBuildNumber; windows_version->BuildNumber = vi.dwBuildNumber;
if (WindowsVersion->Version >= WINDOWS_8) { if (windows_version->Version >= WINDOWS_8) {
int nUbr = ReadRegistryKey32(REGKEY_HKLM, "Software\\Microsoft\\Windows NT\\CurrentVersion\\UBR"); int nUbr = ReadRegistryKey32(REGKEY_HKLM, "Software\\Microsoft\\Windows NT\\CurrentVersion\\UBR");
vptr = &WindowsVersion->VersionStr[safe_strlen(WindowsVersion->VersionStr)]; vptr = &windows_version->VersionStr[safe_strlen(windows_version->VersionStr)];
vlen = sizeof(WindowsVersion->VersionStr) - safe_strlen(WindowsVersion->VersionStr) - 1; vlen = sizeof(windows_version->VersionStr) - safe_strlen(windows_version->VersionStr) - 1;
if (nUbr > 0) 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 else
safe_sprintf(vptr, vlen, " (Build %d)", WindowsVersion->BuildNumber); safe_sprintf(vptr, vlen, " (Build %lu)", windows_version->BuildNumber);
} }
} }