502 lines
14 KiB
C++
502 lines
14 KiB
C++
#include "utils.h"
|
|
|
|
#include <cmath>
|
|
|
|
std::string AppVer;
|
|
|
|
float WinVer;
|
|
|
|
namespace {
|
|
static bool is_win11;
|
|
|
|
static ULONG NT_MAJOR = 0;
|
|
|
|
static ULONG NT_MINOR = 0;
|
|
|
|
static ULONG NT_BUILD = 0;
|
|
|
|
static std::wstring NT_CSD_VERSION;
|
|
|
|
static std::string NT_SERVICE_PACK;
|
|
|
|
static USHORT NT_SUITE;
|
|
|
|
static UCHAR NT_TYPE;
|
|
}
|
|
|
|
HANDLE LoadImageFromDLL(LPCWSTR dllName,
|
|
UINT resourceId,
|
|
UINT imgType,
|
|
int width,
|
|
int height,
|
|
UINT flags) {
|
|
// Load the .dll module from supplied name
|
|
HMODULE hModule = LoadLibraryW(dllName);
|
|
if (!hModule) {
|
|
return nullptr;
|
|
}
|
|
|
|
// Load the image using LoadImageW
|
|
HANDLE hImage;
|
|
hImage = LoadImageW(
|
|
hModule, // hinst
|
|
MAKEINTRESOURCEW(resourceId), // resource name/id
|
|
imgType,
|
|
width,
|
|
height,
|
|
flags);
|
|
|
|
// We can free the module after loading unless caller wants otherwise
|
|
if (hImage) {
|
|
FreeLibrary(hModule);
|
|
}
|
|
|
|
return hImage;
|
|
}
|
|
|
|
HICON getDialogIcon(bool use_custom_icon, int resource, int x, int y) {
|
|
HICON icon;
|
|
// Get key icon
|
|
static const LPCWSTR dll_name = L"shell32.dll";
|
|
if (use_custom_icon) {
|
|
icon = (HICON)LoadImageFromDLL(
|
|
dll_name,
|
|
resource,
|
|
IMAGE_ICON,
|
|
x,
|
|
y,
|
|
LR_DEFAULTCOLOR);
|
|
} else {
|
|
icon = (HICON)LoadImage(
|
|
GetModuleHandle(NULL),
|
|
MAKEINTRESOURCE(IDI_SMALL), // Our normal telephone icon
|
|
IMAGE_ICON,
|
|
x,
|
|
y,
|
|
LR_DEFAULTCOLOR);
|
|
}
|
|
return icon;
|
|
}
|
|
|
|
std::string getVersionA() {
|
|
std::ostringstream ostr;
|
|
ostr << MAJOR_VERSION << "." << MINOR_VERSION << "." << BUILD_VERSION;
|
|
const std::string retval = ostr.str();
|
|
AppVer = retval;
|
|
return retval;
|
|
}
|
|
|
|
std::wstring getVersionW() {
|
|
const std::wstring retval = stringToWstring(getVersionA());
|
|
return retval;
|
|
}
|
|
|
|
float concatToFloat(int major, int minor) {
|
|
// Count digits of the fractional part
|
|
int digits = (minor == 0) ? 1 : std::to_string(minor).size();
|
|
|
|
// Build the float: whole + fractional / (10^digits)
|
|
const float retval = major + minor / std::pow(10.0f, digits);
|
|
return retval;
|
|
}
|
|
|
|
bool getWinNTVersion() {
|
|
bool success = false;
|
|
// Use RtlGetVersion from winnt.h, not wdm.h
|
|
NTSTATUS(WINAPI *RtlGetVersion)(LPOSVERSIONINFOEXW);
|
|
// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-osversioninfoexw
|
|
OSVERSIONINFOEXW osInfo;
|
|
|
|
// Make sure we get the dll
|
|
HMODULE NtDllModule = GetModuleHandleW(L"ntdll");
|
|
|
|
// Get and run ntdll.dll function pointer to RtlGetVersion()
|
|
if (NtDllModule && NtDllModule != nullptr) {
|
|
*reinterpret_cast<FARPROC*>(&RtlGetVersion) =
|
|
GetProcAddress(NtDllModule, "RtlGetVersion");
|
|
} else {
|
|
RtlGetVersion = nullptr;
|
|
success = false;
|
|
}
|
|
|
|
// Should never be null
|
|
if (RtlGetVersion != nullptr) {
|
|
osInfo.dwOSVersionInfoSize = sizeof osInfo;
|
|
RtlGetVersion(&osInfo);
|
|
NT_MAJOR = osInfo.dwMajorVersion;
|
|
NT_MINOR = osInfo.dwMinorVersion;
|
|
NT_BUILD = osInfo.dwBuildNumber;
|
|
NT_CSD_VERSION = osInfo.szCSDVersion;
|
|
NT_SUITE = osInfo.wSuiteMask;
|
|
NT_TYPE = osInfo.wProductType;
|
|
success = true;
|
|
} else {
|
|
MessageBoxW(g_hMainDlg, strings[IDS_GETVER_ERR], strings[IDS_ERROR], MB_ICONSTOP);
|
|
}
|
|
|
|
const int major = static_cast<int>(NT_MAJOR);
|
|
const int minor = static_cast<int>(NT_MINOR);
|
|
// Set our extern WinVer
|
|
WinVer = concatToFloat(major, minor);
|
|
|
|
return success;
|
|
}
|
|
|
|
// Use WINNT API functions to get OS and system information
|
|
std::string const GetOSNameA() {
|
|
// Human readable OS name
|
|
std::string OsVer;
|
|
// For obscure versions or pre NT4 SP6
|
|
std::ostringstream debugStream;
|
|
|
|
const bool gotNTVersion = getWinNTVersion();
|
|
if (!gotNTVersion) {
|
|
return std::string();
|
|
}
|
|
|
|
// Get the service pack
|
|
std::string NT_SERVICE_PACK(NT_CSD_VERSION.begin(),
|
|
NT_CSD_VERSION.end());
|
|
|
|
|
|
if (NT_MAJOR <= 3) {
|
|
NT_FEATURE_VERSION = NT_SERVICE_PACK;
|
|
NT_POST_STRING = NT_FEATURE_VERSION;
|
|
}
|
|
if (NT_MAJOR == 4) {
|
|
if (NT_BUILD < 1381) {
|
|
if (NT_SUITE == VER_SUITE_TERMINAL) {
|
|
NT_FEATURE_VERSION = " Beta Cairo Build";
|
|
} else {
|
|
NT_FEATURE_VERSION = " Beta Hydra Build";
|
|
}
|
|
} else {
|
|
if (NT_SUITE == VER_SUITE_TERMINAL) {
|
|
NT_FEATURE_VERSION = " Terminal Server";
|
|
}
|
|
}
|
|
} else if (NT_MAJOR == 5) {
|
|
switch (NT_MINOR) {
|
|
case 0:
|
|
if (NT_BUILD > 1386 && NT_BUILD < 2195) {
|
|
NT_FEATURE_VERSION = " Beta Win2K Build";
|
|
}
|
|
break;
|
|
case 1:
|
|
if (NT_BUILD > 2196 && NT_BUILD < 2600) {
|
|
NT_FEATURE_VERSION = " Beta Whistler Build";
|
|
}
|
|
if (NT_BUILD == 2700) {
|
|
NT_FEATURE_VERSION = " MCE 2005";
|
|
}
|
|
if (NT_BUILD == 2710) {
|
|
NT_FEATURE_VERSION = " MCE 2005 Update Rollup 2";
|
|
}
|
|
break;
|
|
case 2:
|
|
if (NT_BUILD > 2228 && NT_BUILD < 3790) {
|
|
NT_FEATURE_VERSION = " Beta Whistler Build";
|
|
}
|
|
if (NT_SUITE == VER_SUITE_WH_SERVER) {
|
|
if (NT_BUILD > 1282 && NT_BUILD < 3790) {
|
|
NT_FEATURE_VERSION = " Beta Quattro Build";
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
NT_FEATURE_VERSION = "";
|
|
break;
|
|
}
|
|
} else if (NT_MAJOR == 6) {
|
|
switch (NT_MINOR) {
|
|
case 0:
|
|
if (NT_BUILD > 3663 && NT_BUILD < 6000) {
|
|
NT_FEATURE_VERSION = " Beta Longhorn Build";
|
|
} else if (NT_BUILD == 6003) {
|
|
NT_FEATURE_VERSION = " KB4489887";
|
|
}
|
|
break;
|
|
case 1:
|
|
if (NT_BUILD > 6429 && NT_BUILD < 7600) {
|
|
NT_FEATURE_VERSION = " Beta Win7 Build";
|
|
}
|
|
break;
|
|
case 2:
|
|
if (NT_BUILD > 7652 && NT_BUILD < 9200) {
|
|
NT_FEATURE_VERSION = " Beta Win8 Build";
|
|
}
|
|
break;
|
|
case 3:
|
|
if (NT_BUILD > 9255 && NT_BUILD < 9600) {
|
|
NT_FEATURE_VERSION = " Beta Blue Build";
|
|
}
|
|
break;
|
|
default:
|
|
NT_FEATURE_VERSION = "";
|
|
break;
|
|
}
|
|
NT_POST_STRING = NT_SERVICE_PACK + NT_FEATURE_VERSION;
|
|
// No such thing as feature releases for Windows 8.1 and below
|
|
} else if (NT_MAJOR >= 10) {
|
|
if (NT_BUILD > 19045) {
|
|
is_win11 = true;
|
|
} else {
|
|
is_win11 = false;
|
|
}
|
|
|
|
if (NT_BUILD < 10240) {
|
|
NT_FEATURE_VERSION = "Beta Threshold Build ";
|
|
} else if (NT_BUILD == 10240) {
|
|
NT_FEATURE_VERSION = "1507 (RTM 2015 Release) ";
|
|
} else if (NT_BUILD == 10586) {
|
|
NT_FEATURE_VERSION = "1511 (Nov. 2015 Update) ";
|
|
} else if (NT_BUILD == 14393) {
|
|
NT_FEATURE_VERSION = "1607 (Anniversary Update) ";
|
|
} else if (NT_BUILD == 15063) {
|
|
NT_FEATURE_VERSION = "1703 (Creators Update) ";
|
|
} else if (NT_BUILD == 16299) {
|
|
NT_FEATURE_VERSION = "1709 (Fall Creators Update) ";
|
|
} else if (NT_BUILD == 17134) {
|
|
NT_FEATURE_VERSION = "1803 (Apr. 2018 Update) ";
|
|
} else if (NT_BUILD == 17763) {
|
|
NT_FEATURE_VERSION = "1809 (Oct. 2018 Update) ";
|
|
} else if (NT_BUILD == 18362) {
|
|
NT_FEATURE_VERSION = "1903 (May. 2019 Update) ";
|
|
} else if (NT_BUILD == 18363) {
|
|
NT_FEATURE_VERSION = "1909 (Nov. 2019 Update) ";
|
|
} else if (NT_BUILD == 19041) {
|
|
NT_FEATURE_VERSION = "2004 (May. 2020 Update) ";
|
|
} else if (NT_BUILD == 19042) {
|
|
NT_FEATURE_VERSION = "20H2 (Oct. 2020 Update) ";
|
|
} else if (NT_BUILD == 19043) {
|
|
NT_FEATURE_VERSION = "21H1 (May. 2021 Update) ";
|
|
} else if (NT_BUILD == 19044) {
|
|
NT_FEATURE_VERSION = "21H2 (Nov. 2021 Update) ";
|
|
} else if (NT_BUILD == 19045) {
|
|
NT_FEATURE_VERSION = "22H2 (Oct. 2022 Update) ";
|
|
} else if (NT_BUILD == 20348 || NT_BUILD == 25398) {
|
|
NT_FEATURE_VERSION = "Server 2022 ";
|
|
} else if (NT_BUILD < 22000 && NT_BUILD > 20348 && NT_BUILD != 25398) {
|
|
NT_FEATURE_VERSION = "Beta Build ";
|
|
} else if (NT_BUILD == 22000) {
|
|
NT_FEATURE_VERSION = "21H2 (RTM 2021 Release) ";
|
|
} else if (NT_BUILD == 22621) {
|
|
NT_FEATURE_VERSION = "22H2 (Sep. 2022 Update) ";
|
|
} else if (NT_BUILD == 22631) {
|
|
NT_FEATURE_VERSION = "23H2 (Oct. 2023 Update) ";
|
|
} else if (NT_BUILD == 26100) {
|
|
NT_FEATURE_VERSION = "24H2 (Oct. 2024 Update) ";
|
|
} else {
|
|
NOTREACHED();
|
|
}
|
|
}
|
|
NT_POST_STRING = NT_SERVICE_PACK + NT_FEATURE_VERSION;
|
|
|
|
|
|
if (NT_MAJOR == 3) {
|
|
OsVer = "Windows NT 3.x";
|
|
} else if (NT_MAJOR == 4) {
|
|
// Known to be buggy on NT 4.0, and needs SP6 to work
|
|
switch (NT_MINOR) {
|
|
case 0:
|
|
OsVer = "Windows NT 4.0 ";
|
|
break;
|
|
default:
|
|
debugStream.str("");
|
|
debugStream.clear();
|
|
debugStream << " Unknown Windows "
|
|
<< NT_MAJOR << NT_MINOR
|
|
<< NT_BUILD << std::endl;
|
|
OsVer = debugStream.str();
|
|
break;
|
|
}
|
|
} else if (NT_MAJOR == 5) {
|
|
switch (NT_MINOR) {
|
|
case 0:
|
|
OsVer = "Windows 2000 " + NT_POST_STRING;
|
|
break;
|
|
case 1:
|
|
if (NT_SUITE == VER_SUITE_PERSONAL) {
|
|
OsVer = "Windows XP Home Edition " + NT_POST_STRING;
|
|
} else if (NT_SUITE == VER_SUITE_EMBEDDEDNT) {
|
|
OsVer = "Windows XP Embedded " + NT_POST_STRING;
|
|
} else {
|
|
OsVer = "Windows XP Professional " + NT_POST_STRING;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (NT_SUITE == VER_SUITE_WH_SERVER) {
|
|
OsVer = "Windows Home Server" + NT_POST_STRING;
|
|
} else {
|
|
OsVer = "Windows Server 2003/XP x64 " + NT_POST_STRING;
|
|
}
|
|
break;
|
|
case 5:
|
|
OsVer = "Windows Neptune " + NT_POST_STRING;
|
|
break;
|
|
default:
|
|
debugStream.str("");
|
|
debugStream.clear();
|
|
debugStream << " Unknown Windows "
|
|
<< NT_MAJOR << NT_MINOR
|
|
<< NT_BUILD << std::endl;
|
|
OsVer = debugStream.str();
|
|
break;
|
|
}
|
|
} else if (NT_MAJOR == 6) {
|
|
switch (NT_MINOR) {
|
|
case 0:
|
|
if (NT_TYPE == VER_NT_WORKSTATION) {
|
|
OsVer = "Windows Vista " + NT_POST_STRING;
|
|
} else {
|
|
OsVer = "Windows Server 2008 " + NT_POST_STRING;
|
|
}
|
|
break;
|
|
case 1:
|
|
if (NT_BUILD == 8400 || NT_SUITE == VER_SUITE_WH_SERVER) {
|
|
OsVer = "Windows Home Server 2011 " + NT_POST_STRING;
|
|
} else {
|
|
if (NT_TYPE == VER_NT_WORKSTATION) {
|
|
OsVer = "Windows 7 " + NT_POST_STRING;
|
|
} else {
|
|
OsVer = "Windows Server 2008 R2 " + NT_POST_STRING;
|
|
}
|
|
}
|
|
break;
|
|
case 2:
|
|
if (NT_TYPE == VER_NT_WORKSTATION) {
|
|
OsVer = "Windows 8 " + NT_POST_STRING;
|
|
} else {
|
|
OsVer = "Windows Server 2012 " + NT_POST_STRING;
|
|
}
|
|
break;
|
|
case 3:
|
|
if (NT_TYPE == VER_NT_WORKSTATION) {
|
|
OsVer = "Windows 8.1 " + NT_POST_STRING;
|
|
} else {
|
|
OsVer = "Windows Server 2012 R2 " + NT_POST_STRING;
|
|
}
|
|
break;
|
|
default:
|
|
debugStream.str("");
|
|
debugStream.clear();
|
|
debugStream << " Unknown Windows "
|
|
<< NT_MAJOR << NT_MINOR
|
|
<< NT_BUILD << std::endl;
|
|
OsVer = debugStream.str();
|
|
break;
|
|
}
|
|
} else if (NT_MAJOR == 10) {
|
|
switch (NT_MINOR) {
|
|
case 0: {
|
|
if (!is_win11) {
|
|
if (NT_TYPE == VER_NT_WORKSTATION) {
|
|
OsVer = "Windows 10 " + NT_POST_STRING;
|
|
} else {
|
|
if (NT_BUILD >= 14393 && NT_BUILD < 17763) {
|
|
OsVer = "Windows Server 2016 " + NT_POST_STRING;
|
|
} else if (NT_BUILD >= 17763 && NT_BUILD < 20348) {
|
|
OsVer = "Windows Server 2019 " + NT_POST_STRING;
|
|
} else if (NT_BUILD >= 20348 && NT_BUILD <= 25398) {
|
|
OsVer = "Windows Server 2022 " + NT_POST_STRING;
|
|
} else {
|
|
OsVer = "Windows Server " + NT_POST_STRING;
|
|
}
|
|
}
|
|
} else {
|
|
if (NT_TYPE == VER_NT_WORKSTATION) {
|
|
OsVer = "Windows 11 " + NT_POST_STRING;
|
|
} else {
|
|
if (NT_BUILD == 26100) {
|
|
OsVer = "Windows Server 2025 " + NT_POST_STRING;
|
|
} else {
|
|
OsVer = "Windows Server " + NT_POST_STRING;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 1:
|
|
OsVer = "Windows 12 " + NT_POST_STRING;
|
|
break;
|
|
default:
|
|
debugStream.str("");
|
|
debugStream.clear();
|
|
debugStream << " - Unknown Windows "
|
|
<< NT_MAJOR << NT_MINOR
|
|
<< NT_BUILD << std::endl;
|
|
OsVer = debugStream.str();
|
|
break;
|
|
}
|
|
} else {
|
|
debugStream.str("");
|
|
debugStream.clear();
|
|
debugStream << " - Unknown Windows";
|
|
OsVer = debugStream.str();
|
|
NOTREACHED();
|
|
}
|
|
|
|
return OsVer;
|
|
}
|
|
|
|
std::wstring const GetOSNameW() {
|
|
const std::wstring retval = stringToWstring(GetOSNameA());
|
|
return retval;
|
|
}
|
|
|
|
std::wstring const GetWinVersion() {
|
|
const std::wstring wver = stringToWstring(GetNTString());
|
|
return wver;
|
|
}
|
|
|
|
std::string const GetNTString() {
|
|
// NT version number
|
|
std::string NtVer;
|
|
std::ostringstream debugStream;
|
|
|
|
bool gotNTVersion = getWinNTVersion();
|
|
if (!gotNTVersion) {
|
|
return std::string();
|
|
}
|
|
|
|
// Make sure that the values returned make sense.
|
|
// NT Kernels with numbers outside this range don't exist
|
|
if (NT_MAJOR >=3 && NT_MAJOR <=11) {
|
|
// Define NtVer as human readable string literal separated by decimals
|
|
NtVer = std::to_string(NT_MAJOR)
|
|
+ "." + std::to_string(NT_MINOR)
|
|
+ "." + std::to_string(NT_BUILD);
|
|
}
|
|
|
|
return NtVer;
|
|
}
|
|
|
|
// Intentionally execute an invalid opcode to kill the program and signal to debugger
|
|
// See http://ref.x86asm.net/coder32.html
|
|
void ImmediateDebugCrash() {
|
|
#if defined(_WIN32) && !defined(_WIN64)
|
|
#ifdef __MINGW32__
|
|
asm("int3\n\t"
|
|
"ud2");
|
|
#else
|
|
// 32 bit assembly code
|
|
__asm int 3 // Execute int3 interrupt
|
|
__asm {
|
|
UD2 // Execute 0x0F, 0x0B
|
|
}
|
|
#endif // __MINGW32__
|
|
#elif defined(_WIN64) // x86_64
|
|
/* MSVC-specific x64 ud2 since MSVC doesn't allow inline assembly
|
|
when compiling for x64 */
|
|
__debugbreak();
|
|
#endif // defined(_WIN32) && !defined(_WIN64)
|
|
}
|
|
|
|
// Dumb equivalent of Chromium's implementation
|
|
void NotReachedImpl(std::string func_name) {
|
|
// Log function name and then crash the program
|
|
std::string func_string = func_name;
|
|
std::cerr << "NOTREACHED(): " << func_string << std::endl;
|
|
ImmediateDebugCrash();
|
|
}
|