开发者

Get OS in c++ win32 for all versions of win?

How to get the OS vers开发者_如何学Pythonion for all windows, at least the name for win95,98,me,xp,vista,7?

Im using visual c++ 2010 and I want to include this feature in a pure win32 app.


How about something like this:

#include <windows.h>
#include <string>
#include <lm.h>
#pragma comment(lib, "netapi32.lib")

bool GetWinMajorMinorVersion(DWORD& major, DWORD& minor)
{
    bool bRetCode = false;
    LPBYTE pinfoRawData = 0;
    if (NERR_Success == NetWkstaGetInfo(NULL, 100, &pinfoRawData))
    {
        WKSTA_INFO_100* pworkstationInfo = (WKSTA_INFO_100*)pinfoRawData;
        major = pworkstationInfo->wki100_ver_major;
        minor = pworkstationInfo->wki100_ver_minor;
        ::NetApiBufferFree(pinfoRawData);
        bRetCode = true;
    }
    return bRetCode;
}


std::string GetWindowsVersionString()
{
    std::string     winver;
    OSVERSIONINFOEX osver;
    SYSTEM_INFO     sysInfo;
    typedef void(__stdcall *GETSYSTEMINFO) (LPSYSTEM_INFO);

    __pragma(warning(push))
    __pragma(warning(disable:4996))
    memset(&osver, 0, sizeof(osver));
    osver.dwOSVersionInfoSize = sizeof(osver);
    GetVersionEx((LPOSVERSIONINFO)&osver);
    __pragma(warning(pop))
    DWORD major = 0;
    DWORD minor = 0;
    if (GetWinMajorMinorVersion(major, minor))
    {
        osver.dwMajorVersion = major;
        osver.dwMinorVersion = minor;
    }
    else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 2)
    {
        OSVERSIONINFOEXW osvi;
        ULONGLONG cm = 0;
        cm = VerSetConditionMask(cm, VER_MINORVERSION, VER_EQUAL);
        ZeroMemory(&osvi, sizeof(osvi));
        osvi.dwOSVersionInfoSize = sizeof(osvi);
        osvi.dwMinorVersion = 3;
        if (VerifyVersionInfoW(&osvi, VER_MINORVERSION, cm))
        {
            osver.dwMinorVersion = 3;
        }
    }

    GETSYSTEMINFO getSysInfo = (GETSYSTEMINFO)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "GetNativeSystemInfo");
    if (getSysInfo == NULL)  getSysInfo = ::GetSystemInfo;
    getSysInfo(&sysInfo);

    if (osver.dwMajorVersion == 10 && osver.dwMinorVersion >= 0 && osver.wProductType != VER_NT_WORKSTATION)  winver = "Windows 10 Server";
    if (osver.dwMajorVersion == 10 && osver.dwMinorVersion >= 0 && osver.wProductType == VER_NT_WORKSTATION)  winver = "Windows 10";
    if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 3 && osver.wProductType != VER_NT_WORKSTATION)  winver = "Windows Server 2012 R2";
    if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 3 && osver.wProductType == VER_NT_WORKSTATION)  winver = "Windows 8.1";
    if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 2 && osver.wProductType != VER_NT_WORKSTATION)  winver = "Windows Server 2012";
    if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 2 && osver.wProductType == VER_NT_WORKSTATION)  winver = "Windows 8";
    if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 1 && osver.wProductType != VER_NT_WORKSTATION)  winver = "Windows Server 2008 R2";
    if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 1 && osver.wProductType == VER_NT_WORKSTATION)  winver = "Windows 7";
    if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 0 && osver.wProductType != VER_NT_WORKSTATION)  winver = "Windows Server 2008";
    if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 0 && osver.wProductType == VER_NT_WORKSTATION)  winver = "Windows Vista";
    if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 2 && osver.wProductType == VER_NT_WORKSTATION
        &&  sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)  winver = "Windows XP x64";
    if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 2)   winver = "Windows Server 2003";
    if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 1)   winver = "Windows XP";
    if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 0)   winver = "Windows 2000";
    if (osver.dwMajorVersion < 5)   winver = "unknown";

    if (osver.wServicePackMajor != 0)
    {
        std::string sp;
        char buf[128] = { 0 };
        sp = " Service Pack ";
        sprintf_s(buf, sizeof(buf), "%hd", osver.wServicePackMajor);
        sp.append(buf);
        winver += sp;
    }

    return winver;
}


Use GetVersionEx http://msdn.microsoft.com/en-us/library/ms724451%28v=VS.85%29.aspx


I had a similar problem. Here is some code with Win 11 support. It won't work for server versions, but it is easy to implement add this feature (just another mapping for servers).

 // To Workaround Win 10 problem for User Mode VerifyVersionInfo
