Files
xp_activate32/src/utils.cc
T
2025-11-26 03:52:47 -06:00

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