Win32获取系统版本信息

COSVersion.h

#pragma once

#include <wtypesbase.h>
#include <tchar.h>
#include <vector>
#include <map>
#include <string>

#ifdef _UNICODE
using _tstring = std::wstring;
#else
using _tstring = std::string;
#endif

namespace COSVersion
{
    typedef struct _NTVERSIONNUMBERS_INFO NTVERSIONNUMBERS_INFO, * PNTVERSIONNUMBERS_INFO;

    typedef struct _FILE_VERSION_NUMBERS
    {
        DWORD dwMajor;          // 主版本号
        DWORD dwMinor;          // 次版本号
        DWORD dwBuildMajor;     // 主构建版本号
        DWORD dwBuildMinor;     // 次构建版本号

        _FILE_VERSION_NUMBERS() :
            dwMajor(0),
            dwMinor(0),
            dwBuildMajor(0),
            dwBuildMinor(0)
        {

        }
    }FILE_VERSION_NUMBERS, * PFILE_VERSION_NUMBERS;

    typedef struct _OS_VERSION_INFO
    {
        _tstring strDisplayVersion;         // 显示版本
        _tstring strInstallDate;            // 安装日期
        FILE_VERSION_NUMBERS osVersion;     // 系统版本号
        FILE_VERSION_NUMBERS ntdllVersion;  // ntdll 版本号
        SYSTEMTIME stInstallDate;           // 安装日期
        RTL_OSVERSIONINFOEXW osVersionEx;   // OS版本信息
        DWORD dwProductType;                // 产品类型
        _OS_VERSION_INFO() :
            osVersionEx{ 0 },
            stInstallDate{ 0 },
            dwProductType(0)
        {

        }

    }OS_VERSION_INFO, * POS_VERSION_INFO;

    // 获取操作系统版本信息
     OS_VERSION_INFO GetOSVersionInfo();

    // 系统版本检查
     bool IsWindows10_Or_11();
     bool IsWindows10();
     bool IsWindows11();
     bool IsWindows11_24H2();
     bool IsWindows11_23H2();
     bool IsWindows11_22H2();
     bool IsWindows11_21H2();

    // 获取 Ntdll.dll 版本号
     bool _GetNtdllVersion(PFILE_VERSION_NUMBERS pVersion);

    // 获取操作系统显示名
     _tstring _GetDisplayVersion();

    // 获取更新构建修订版本号
     DWORD _GetUpdateBuildRevision();

    // 获取安装日期
     DWORD _GetInstallDate();

     int64_t _GetInstallTime();

    // 获取版本号信息
     bool _GetNtVersionNumbers(PNTVERSIONNUMBERS_INFO pNtVerInfo);

    // 获取版本信息
     bool _GetVersion(RTL_OSVERSIONINFOEXW* pVerInfo);

    // 获取版本号信息
     bool _RtlGetNtVersionNumbers(DWORD* pMajor, DWORD* pMinor, DWORD* pBuild);

    // 获取版本信息
     bool _RtlGetVersion(PRTL_OSVERSIONINFOEXW lpVersionInformation);

    // 获取产品版本
    // 最低受支持的客户端    Windows Vista [仅限桌面应用]
    // 最低受支持的服务器    Windows Server 2008 [仅限桌面应用]
     bool _RtlGetProductInfo(DWORD dwOSMajor, DWORD dwOSMinor, DWORD dwSpMajor, DWORD dwSpMinor, PDWORD pdwProductType);

    // 获取文件产品版本号
     bool _GetFileProductVersion(const _tstring& strFile, PFILE_VERSION_NUMBERS pVersion);

    // 注册表操作
     bool _GetRegString(HKEY hKey, const _tstring& lpSubKey, const _tstring& lpValueName, _tstring& strValue);
     _tstring _GetRegString(HKEY hKey, const _tstring& lpSubKey, const _tstring& lpValueName);
     bool _GetRegDword(HKEY hKey, const _tstring& lpSubKey, const _tstring& lpValueName, DWORD& dwValue);
     DWORD _GetRegDword(HKEY hKey, const _tstring& lpSubKey, const _tstring& lpValueName);
     bool _GetRegQword(HKEY hKey, const _tstring& lpSubKey, const _tstring& lpValueName, int64_t& ullValue);
     int64_t _GetRegQword(HKEY hKey, const _tstring& lpSubKey, const _tstring& lpValueName);

