获取系统版本信息
通过 GetVersionEx 获取系统版本的方法可能不适用于所有情况,而且将要过时(被废弃)。下面介绍一种通过 WMI 查询并根据版本号进行划分的系统版本解析工具,其他方法还有通过注册表和通过文件属性等等。内部版本号表可以通过官方渠道获取,例如:
Windows 10 更新历史记录;
Windows 11 更新历史记录
代码
sysinfo.h
#pragma once
#include <string>
#include <iostream>
#include <windows.h>
#include <iphlpapi.h>
#include <comdef.h>
#include <Wbemidl.h>
#include <math.h>
class SysInfo
{
public:
SysInfo();
virtual ~SysInfo();
bool init_wmi();
void uninit_wmi();
double get_memory_size();
std::string get_os_name();
std::string get_host_name();
int get_file_flag(std::string file_name);
std::string get_area(std::string ip);
std::string wstring_to_string(wchar_t* data);
protected:
private:
bool m_init_wmi = false;
IWbemServices* pSvc = NULL;
IWbemLocator* pLoc = NULL;
HRESULT hres = NULL;
};
SysInfo.cpp
#include "SysInfo.h"
#pragma comment(lib, "wbemuuid.lib")
#pragma comment(lib, "iphlpapi.lib")
#define GBYTES 1073741824
#define MBYTES 1048576
#define KBYTES 1024
#define DKBYTES 1024.0
SysInfo::SysInfo()
{
m_init_wmi = init_wmi();
}
SysInfo::~SysInfo()
{
uninit_wmi();
}
bool SysInfo::init_wmi()
{
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
return false;
}
hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
if (FAILED(hres))
{
CoUninitialize();
return false;
}
hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc);
if (FAILED(hres))
{
CoUninitialize();
return false;
}
hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);
if (FAILED(hres))
{
pLoc->Release();
CoUninitialize();
return false;
}
hres = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
if (FAILED(hres))
{
pSvc->Release();
pLoc->Release();
CoUninitialize();
return false;
}
return true;
}
void SysInfo::uninit_wmi()
{
pSvc->Release();
pLoc->Release();
CoUninitialize();
}
//Win32_PhysicalMemory
double SysInfo::get_memory_size()
{
double mem_size = 0;
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(bstr_t("WQL"), bstr_t("SELECT * FROM Win32_PhysicalMemory")
, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
if (FAILED(hres))
{
pSvc->Release();
pLoc->Release();
CoUninitialize();
return -1;
}
IWbemClassObject* pclsObj = NULL;
ULONG uReturn = 0;
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if (0 == uReturn)
{
break;
}
VARIANT vtProp = { 0 };
VariantInit(&vtProp);// 标准初始化
hr = pclsObj->Get(L"Capacity", 0, &vtProp, 0, 0);
std::string data = wstring_to_string(vtProp.bstrVal);
mem_size += ::atof(data.c_str());
VariantClear(&vtProp);
pclsObj->Release();
}
pEnumerator->Release();
double mem_total = mem_size / 1024 / 1024 / 1024;
return floor(mem_total * 100) / 100;
}
std::string SysInfo::get_os_name()
{
std::string res_data;
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(bstr_t("WQL"), bstr_t("SELECT * FROM win32_operatingsystem")
, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
if (FAILED(hres))
{
pSvc->Release();
pLoc->Release();
CoUninitialize();
return res_data;
}
IWbemClassObject* pclsObj = NULL;
ULONG uReturn = 0;
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if (0 == uReturn)
{
break;
}
VARIANT vtProp = { 0 };
VariantInit(&vtProp);// 标准初始化
hr = pclsObj->Get(L"name", 0, &vtProp, 0, 0);
std::string data = wstring_to_string(vtProp.bstrVal);
data = data.substr(0, data.find('|'));
hr = pclsObj->Get(L"Version", 0, &vtProp, 0, 0);
res_data = wstring_to_string(vtProp.bstrVal);
std::string restp = res_data;
std::string temp = "[";
temp += res_data;
temp += "] ";
temp += data;
res_data = temp;
// 分割string字符串
int pos1 = 0, pos2 = 0;
std::string pattern = ".";
restp += pattern;
std::string s[3];
for (int i = 0; i < 3; i++) {
pos2 = (int)restp.find(pattern, pos1);
s[i] = restp.substr(pos1,
static_cast<std::basic_string<char, std::char_traits<char>,
std::allocator<char>>::size_type>(pos2) - pos1);
pos1 = pos2 + 1;
}
//for (int i = 0; i < 3; i++) {
//std::cout << s[i] << std::endl;
//}
/*
size_t size = s[0].length() + 1;
char* MajorVer = (char*)malloc(sizeof(char) * size);
if (MajorVer != NULL) strcpy_s(MajorVer, size, s[0].c_str());
size = s[1].length() + 1;
char* MinorVer = (char*)malloc(sizeof(char) * size);
if (MinorVer != NULL) strcpy_s(MinorVer, size, s[1].c_str());
size = s[2].length() + 1;
char* BuildVer = (char*)malloc(sizeof(char) * size);
if (BuildVer != NULL) strcpy_s(BuildVer, size, s[2].c_str());
*/
int MajorVer = 0, MinorVer = 0, BuildVer = 0, L;
L = sscanf_s(s[0].c_str(), "%d", &MajorVer);
L = sscanf_s(s[1].c_str(), "%d", &MinorVer);
L = sscanf_s(s[2].c_str(), "%d", &BuildVer);
printf("大版本号:%d, 小版本号:%d, 内部版本号:%d\n", MajorVer, MinorVer, BuildVer);
printf("显式版本: ");
if (BuildVer >= 22621) printf("Windows 11 22H2 Or Greater\n");
else if (BuildVer >= 22000) printf("Windows 11 21H2\n");
else if (BuildVer == 20348) printf("Windows Server 2022\n");
else if (BuildVer >= 19045) printf("Windows 10 22H2\n");
else if (BuildVer >= 19044) printf("Windows 10 21H2\n");
else if (BuildVer >= 19043) printf("Windows 10 21H1\n");
else if (BuildVer >= 19042) printf("Windows 10 20H2\n");
else if (BuildVer >= 19041) printf("Windows 10 2004\n");
else if (BuildVer >= 18363) printf("Windows 10 1909\n");
else if (BuildVer >= 18362) printf("Windows 10 1903\n");
else if (BuildVer >= 17763) printf("Windows 10 1809\n");
else if (BuildVer >= 17134) printf("Windows 10 1803\n");
else if (BuildVer >= 16299) printf("Windows 10 1709\n");
else if (BuildVer >= 15063) printf("Windows 10 1703\n");
else if (BuildVer >= 14393) printf("Windows 10 1607\n");
else if (BuildVer >= 10586) printf("Windows 10 1511\n");
else if (BuildVer >= 10240) printf("Windows 10 1507\n");
// 以下数据属于网络收集,不一定准确,数据已经不可考究
else if (BuildVer >= 9200)
{// 6.2->win 8; 6.3->win 8.1
if (MinorVer == 2) printf("Windows 8 Release\n");
else if (MinorVer == 3) printf("Windows 8.1 Release\n");
}
else if (BuildVer >= 7601) printf("Windows 7 Service Pack 1\n");
else if (BuildVer >= 7600) printf("Windows 7 Release\n");
else if (BuildVer >= 6002) printf("Windows Vista SP2\n");
else if (BuildVer >= 6001) printf("Windows Vista SP1\n");
else if (BuildVer >= 6000) printf("Windows Vista\n");
else if (BuildVer >= 3790) printf("Windows XP Professional x64 Edition\n");
else if (BuildVer == 3000) printf("Windows Me");// 版本特殊?
else if (BuildVer >= 2600) printf("Windows XP\n");// 存在特殊版本
else if (BuildVer == 2222) printf("Windows 98 Second Edition\n");// 版本特殊?
else if (BuildVer >= 2195) printf("Windows 2000 Professional\n");
else if (BuildVer >= 1998) printf("Windows 98\n");
else if (BuildVer >= 1381) printf("Windows NT Workstation 4.0\n");
else if (BuildVer >= 1057) printf("Windows NT Workstation 3.51\n");// 版本特殊?
else if (BuildVer >= 950) printf("Windows 95\n");
else if (BuildVer >= 807) printf("Windows NT Workstation 3.5\n");
else if (BuildVer >= 528) printf("Windows NT 3.1\n");
else printf("版本特殊或者为远古版本!\n");
// 释放
//free(MajorVer);
//free(MinorVer);
//free(BuildVer);
VariantClear(&vtProp);
pclsObj->Release();
}
pEnumerator->Release();
return res_data;
}
std::string SysInfo::get_host_name()
{
std::string host_name;
char buf[MAX_PATH] = { 0 };
DWORD length = MAX_PATH;
if (::GetComputerNameA(buf, &length)) {
host_name = buf;
}
return host_name;
}
int SysInfo::get_file_flag(std::string file_name)
{
return 0;
}
std::string SysInfo::get_area(std::string ip)
{
std::string area;
return area;
}
std::string SysInfo::wstring_to_string(wchar_t* data)
{
std::string res_data;
int iSize;
// 宽字符串转换
iSize = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL);
char* pCapacity = (char*)malloc(iSize * sizeof(char));
if (pCapacity == NULL) return res_data;
pCapacity[0] = 0;
WideCharToMultiByte(CP_ACP, 0, data, -1, pCapacity, iSize, NULL, NULL);
res_data = pCapacity;
free(pCapacity);
return res_data;
}
mian.cpp
#include "SysInfo.h"
int main()
{
SysInfo Info;
Info.init_wmi();
printf("%s\n", Info.get_os_name().c_str());
//Info.uninit_wmi();
system("pause");
return 0;
}
效果如图所示:

代码是很早之前写的,用的话需要自己优化一下。
更新版本
参考:https://blog.csdn.net/magictong/article/details/40753519,修复了 PE 开启了兼容模式时 RtlGetVersion 获取到错误的版本号的问题。
下面贴一张作者文章的原图:

#pragma once
#include <Windows.h>
#define _LIBLIANYOU_OSVERSION_INVALID 0xffffffff
typedef LONG NTSTATUS, * PNTSTATUS;
#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS (0x00000000)
#endif
#ifndef DISPLAY_VERSION_VALUE
#define DISPLAY_VERSION_VALUE L"DisplayVersion"
#endif
typedef NTSTATUS(WINAPI* __LYRtlGetVersion)(PRTL_OSVERSIONINFOW);
typedef VOID(NTAPI* __LYRtlGetNtVersionNumbers)(
_Out_opt_ PULONG NtMajorVersion,
_Out_opt_ PULONG NtMinorVersion,
_Out_opt_ PULONG NtBuildNumber);
// https://stackoverflow.com/questions/36543301/detecting-windows-10-version/36543774#36543774
// https://blog.csdn.net/magictong/article/details/40753519
inline BOOL LYGetOSVersion(PRTL_OSVERSIONINFOW lpRovi, BOOL bRedirection = false)
{
HMODULE hMod = GetModuleHandleW(L"ntdll.dll");
if (hMod != nullptr)
{
__LYRtlGetVersion myRtlGetVersion = nullptr;
__LYRtlGetNtVersionNumbers myRtlGetNtVersionNumbers =
(__LYRtlGetNtVersionNumbers)GetProcAddress(
hMod,
"RtlGetNtVersionNumbers"
);
if (bRedirection) { // 是否遵循兼容模式的 API 重定向
myRtlGetVersion = (__LYRtlGetVersion)GetProcAddress(
hMod,
"RtlGetVersion"
);
if (myRtlGetVersion != nullptr)
{
lpRovi->dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW);
if (STATUS_SUCCESS == myRtlGetVersion(lpRovi))
{
return TRUE;
}
else {
return FALSE;
}
}
}
if (myRtlGetNtVersionNumbers != nullptr
&& (!bRedirection || myRtlGetVersion == nullptr))
{
lpRovi->dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW);
ULONG NtMajorVersion = 0;
ULONG NtMinorVersion = 0;
ULONG NtBuildNumber = 0;
myRtlGetNtVersionNumbers(&NtMajorVersion, &NtMinorVersion, &NtBuildNumber);
NtBuildNumber &= 0x0ffff;
lpRovi->dwMajorVersion = NtMajorVersion;
lpRovi->dwMinorVersion = NtMinorVersion;
lpRovi->dwBuildNumber = NtBuildNumber;
return TRUE;
}
}
return FALSE;
}
// https://stackoverflow.com/questions/47926094/detecting-windows-10-os-build-minor-version
inline BOOL LYGetDisplayVersion(std::wstring& lpszOSDisplayVersion)
{
HKEY hKey;
LRESULT lRes = RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
wcschr(
wcschr(
wcschr(
UNIFIEDBUILDREVISION_KEY,
'\\'
) + 1,
'\\'
) + 1,
'\\'
) + 1,
0,
KEY_READ,
&hKey
);
if (lRes == ERROR_SUCCESS)
{
DWORD dwType = 0;
DWORD dwSize = 0;
// 第一次调用:获取所需缓冲区大小
LONG lResult = RegQueryValueExW(
hKey,
DISPLAY_VERSION_VALUE,
nullptr,
&dwType,
nullptr,
&dwSize);
if (lResult != ERROR_SUCCESS ||
(dwType != REG_SZ
&& dwType != REG_EXPAND_SZ)) {
return false; // 读取失败或类型不匹配
}
// 分配缓冲区(以 WCHAR 为单位),包括空字符
std::vector<wchar_t> buffer(dwSize / sizeof(wchar_t));
// 第二次调用:读取实际的字符串值
lResult = RegQueryValueExW(hKey,
DISPLAY_VERSION_VALUE,
nullptr,
nullptr,
reinterpret_cast<LPBYTE>(buffer.data()),
&dwSize);
if (lResult != ERROR_SUCCESS) {
return false; // 读取失败
}
// 将缓冲区转换为 std::wstring,确保字符串以空字符结尾
lpszOSDisplayVersion.assign(buffer.data());
return true;
}
return false;
}
inline DWORD32 LYGetUBR(void)
{
DWORD32 ubr = 0, ubr_size = sizeof(DWORD32);
HKEY hKey;
LRESULT lRes = RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
wcschr(
wcschr(
wcschr(
UNIFIEDBUILDREVISION_KEY,
'\\'
) + 1,
'\\'
) + 1,
'\\'
) + 1,
0,
KEY_READ,
&hKey
);
if (lRes == ERROR_SUCCESS)
{
RegQueryValueExW(
hKey,
UNIFIEDBUILDREVISION_VALUE,
0,
NULL,
(LPBYTE)&ubr,
(LPDWORD)&ubr_size
);
}
return ubr;
}
inline DWORD32 LYGetOSVersionAndUBR(PRTL_OSVERSIONINFOW lpRovi)
{
if (!LYGetOSVersion(lpRovi))
{
return _LIBLIANYOU_OSVERSION_INVALID;
}
return LYGetUBR();
}
// 函数:格式化版本号
std::wstring LYFormatVersionString(const RTL_OSVERSIONINFOW& osvi, DWORD32 UBR) {
std::wstringstream versionStream;
versionStream << osvi.dwMajorVersion << L"."
<< osvi.dwMinorVersion << L"."
<< osvi.dwBuildNumber << L"."
<< UBR;
return versionStream.str();
}
std::wstring LYFormatVersionString2(const RTL_OSVERSIONINFOW& osvi, std::wstring szOSDisplayVersion) {
std::wstringstream versionStream;
if (osvi.dwBuildNumber < 7600) { // win7 以前
versionStream << L"版本过低(Vista 或更早)";
}
else if(osvi.dwBuildNumber >= 7600
&& osvi.dwBuildNumber < 9200) { // win7
versionStream << L"Windows 7 <"
<< szOSDisplayVersion << L">";
}
else if (osvi.dwBuildNumber >= 9200
&& osvi.dwBuildNumber < 10240) { // win8
versionStream << L"Windows 8 <"
<< szOSDisplayVersion << L">";
}
else if (osvi.dwBuildNumber >= 10240
&& osvi.dwBuildNumber < 19042) { // win10 20H2 之前版本
versionStream << L"Windows 10 低于 20H2 <"
<< szOSDisplayVersion << L">";
}
else if (osvi.dwBuildNumber == 19042) { // win10 20H2
versionStream << L"Windows 10 20H2 <"
<< szOSDisplayVersion << L">";
}
else if (osvi.dwBuildNumber == 19043) { // win10 21H1
versionStream << L"Windows 10 21H1 <"
<< szOSDisplayVersion << L">";
}
else if (osvi.dwBuildNumber == 19044) { // win10 21H2
versionStream << L"Windows 10 21H2 <"
<< szOSDisplayVersion << L">";
}
else if (osvi.dwBuildNumber == 19045) { // win10 22H2
versionStream << L"Windows 10 22H2 <"
<< szOSDisplayVersion << L">";
}
else if(osvi.dwBuildNumber == 22000) { // win11 21H2
versionStream << L"Windows 11 21H2 <"
<< szOSDisplayVersion << L">";
}
else if (osvi.dwBuildNumber == 22621) { // win11 22H2
versionStream << L"Windows 11 22H2 <"
<< szOSDisplayVersion << L">";
}
else if (osvi.dwBuildNumber == 22631) { // win11 23H2
versionStream << L"Windows 11 23H2 <"
<< szOSDisplayVersion << L">";
}
else if (osvi.dwBuildNumber == 26100) { // win11 24H2
versionStream << L"Windows 11 24H2 <"
<< szOSDisplayVersion << L">";
}
else if (osvi.dwBuildNumber > 26100) {
versionStream << L"Windows 11 24H2 或者更高版本 <"
<< szOSDisplayVersion << L">";
}
else {
versionStream << L"预览体验计划版本或者其他 <"
<< szOSDisplayVersion << L">";
}
return versionStream.str();
}
使用样例:
/**
*
* CRunaGUIDlg::OnBnClickedButton6()
* -- 设置是否使用小任务栏按钮
* (系统默认不显示)
*
*/
void CRunaGUIDlg::OnBnClickedButton6()
{
RTL_OSVERSIONINFOW osvi{};
DWORD32 UBR = LYGetOSVersionAndUBR(&osvi);
if (UBR == _LIBLIANYOU_OSVERSION_INVALID)
{
if (IDYES != MessageBoxW(
L"当前系统版本可能不支持此功能,继续执行可能出现未知结果。是否要继续?",
L"提示", MB_YESNO | MB_ICONWARNING | MB_APPLMODAL))
return;
}
else if (osvi.dwMajorVersion >= 10 && osvi.dwBuildNumber >= 22621 && UBR >= 1413)
{
// 格式化版本号
std::wstring formattedVersion = LYFormatVersionString(osvi, UBR);
std::wstring szOSDisplayVersion;
if (!LYGetDisplayVersion(szOSDisplayVersion)) {
szOSDisplayVersion = L"(Unknown)";
}
std::wstring formattedVersion2 =
LYFormatVersionString2(osvi, szOSDisplayVersion);
// 构建完整的消息框内容
std::wstring message =
L"当前系统版本不支持此功能。\n构建版本: "
+ formattedVersion
+ L"\n显式版本: " + formattedVersion2;
// 显示消息框
MessageBoxW( message.c_str(),
L"提示", MB_OK | MB_ICONWARNING | MB_APPLMODAL);
return;
}
//TaskbarSmallIcons
const char* valueName1 = "TaskbarSmallIcons";
DWORD value1;
value1 = RegGetExplorerAdvancedDwordValue(valueName1);
if (value1 != IsSmallTaskIconsEnabled)
{
MessageBoxW(L"当前缓存的设置与系统配置不一致,需要同步后再操作。",
L"提示",
MB_OK | MB_ICONINFORMATION | MB_APPLMODAL);
OnInitCheckIsTaskbarSmallIconsEnabled();
return;
}
if (!IsSmallTaskIconsEnabled)
{
RegSetExplorerAdvancedDwordValue(valueName1, 1);
IsSmallTaskIconsEnabled = true;
smallTaskbarIconsBn.SetWindowTextW(L"禁用小任务栏按钮");
}
else
{
RegSetExplorerAdvancedDwordValue(valueName1, 0);
IsSmallTaskIconsEnabled = false;
smallTaskbarIconsBn.SetWindowTextW(L"启用小任务栏按钮");
}
// 小任务栏按钮
// (目前需要配合修改注册表,不需要注册表的实现还在研究,可能存在)
// HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced
// TaskbarSmallIcons 值:1 小图标, 值 0 大图标
SendMessageTimeoutW(
HWND_BROADCAST,
WM_SETTINGCHANGE, NULL,
(LPARAM)L"TraySettings",
SMTO_NOTIMEOUTIFNOTHUNG,
3000, NULL);
MessageBoxW(L"操作成功完成", L"提示",
MB_OK | MB_ICONINFORMATION | MB_APPLMODAL);
}
效果:

[补充]
判断进程是否运行在兼容模式下:
#include <windows.h>
#include <psapi.h>
#include <iostream>
#include <string>
#include <locale>
#include <vector>
struct CompatibilityEntry {
std::wstring programPath;
std::wstring compatibilityMode;
};
// Convert a string to lowercase
void ToLower(std::wstring& str) {
for (size_t i = 0; i < str.length(); ++i) {
str[i] = towlower(str[i]);
}
}
// Function to get the current executable path
std::wstring GetCurrentExecutablePath() {
DWORD bufferSize = MAX_PATH;
std::vector<wchar_t> buffer(bufferSize);
while (true) {
DWORD result = GetModuleFileNameW(
NULL,
buffer.data(),
bufferSize);
if (result == 0) {
std::wcerr << L"Failed to get the current process path." << std::endl;
return L"";
}
if (result < bufferSize) {
return std::wstring(buffer.data());
}
bufferSize *= 2;
buffer.resize(bufferSize);
}
}
// Function to check if AcLayers.dll is loaded in the current process
BOOL IsAcLayersDllLoaded() {
WCHAR systemDir[MAX_PATH];
if (GetSystemDirectoryW(systemDir, MAX_PATH) == 0) {
std::wcerr << L"Failed to get the system directory." << std::endl;
return FALSE;
}
std::wstring aclayersPath = systemDir;
aclayersPath += L"\\AcLayers.dll";
ToLower(aclayersPath);
HMODULE hModules[1024];
DWORD cbNeeded;
if (EnumProcessModules(GetCurrentProcess(), hModules, sizeof(hModules),
&cbNeeded)) {
for (size_t i = 0; i < (cbNeeded / sizeof(HMODULE)); ++i) {
WCHAR moduleName[MAX_PATH];
if (GetModuleFileNameExW(GetCurrentProcess(), hModules[i],
moduleName, MAX_PATH)) {
std::wstring modulePath = moduleName;
ToLower(modulePath);
if (modulePath == aclayersPath) {
return TRUE;
}
}
}
}
return FALSE;
}
// Function to check compatibility mode and merge results
BOOL RegCheckCompatibilityMode(
HKEY rootKey,
const std::wstring& subKey,
const std::wstring& currentPath,
std::vector<CompatibilityEntry>& results
)
{
HKEY hKey;
if (RegOpenKeyEx(rootKey, subKey.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS) {
std::wcerr << L"Failed to open registry key: " << subKey << std::endl;
return FALSE;
}
DWORD index = 0;
WCHAR valueName[256];
DWORD valueNameSize = sizeof(valueName) / sizeof(valueName[0]);
BYTE data[256];
DWORD dataSize = sizeof(data);
DWORD type;
std::wcout.imbue(std::locale(""));
while (RegEnumValue(hKey,
index, valueName, &valueNameSize,
NULL, &type, data, &dataSize) == ERROR_SUCCESS) {
if (type == REG_SZ) {
CompatibilityEntry entry;
entry.programPath = valueName;
entry.compatibilityMode = (WCHAR*)data;
auto it = std::find_if(
results.begin(),
results.end(),
[&](const CompatibilityEntry& e)
{
return e.programPath == entry.programPath;
});
// Add or overwrite entry
if (it != results.end()) {
if (rootKey == HKEY_LOCAL_MACHINE) {
*it = entry; // Overwrite if from HKEY_LOCAL_MACHINE
}
}
else {
results.push_back(entry);
}
if (entry.programPath == currentPath) {
std::wcout << L"[-] Match found!\n\tProgram: "
<< entry.programPath << L" - Compatibility Mode: "
<< entry.compatibilityMode << std::endl;
}
}
index++;
valueNameSize = sizeof(valueName) / sizeof(valueName[0]);
dataSize = sizeof(data);
}
RegCloseKey(hKey);
return TRUE;
}
// Function that encapsulates all three checks
BOOL PerformCheckCompatibilityMode() {
// Check if AcLayers.dll is loaded
if (!IsAcLayersDllLoaded()) {
std::wcerr << L"[+] AcLayers.dll is not loaded in the current process." << std::endl;
return FALSE;
}
else {
std::wcout << L"[-] AcLayers.dll is loaded in the current process." << std::endl;
}
std::wstring currentPath = GetCurrentExecutablePath();
if (currentPath.empty()) {
return FALSE;
}
std::wcout << L"[*] Current process path: " << currentPath << std::endl;
std::vector<CompatibilityEntry> results;
// Check HKEY_CURRENT_USER registry path
std::wcout << L"[*] Checking HKEY_CURRENT_USER..." << std::endl;
RegCheckCompatibilityMode(HKEY_CURRENT_USER,
L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers",
currentPath, results);
// Check HKEY_LOCAL_MACHINE registry path
std::wcout << L"[*] Checking HKEY_LOCAL_MACHINE..." << std::endl;
RegCheckCompatibilityMode(HKEY_LOCAL_MACHINE,
L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers",
currentPath, results);
// Final check: Ensure at least one registry entry matches and DLL is loaded
if (!results.empty()) {
//std::wcout << L"Compatibility settings detected." << std::endl;
return TRUE;
}
else {
//std::wcerr << L"No compatibility settings found." << std::endl;
return FALSE;
}
}
int main() {
if (PerformCheckCompatibilityMode()) {
std::wcout << L"\n[-] The current process is running in compatibility mode." << std::endl;
}
else {
std::wcout << L"\n[+] Not detected." << std::endl;
}
return 0;
}
原文出处链接:https://blog.csdn.net/qq_59075481/article/details/142319803。
本文发布于:2024.09.17,修改于:2024.09.17, 2024.10.23, 2024.10.31。

1100

被折叠的 条评论
为什么被折叠?