bool VerifyWindowsVersionInfo(PRTL_OSVERSIONINFOEXW versionInfo, ULONG typeMask, ULONGLONG conditionMask)
{
    HMODULE hMod = nullptr;
    if ((TRUE != ::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, L"ntdll.dll", &hMod)) || !hMod)
        return false;

    typedef NTSTATUS(WINAPI* _RtlVerifyVersionInfo)(PRTL_OSVERSIONINFOEXW, ULONG, ULONGLONG);
    const auto RtlVerifyVersionInfo =
        reinterpret_cast<_RtlVerifyVersionInfo>(::GetProcAddress(hMod, "RtlVerifyVersionInfo"));

    if (!RtlVerifyVersionInfo)
        return false;

    return NT_SUCCESS(RtlVerifyVersionInfo(versionInfo, typeMask, conditionMask));
}

bool IsWindowsVersionOrGreater(int wMajorVersion, int wMinorVersion, int wBuildNumber, int wServicePackMajor)
{
    RTL_OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 };
    osvi.dwMajorVersion = wMajorVersion;
    osvi.dwMinorVersion = wMinorVersion;
    osvi.dwBuildNumber = wBuildNumber;
    osvi.wServicePackMajor = static_cast<WORD>(wServicePackMajor);

    DWORDLONG dwlConditionMask = 0;
    VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
    VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
    VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
    VER_SET_CONDITION(dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);

    return VerifyWindowsVersionInfo(&osvi,
        VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER | VER_SERVICEPACKMAJOR,
        dwlConditionMask);

}

std::wstring GetVerbalOsVersion()
{
    // see https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms724832(v=vs.85).aspx for details
    using OsMajorVersion = int;
    using OsMinorVersion = int;
    using OsBuildVersion = int;
    using OsServicePackMajorVersion = int;

    using VersionStrWithNumberPair =
        std::pair<std::wstring, std::tuple<OsMajorVersion, OsMinorVersion, OsBuildVersion, OsServicePackMajorVersion>>;


    const auto win11BuildNumber = 22000;

    const std::vector<VersionStrWithNumberPair> winVersionMapping = {
        {L"Windows 11 ",
         std::make_tuple(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), win11BuildNumber, 0)},
        {L"Windows 10 ", std::make_tuple(HIBYTE(_WIN32_WINNT_WIN10), LOBYTE(_WIN32_WINNT_WIN10), 0, 0)},

        {L"Windows 8.1", std::make_tuple(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0, 0)},
        {L"Windows 8 ", std::make_tuple(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0, 0)},

        {L"Windows 7  Service Pack 1", std::make_tuple(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0, 1)},
        {L"Windows 7 ", std::make_tuple(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0, 0)},

        {L"Windows Vista Service Pack 2",
         std::make_tuple(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0, 2)},
        {L"Windows Vista Service Pack 1",
         std::make_tuple(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0, 1)},
        {L"Windows Vista", std::make_tuple(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0, 0)},

        {L"Windows XP  Service Pack 3",
         std::make_tuple(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0, 3)},
        {L"Windows XP Service Pack 2",
         std::make_tuple(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0, 2)},
        {L"Windows XP Service Pack 1",
         std::make_tuple(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0, 1)},
        {L"Windows XP ", std::make_tuple(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0, 0)} };

    const auto it = std::find_if(std::begin(winVersionMapping),
        std::end(winVersionMapping),
        [](const VersionStrWithNumberPair& el)
        {
            return IsWindowsVersionOrGreater(std::get<0>(el.second),
                std::get<1>(el.second),
                std::get<2>(el.second),
                std::get<3>(el.second));
        });

    if (it == std::end(winVersionMapping))
        return L"Unknown windows version";

    return it->first;
}


Take a look at the MSDN article Getting the System Version

While the article only mentions currently supported Windows versions, see this knowledge base article for the numbers you'll see in the OSVERSIONINFO structure for Win 95, 98 etc.


It all depends on why you need to know OS version:

  • To use certain feature that may not be available in older OS. In this case I would strongly suggest checking if the API itself is available using LoadLibrary and GetProcAddress functions. Otherwise, I guess you can dynamically import RtlGetVersion from ntdll.dll and use it, but again, there're too many ways it can return inaccurate information (the ones that come to mind are compatibility mode and API trampolines that can be installed by malware, AVP, and even OS itself.)

  • For display purposes only. (ex: in About window for your app, or to include it in your diagnostic event log, etc.) In this case a quick and easy hack is to read it as text from the System Registry:

Get OS in c++ win32 for all versions of win?

The downside of this approach though, is that the names and numbers can be localized for the end-user's system.

Use the following key that is available since Windows XP:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion

and its following REG_SZ (or string) values:

  • ProductName = for OS name
  • CurrentVersion = for OS version
  • BuildLab = for full build number
  • BuildLabEx = extended build number (available since Windows 7)
  • ReleaseId = Release number (available since Windows 10)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