    // 时间戳操作
     _tstring _TimestampToString(int64_t timestamp, bool bHasDate = true);
     SYSTEMTIME _TimestampToSystemTime(int64_t timestamp);
};

COSVersion.cpp

#include "COSVersion.h"
#include <versionhelpers.h>
#include <strsafe.h>
#include <map>

#define NT_SUCCESS(Status)  (((NTSTATUS)(Status)) >= 0)
#define STATUS_SUCCESS  ((NTSTATUS)0x00000000L)

#pragma comment(lib, "Version.lib")

namespace COSVersion
{
    typedef struct _NTVERSIONNUMBERS_INFO
    {
        DWORD dwMajor;          // 主版本号
        DWORD dwMinor;          // 次版本号
        DWORD dwBuild;          // 构建版本号
    }NTVERSIONNUMBERS_INFO, * PNTVERSIONNUMBERS_INFO;

    // https://learn.microsoft.com/zh-cn/windows/win32/sysinfo/operating-system-version
    // 操作系统                版本号    dwMajorVersion    dwMinorVersion     其他
    // Windows 10              10.0*       10              0                   OSVERSIONINFOEX.wProductType == VER_NT_WORKSTATION
    // Windows Server 2016     10.0*       10              0                   OSVERSIONINFOEX.wProductType != VER_NT_WORKSTATION
    // Windows 8.1             6.3*        6               3                   OSVERSIONINFOEX.wProductType == VER_NT_WORKSTATION
    // Windows Server 2012 R2  6.3*        6               3                   OSVERSIONINFOEX.wProductType != VER_NT_WORKSTATION
    // Windows 8               6.2         6               2                   OSVERSIONINFOEX.wProductType == VER_NT_WORKSTATION
    // Windows Server 2012     6.2         6               2                   OSVERSIONINFOEX.wProductType != VER_NT_WORKSTATION
    // Windows 7               6.1         6               1                   OSVERSIONINFOEX.wProductType == VER_NT_WORKSTATION
    // Windows Server 2008 R2  6.1         6               1                   OSVERSIONINFOEX.wProductType != VER_NT_WORKSTATION
    // Windows Server 2008     6.0         6               0                   OSVERSIONINFOEX.wProductType != VER_NT_WORKSTATION
    // Windows Vista           6.0         6               0                   OSVERSIONINFOEX.wProductType == VER_NT_WORKSTATION
    // Windows Server 2003 R2  5.2         5               2                   GetSystemMetrics (SM_SERVERR2) != 0
    // Windows Home Server     5.2         5               2                   OSVERSIONINFOEX.wSuiteMask & VER_SUITE_WH_SERVER
    // Windows Server 2003     5.2         5               2                   GetSystemMetrics (SM_SERVERR2) == 0
    // Windows XP Professional 5.2         5               2                   (OSVERSIONINFOEX.wProductType == VER_NT_WORKSTATION) &&
    //             x64 Edition                                                 (SYSTEM_INFO.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
    // Windows XP              5.1    5    1    不适用
    // Windows 2000            5.0    5    0    不适用

    typedef struct _WINDOWS_VERSIONNUMBERS
    {
        DWORD dwMajor;          // 主版本号
        DWORD dwMinor;          // 次版本号
        DWORD dwBuild;          // 构建号
    }WINDOWS_VERSIONNUMBERS, * PWINDOWS_VERSIONNUMBERS;

