COSVersion.h
cpp
#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
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;
class COSVersion
{
public:
// 获取操作系统版本信息
static OS_VERSION_INFO GetOSVersionInfo();
// 系统版本检查
static bool IsWindows10Or11();
static bool IsWindows10();
static bool IsWindows11();
static bool IsWindows11_24H2();
static bool IsWindows11_23H2();
static bool IsWindows11_22H2();
static bool IsWindows11_21H2();
private:
// 获取 Ntdll.dll 版本号
static bool _GetNtdllVersion(PFILE_VERSION_NUMBERS pVersion);
// 获取操作系统显示名
static _tstring _GetDisplayVersion();
// 获取更新构建修订版本号
static DWORD _GetUpdateBuildRevision();
// 获取安装日期
static DWORD _GetInstallDate();
static int64_t _GetInstallTime();
// 获取版本号信息
static bool _GetNtVersionNumbers(PNTVERSIONNUMBERS_INFO pNtVerInfo);
// 获取版本信息
static bool _GetVersion(RTL_OSVERSIONINFOEXW* pVerInfo);
// 获取版本号信息
static bool _RtlGetNtVersionNumbers(DWORD* pMajor, DWORD* pMinor, DWORD* pBuild);
// 获取版本信息
static bool _RtlGetVersion(PRTL_OSVERSIONINFOEXW lpVersionInformation);
// 获取产品版本
// 最低受支持的客户端 Windows Vista [仅限桌面应用]
// 最低受支持的服务器 Windows Server 2008 [仅限桌面应用]
static bool _RtlGetProductInfo(DWORD dwOSMajor, DWORD dwOSMinor, DWORD dwSpMajor, DWORD dwSpMinor, PDWORD pdwProductType);
// 获取文件产品版本号
static bool _GetFileProductVersion(const _tstring& strFile, PFILE_VERSION_NUMBERS pVersion);
// 注册表操作
static bool _GetRegString(HKEY hKey, const _tstring& lpSubKey, const _tstring& lpValueName, _tstring& strValue);
static _tstring _GetRegString(HKEY hKey, const _tstring& lpSubKey, const _tstring& lpValueName);
static bool _GetRegDword(HKEY hKey, const _tstring& lpSubKey, const _tstring& lpValueName, DWORD& dwValue);
static DWORD _GetRegDword(HKEY hKey, const _tstring& lpSubKey, const _tstring& lpValueName);
static bool _GetRegQword(HKEY hKey, const _tstring& lpSubKey, const _tstring& lpValueName, int64_t& ullValue);
static int64_t _GetRegQword(HKEY hKey, const _tstring& lpSubKey, const _tstring& lpValueName);
// 时间戳操作
static _tstring _TimestampToString(int64_t timestamp, bool bHasDate = true);
static SYSTEMTIME _TimestampToSystemTime(int64_t timestamp);
};
COSVersion.cpp
cpp
#include "COSVersion.h"
#include <versionhelpers.h>
#include <strsafe.h>
#include <map>
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
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 COSVersion::_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 COSVersion::_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 COSVersion::_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 COSVersion::_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 COSVersion::_GetRegString(HKEY hKey, const _tstring& lpSubKey, const _tstring& lpValueName)
{
_tstring strResult;
(void)_GetRegString(hKey, lpSubKey, lpValueName, strResult);
return strResult;
}
bool COSVersion::_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 COSVersion::_GetRegDword(HKEY hKey, const _tstring& lpSubKey, const _tstring& lpValueName)
{
DWORD dwResult = 0;
(void)_GetRegDword(hKey, lpSubKey, lpValueName, dwResult);
return dwResult;
}
bool COSVersion::_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 COSVersion::_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 COSVersion::_GetRegQword(HKEY hKey, const _tstring& lpSubKey, const _tstring& lpValueName)
{
int64_t ullResult = 0;
(void)_GetRegQword(hKey, lpSubKey, lpValueName, ullResult);
return ullResult;
}
bool COSVersion::_GetNtVersionNumbers(PNTVERSIONNUMBERS_INFO pNtVerInfo)
{
return _RtlGetNtVersionNumbers(&pNtVerInfo->dwMajor, &pNtVerInfo->dwMinor, &pNtVerInfo->dwBuild);
}
bool COSVersion::_GetVersion(RTL_OSVERSIONINFOEXW* pVerInfo)
{
return _RtlGetVersion(pVerInfo);
}
bool COSVersion::_GetNtdllVersion(PFILE_VERSION_NUMBERS pVersion)
{
return _GetFileProductVersion(_T(R"(C:\Windows\System32\ntdll.dll)"), pVersion);
}
_tstring COSVersion::_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 COSVersion::_GetDisplayVersion()
{
return _GetRegString(HKEY_LOCAL_MACHINE, _T(R"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)"), _T("DisplayVersion"));
}
DWORD COSVersion::_GetUpdateBuildRevision()
{
return _GetRegDword(HKEY_LOCAL_MACHINE, _T(R"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)"), _T("UBR"));
}
DWORD COSVersion::_GetInstallDate()
{
return _GetRegDword(HKEY_LOCAL_MACHINE, _T(R"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)"), _T("InstallDate"));
}
int64_t COSVersion::_GetInstallTime()
{
return _GetRegQword(HKEY_LOCAL_MACHINE, _T(R"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)"), _T("InstallTime"));
}
bool COSVersion::IsWindows10Or11()
{
NTVERSIONNUMBERS_INFO verInfo = { 0 };
COSVersion::_GetNtVersionNumbers(&verInfo);
if (!(10 == verInfo.dwMajor && 10 == verInfo.dwMinor))
{
return false;
}
return true;
}
bool COSVersion::IsWindows10()
{
NTVERSIONNUMBERS_INFO verInfo = { 0 };
COSVersion::_GetNtVersionNumbers(&verInfo);
if (!(10 == verInfo.dwMajor && 10 == verInfo.dwMinor))
{
return false;
}
return verInfo.dwBuild >= 10240 && verInfo.dwBuild < 22000;
}
bool COSVersion::IsWindows11()
{
NTVERSIONNUMBERS_INFO verInfo = { 0 };
COSVersion::_GetNtVersionNumbers(&verInfo);
if (!(10 == verInfo.dwMajor && 10 == verInfo.dwMinor))
{
return false;
}
return verInfo.dwBuild >= 22000;
}
bool COSVersion::IsWindows11_24H2()
{
NTVERSIONNUMBERS_INFO verInfo = { 0 };
COSVersion::_GetNtVersionNumbers(&verInfo);
if (!(10 == verInfo.dwMajor && 10 == verInfo.dwMinor))
{
return false;
}
return verInfo.dwBuild >= 26100;
}
bool COSVersion::IsWindows11_23H2()
{
NTVERSIONNUMBERS_INFO verInfo = { 0 };
COSVersion::_GetNtVersionNumbers(&verInfo);
if (!(10 == verInfo.dwMajor && 10 == verInfo.dwMinor))
{
return false;
}
return verInfo.dwBuild >= 22631 && verInfo.dwBuild < 26100;
}
bool COSVersion::IsWindows11_22H2()
{
NTVERSIONNUMBERS_INFO verInfo = { 0 };
COSVersion::_GetNtVersionNumbers(&verInfo);
if (!(10 == verInfo.dwMajor && 10 == verInfo.dwMinor))
{
return false;
}
return verInfo.dwBuild >= 22621 && verInfo.dwBuild < 22631;
}
bool COSVersion::IsWindows11_21H2()
{
NTVERSIONNUMBERS_INFO verInfo = { 0 };
COSVersion::_GetNtVersionNumbers(&verInfo);
if (!(10 == verInfo.dwMajor && 10 == verInfo.dwMinor))
{
return false;
}
return verInfo.dwBuild >= 22000 && verInfo.dwBuild < 22621;
}
SYSTEMTIME COSVersion::_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 COSVersion::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
cpp
#include "Win32Utils/COSVersion.h"
int _tmain(int argc, LPCTSTR argv[])
{
setlocale(LC_ALL, "");
OS_VERSION_INFO osVersion = COSVersion::GetOSVersionInfo();
return 0;
}