    std::map<_tstring, WINDOWS_VERSIONNUMBERS> g_mapOSServerVersion =
    {
        // Windows Server
        {_T("Windows Server 2003"), {5, 2, 0}},
        {_T("Windows Server 2003 R2"), {5, 2, 0}},

        {_T("Windows Server 2008"), {6, 0, 0}},
        {_T("Windows Server 2008 R2"), {6, 1, 0}},

        {_T("Windows Server 2012"), {6, 2, 0}},
        {_T("Windows Server 2012 R2"), {6, 2, 0}},

        {_T("Windows Server 2016 1607"), {10, 0, 14393}},
        {_T("Windows Server 2019 1809"), {10, 0, 17763}},
        {_T("Windows Server 2022"), {10, 0, 20348}},
    };

    std::map<_tstring, WINDOWS_VERSIONNUMBERS> g_mapOSClientVersion =
    {
        // Windows XP
        {_T("Windows XP"), {5, 1, 0}},
        {_T("Windows XP x64"), {5, 2, 0}},

        // Windows Vista
        {_T("Windows Vista"), {6, 0, 0}},

        // Windows 7
        {_T("Windows 7"), {6, 1, 0}},

        // Windows 8
        {_T("Windows 8"), {6, 2, 0}},

        // Windows 8.1
        {_T("Windows 8.1"), {6, 3, 0}},

        // Windows 10
        {_T("Windows 10 1507"), {10, 0, 10240}},
        {_T("Windows 10 1511"), {10, 0, 10586}},
        {_T("Windows 10 1607"), {10, 0, 14393}},
        {_T("Windows 10 1703"), {10, 0, 15036}},
        {_T("Windows 10 1709"), {10, 0, 16299}},
        {_T("Windows 10 1803"), {10, 0, 17134}},
        {_T("Windows 10 1809"), {10, 0, 17753}},
        {_T("Windows 10 1903"), {10, 0, 18362}},
        {_T("Windows 10 1909"), {10, 0, 18363}},
        {_T("Windows 10 2004"), {10, 0, 19041}},
        {_T("Windows 10 20H2"), {10, 0, 19042}},
        {_T("Windows 10 21H1"), {10, 0, 19043}},
        {_T("Windows 10 21H2"), {10, 0, 19044}},
        {_T("Windows 10 22H2"), {10, 0, 19045}},

        // Windows 11
        {_T("Windows 11 21H2"), {10, 0, 22000}},
        {_T("Windows 11 22H2"), {10, 0, 22621}},
        {_T("Windows 11 23H2"), {10, 0, 22631}},
        {_T("Windows 11 24H2"), {10, 0, 26100}},
    };

    bool _RtlGetNtVersionNumbers(DWORD* pMajor, DWORD* pMinor, DWORD* pBuild)
    {
        typedef VOID(NTAPI* NTPROC)(DWORD* dwMajor, DWORD* dwMinor, DWORD* dwBuild);
        HMODULE hModule = NULL;
        static NTPROC ProcAddress = NULL;
        bool fResult = false;

        if (NULL == ProcAddress)
        {
            hModule = ::LoadLibrary(_T("ntdll.dll"));
            if (NULL != hModule)
            {
                ProcAddress = (NTPROC)::GetProcAddress(hModule, "RtlGetNtVersionNumbers");
                ::FreeLibrary(hModule);
            }
        }

        if (NULL != ProcAddress)
        {
            fResult = true;

            ProcAddress(pMajor, pMinor, pBuild);
            *pBuild &= 0xffff;
        }

        return fResult;
    }

    bool _RtlGetVersion(PRTL_OSVERSIONINFOEXW lpVersionInformation)
    {
        typedef NTSTATUS(NTAPI* NTPROC)(PRTL_OSVERSIONINFOEXW lpVersionInformation);
        HMODULE hModule = NULL;
        static NTPROC ProcAddress = NULL;
        bool fResult = false;

        memset(lpVersionInformation, 0, sizeof(RTL_OSVERSIONINFOEXW));
        lpVersionInformation->dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);

        if (NULL == ProcAddress)
        {
            hModule = ::LoadLibrary(_T("ntdll.dll"));
            if (NULL != hModule)
            {
                ProcAddress = (NTPROC)::GetProcAddress(hModule, "RtlGetVersion");
                ::FreeLibrary(hModule);
            }
        }

        if (NULL != ProcAddress)
        {
            fResult = STATUS_SUCCESS == ProcAddress(lpVersionInformation);
        }

        return fResult;
    }

    bool _RtlGetProductInfo(DWORD dwOSMajor, DWORD dwOSMinor, DWORD dwSpMajor, DWORD dwSpMinor, PDWORD pdwProductType)
    {
        typedef BOOL(NTAPI* NTPROC)(DWORD, DWORD, DWORD, DWORD, PDWORD);
        HMODULE hModule = NULL;
        static NTPROC ProcAddress = NULL;
        bool fResult = false;

        if (NULL == ProcAddress)
        {
            hModule = ::LoadLibrary(_T("ntdll.dll"));
            if (NULL != hModule)
            {
                ProcAddress = (NTPROC)::GetProcAddress(hModule, "RtlGetProductInfo");
                ::FreeLibrary(hModule);
            }
        }

        if (NULL != ProcAddress)
        {
            fResult = ProcAddress(dwOSMajor, dwOSMinor, dwSpMajor, dwSpMinor, pdwProductType);
        }

        return fResult;
    }

#pragma pack(push)
#pragma pack(1)
    // 包含文件的版本信息。 此信息与语言和代码页无关
    // https://learn.microsoft.com/zh-cn/windows/win32/menurc/vs-versioninfo
    typedef struct {
        WORD             wLength;       // VS_VERSIONINFO 结构的长度(以字节为单位),此长度不包括在 32 位边界上对齐任何后续版本资源数据的填充
        WORD             wValueLength;  // Value 成员的长度(以字节为单位)
        WORD             wType;         // 版本资源中的数据类型, 1: 资源包含文本数据 0: 版本资源包含二进制数据
        WCHAR            szKey[15];     // Unicode 字符串 L“VS_VERSION_INFO”
        WORD             Padding1;      // 在 32 位边界上对齐 Children 成员所需的任意或零个 WORD
        //VS_FIXEDFILEINFO Value
        //WORD             Padding2
        //WORD             Children
    } VS_VERSIONINFO, * PVS_VERSIONINFO;

#pragma pack(pop)

    bool _GetFileProductVersion(const _tstring& strFile, PFILE_VERSION_NUMBERS pVersion)
    {
        struct LANGANDCODEPAGE {
            WORD wLanguage;
            WORD wCodePage;

            LANGANDCODEPAGE()
                :
                wLanguage(0),
                wCodePage(0)
            {

            }
        };

        PVOID pFsRedirectionOldValue = NULL;
        bool isDisableWow64Fs = false;
        bool fResult = false;
        UINT cbTranslate = 0;
        DWORD dwVerSize;
        LPVOID lpVerData = NULL;
        LANGANDCODEPAGE Translate;

        do
        {
            if (strFile.empty())
            {
                break;
            }

            // 禁用文件重定向
            isDisableWow64Fs = ::Wow64DisableWow64FsRedirection(&pFsRedirectionOldValue);

            // 获取版本信息数据大小
            dwVerSize = ::GetFileVersionInfoSize(strFile.c_str(), 0);
            if (0 == dwVerSize)
            {
                break;
            }

            // 分配版本信息缓冲
            lpVerData = ::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, dwVerSize);
            if (!lpVerData)
            {
                break;
            }

            // 获取版本信息
            if (!::GetFileVersionInfo(strFile.c_str(), 0, dwVerSize, lpVerData))
            {
                break;
            }

            // 获取语言代码
            LANGANDCODEPAGE* lpTranslate = NULL;
            if (!::VerQueryValue(lpVerData, _T("\\VarFileInfo\\Translation"), (LPVOID*)&lpTranslate, &cbTranslate))
            {
                break;
            }

            Translate = *lpTranslate;

            // 获取 VS_FIXEDFILEINFO 信息
            PVS_VERSIONINFO lpVersion = (PVS_VERSIONINFO)lpVerData;
            if (0 != lpVersion->wValueLength)
            {
                VS_FIXEDFILEINFO* pFixedFileInfo = (VS_FIXEDFILEINFO*)((LPBYTE)lpVersion + sizeof(VS_VERSIONINFO));

                DWORD dwAlign = 4;
                DWORD_PTR dwPadding = ((DWORD_PTR)pFixedFileInfo % dwAlign);
                if (0 != dwPadding)
                {
                    pFixedFileInfo = (VS_FIXEDFILEINFO*)((LPBYTE)pFixedFileInfo + (dwAlign - dwPadding));
                }

                pVersion->dwMajor = HIWORD(pFixedFileInfo->dwProductVersionMS);
                pVersion->dwMinor = LOWORD(pFixedFileInfo->dwProductVersionMS);
                pVersion->dwBuildMajor = HIWORD(pFixedFileInfo->dwProductVersionLS);
                pVersion->dwBuildMinor = LOWORD(pFixedFileInfo->dwProductVersionLS);
            }

            fResult = true;

        } while (false);

        // 恢复文件重定向
        if (isDisableWow64Fs)
        {
            ::Wow64RevertWow64FsRedirection(pFsRedirectionOldValue);
        }

        if (!lpVerData)
        {
            HeapFree(::GetProcessHeap(), 0, lpVerData);
        }

        return fResult;
    }

    _tstring _GetRegString(HKEY hKey, const _tstring& lpSubKey, const _tstring& lpValueName)
    {
        _tstring strResult;
        (void)_GetRegString(hKey, lpSubKey, lpValueName, strResult);
        return strResult;
    }

    bool _GetRegDword(HKEY hKey, const _tstring& lpSubKey, const _tstring& lpValueName, DWORD& dwValue)
    {
        LSTATUS ls = ERROR_SUCCESS;
        DWORD cbSize = sizeof(dwValue);

        ls = ::RegGetValue(hKey, lpSubKey.c_str(), lpValueName.c_str(), RRF_RT_REG_DWORD/* | RRF_ZEROONFAILURE*/, NULL, &dwValue, &cbSize);
        if (ERROR_SUCCESS != ls)
        {
            return false;
        }

        return ERROR_SUCCESS == ls;
    }

    DWORD _GetRegDword(HKEY hKey, const _tstring& lpSubKey, const _tstring& lpValueName)
    {
        DWORD dwResult = 0;
        (void)_GetRegDword(hKey, lpSubKey, lpValueName, dwResult);
        return dwResult;
    }

    bool _GetRegString(HKEY hKey, const _tstring& lpSubKey, const _tstring& lpValueName, _tstring& strValue)
    {
        LSTATUS ls = ERROR_SUCCESS;
        DWORD dwSize = 0;
        LPVOID lpBuf = NULL;

        //获取数据长度
        ls = ::RegGetValue(hKey, lpSubKey.c_str(), lpValueName.c_str(), RRF_RT_REG_SZ/* | RRF_ZEROONFAILURE*/, NULL, 0, &dwSize);
        if (ERROR_SUCCESS != ls)
        {
            return false;
        }

        // 数据长度超过常规大小限制, 则重新分配空间
        lpBuf = HeapAlloc(GetProcessHeap(), 0, dwSize);
        if (lpBuf)
        {
            ls = ::RegGetValue(hKey, lpSubKey.c_str(), lpValueName.c_str(), RRF_RT_REG_SZ /*| RRF_ZEROONFAILURE*/, NULL, lpBuf, &dwSize);
            if (ERROR_SUCCESS == ls)
            {
                strValue = (LPCTSTR)lpBuf;
            }

            HeapFree(GetProcessHeap(), 0, lpBuf);
        }

        return ERROR_SUCCESS == ls;
    }

    bool _GetRegQword(HKEY hKey, const _tstring& lpSubKey, const _tstring& lpValueName, int64_t& ullValue)
    {
        LSTATUS ls = ERROR_SUCCESS;
        DWORD cbSize = sizeof(ullValue);

        ls = ::RegGetValue(hKey, lpSubKey.c_str(), lpValueName.c_str(), RRF_RT_REG_QWORD/* | RRF_ZEROONFAILURE*/, NULL, &ullValue, &cbSize);
        if (ERROR_SUCCESS != ls)
        {
            return false;
        }

        return ERROR_SUCCESS == ls;
    }

    int64_t _GetRegQword(HKEY hKey, const _tstring& lpSubKey, const _tstring& lpValueName)
    {
        int64_t ullResult = 0;
        (void)_GetRegQword(hKey, lpSubKey, lpValueName, ullResult);
        return ullResult;
    }

    bool _GetNtVersionNumbers(PNTVERSIONNUMBERS_INFO pNtVerInfo)
    {
        return _RtlGetNtVersionNumbers(&pNtVerInfo->dwMajor, &pNtVerInfo->dwMinor, &pNtVerInfo->dwBuild);
    }

    bool _GetVersion(RTL_OSVERSIONINFOEXW* pVerInfo)
    {
        return _RtlGetVersion(pVerInfo);
    }

    bool _GetNtdllVersion(PFILE_VERSION_NUMBERS pVersion)
    {
        return _GetFileProductVersion(_T(R"(C:\Windows\System32\ntdll.dll)"), pVersion);
    }

    _tstring _TimestampToString(int64_t timestamp, bool bHasDate/* = true*/)
    {
        TCHAR szBuf[MAX_PATH] = { 0 };
        SYSTEMTIME st = { 0 };
        FILETIME ftFile = { 0 };
        FILETIME ftLocal = { 0 };

        timestamp = timestamp * 10000 + 116444736000000000;

        ftFile.dwLowDateTime = timestamp & 0xFFFFFFFF;
        ftFile.dwHighDateTime = timestamp >> 32;

        ::FileTimeToLocalFileTime(&ftFile, &ftLocal);
        ::FileTimeToSystemTime(&ftLocal, &st);

        if (bHasDate)
        {
            ::StringCchPrintf(szBuf, _countof(szBuf),
                _T("%04d-%02d-%02d %02d:%02d:%02d.%d"),
                st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds
            );
        }
        else
        {
            ::StringCchPrintf(szBuf, _countof(szBuf),
                _T("%02d:%02d:%02d.%d"), st.wHour, st.wMinute, st.wSecond, st.wMilliseconds
            );
        }

        return szBuf;
    }

    _tstring _GetDisplayVersion()
    {
        return _GetRegString(HKEY_LOCAL_MACHINE, _T(R"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)"), _T("DisplayVersion"));
    }

    DWORD _GetUpdateBuildRevision()
    {
        return _GetRegDword(HKEY_LOCAL_MACHINE, _T(R"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)"), _T("UBR"));
    }
    DWORD _GetInstallDate()
    {
        return _GetRegDword(HKEY_LOCAL_MACHINE, _T(R"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)"), _T("InstallDate"));
    }

    int64_t _GetInstallTime()
    {
        return _GetRegQword(HKEY_LOCAL_MACHINE, _T(R"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)"), _T("InstallTime"));
    }

    bool IsWindows10_Or_11()
    {
        NTVERSIONNUMBERS_INFO verInfo = { 0 };
        _GetNtVersionNumbers(&verInfo);

        if (!(10 == verInfo.dwMajor && 0 == verInfo.dwMinor))
        {
            return false;
        }

        return true;
    }

    bool IsWindows10()
    {
        NTVERSIONNUMBERS_INFO verInfo = { 0 };
        _GetNtVersionNumbers(&verInfo);

        if (!(10 == verInfo.dwMajor && 0 == verInfo.dwMinor))
        {
            return false;
        }

        return verInfo.dwBuild >= 10240 && verInfo.dwBuild < 22000;
    }

    bool IsWindows11()
    {
        NTVERSIONNUMBERS_INFO verInfo = { 0 };
        _GetNtVersionNumbers(&verInfo);

        if (!(10 == verInfo.dwMajor && 0 == verInfo.dwMinor))
        {
            return false;
        }

        return verInfo.dwBuild >= 22000;
    }

    bool IsWindows11_24H2()
    {
        NTVERSIONNUMBERS_INFO verInfo = { 0 };
        _GetNtVersionNumbers(&verInfo);

        if (!(10 == verInfo.dwMajor && 0 == verInfo.dwMinor))
        {
            return false;
        }

        return verInfo.dwBuild >= 26100;
    }

    bool IsWindows11_23H2()
    {
        NTVERSIONNUMBERS_INFO verInfo = { 0 };
        _GetNtVersionNumbers(&verInfo);

        if (!(10 == verInfo.dwMajor && 0 == verInfo.dwMinor))
        {
            return false;
        }

        return verInfo.dwBuild >= 22631 && verInfo.dwBuild < 26100;
    }

    bool IsWindows11_22H2()
    {
        NTVERSIONNUMBERS_INFO verInfo = { 0 };
        _GetNtVersionNumbers(&verInfo);

        if (!(10 == verInfo.dwMajor && 0 == verInfo.dwMinor))
        {
            return false;
        }

        return verInfo.dwBuild >= 22621 && verInfo.dwBuild < 22631;
    }

    bool IsWindows11_21H2()
    {
        NTVERSIONNUMBERS_INFO verInfo = { 0 };
        _GetNtVersionNumbers(&verInfo);

        if (!(10 == verInfo.dwMajor && 0 == verInfo.dwMinor))
        {
            return false;
        }

        return verInfo.dwBuild >= 22000 && verInfo.dwBuild < 22621;
    }

    SYSTEMTIME _TimestampToSystemTime(int64_t timestamp)
    {
        SYSTEMTIME st = { 0 };
        FILETIME ftFile = { 0 };
        FILETIME ftLocal = { 0 };

        timestamp = timestamp * 10000 + 116444736000000000;

        ftFile.dwLowDateTime = timestamp & 0xFFFFFFFF;
        ftFile.dwHighDateTime = timestamp >> 32;

        ::FileTimeToLocalFileTime(&ftFile, &ftLocal);
        ::FileTimeToSystemTime(&ftLocal, &st);

        return st;
    }

    OS_VERSION_INFO GetOSVersionInfo()
    {
        OS_VERSION_INFO osVersion;

        // 获取系统版本号(不含次构建版本号)
        _RtlGetNtVersionNumbers(&osVersion.osVersion.dwMajor, &osVersion.osVersion.dwMinor, &osVersion.osVersion.dwBuildMajor);

        // 显示版本
        osVersion.strDisplayVersion = _GetDisplayVersion();

        // 更新构建修订
        osVersion.osVersion.dwBuildMinor = _GetUpdateBuildRevision();

        // 安装日期
        int64_t installDate = _GetInstallDate();
        osVersion.stInstallDate = _TimestampToSystemTime(installDate * 1000);
        osVersion.strInstallDate = _TimestampToString(installDate * 1000, true);

        // ntdll文件版本号
        _GetNtdllVersion(&osVersion.ntdllVersion);

        // 系统产品类型 
        osVersion.osVersionEx.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
        _RtlGetVersion((PRTL_OSVERSIONINFOEXW)&osVersion.osVersionEx);

        _RtlGetProductInfo(osVersion.osVersionEx.dwMajorVersion,
            osVersion.osVersionEx.dwMinorVersion,
            osVersion.osVersionEx.wServicePackMajor,
            osVersion.osVersionEx.wServicePackMinor,
            &osVersion.dwProductType
        );

        SYSTEM_INFO si = { 0 };
        GetNativeSystemInfo(&si);

        if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)
        {
            bool fX64 = true;
        }


        return osVersion;
    }
}

main.cpp

#include "Win32Utils/COSVersion.h"

int _tmain(int argc, LPCTSTR argv[])
{
    setlocale(LC_ALL, "");

    COSVersion::OS_VERSION_INFO osVersion = COSVersion::GetOSVersionInfo();

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值