11

I am making an app to OS specific but I can't seem to narrow down Windows 10, it comes up as Windows 8. I have tested it on Window 10 Pro and the outcome is Major: 6 Min:2. Is there another way to check if it's windows 10 more efficiently?

EDIT: Found a properly working API RtlGetVersion() works for all OS's properly!

#include "windows.h"
#include <iostream>
using namespace std;
BOOL EqualsMajorVersion(DWORD majorVersion)
{
OSVERSIONINFOEX osVersionInfo;
::ZeroMemory(&osVersionInfo, sizeof(OSVERSIONINFOEX));
osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
osVersionInfo.dwMajorVersion = majorVersion;
ULONGLONG maskCondition = ::VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
return ::VerifyVersionInfo(&osVersionInfo, VER_MAJORVERSION, maskCondition);
}
BOOL EqualsMinorVersion(DWORD minorVersion)
{
OSVERSIONINFOEX osVersionInfo;
::ZeroMemory(&osVersionInfo, sizeof(OSVERSIONINFOEX));
osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
osVersionInfo.dwMinorVersion = minorVersion;
ULONGLONG maskCondition = ::VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL);
return ::VerifyVersionInfo(&osVersionInfo, VER_MINORVERSION, maskCondition);
}
int main()
{
    if (EqualsMajorVersion(7) && EqualsMinorVersion(1))
        printf("Maj:7 Min:1");
    else if (EqualsMajorVersion(7) && EqualsMinorVersion(0))
        printf("Maj:7 Min:0");
    else if (EqualsMajorVersion(6) && EqualsMinorVersion(7))
        printf("Maj:6 Min:7");
    else if (EqualsMajorVersion(6) && EqualsMinorVersion(6))
        printf("Maj:6 Min:6");
    else if (EqualsMajorVersion(6) && EqualsMinorVersion(5))
        printf("Maj:6 Min:5");
    else if (EqualsMajorVersion(6) && EqualsMinorVersion(4))
        printf("Maj:6 Min:4");
    else if (EqualsMajorVersion(6) && EqualsMinorVersion(3))
        printf("Maj:6 Min:3");
    else if (EqualsMajorVersion(6) && EqualsMinorVersion(2))
        printf("Maj:6 Min:2");
    else if (EqualsMajorVersion(6) && EqualsMinorVersion(1))
        printf("Maj:6 Min:1");
    else if (EqualsMajorVersion(6) && EqualsMinorVersion(0))
        printf("Maj:6 Min:0");
    else if (EqualsMajorVersion(5) && EqualsMinorVersion(2))
        printf("Maj:5 Min:2");
    else if (EqualsMajorVersion(5) && EqualsMinorVersion(1))
        printf("Maj:5 Min:1");
    else
        printf("OS not on list...");
    getchar();
}
demonplus
  • 5,613
  • 12
  • 49
  • 68
user3732111
  • 151
  • 1
  • 2
  • 8
  • 1
    Something to think about: Microsoft has said newer versions of Windows will emulate older ones as the version that the program manifest claims it was built with. Whether this is done with compatibility libraries or virtual machines is open for the future. But because of that I am not sure if you can find the OS version from an application anymore. – Zan Lynx Aug 25 '15 at 00:50
  • How about using [`GetVersionEx`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724451%28v=vs.85%29.aspx)? That also allows you to cache the structure, and you only need to call it once. – Some programmer dude Aug 25 '15 at 00:59
  • 1
    Hey I found what I remembered: "Applications not manifested for Windows 8.1 or Windows 10 will return the Windows 8 OS version value (6.2). Once an application is manifested for a given operating system version, GetVersionEx will always return the version that the application is manifested for in future releases." -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms724451%28v=vs.85%29.aspx – Zan Lynx Aug 25 '15 at 02:15
  • I have to wonder what you plan to do with `RtlGetVersion`. In the future with the 2025 version of Windows, if Microsoft keeps with their plan, your program will be running in a virtual machine. Asking for the real version of Windows will be like asking for the host OS of the virtual machine. Meaningless information since none of the APIs, device drivers, file system, etc will look like the 2025 Windows. – Zan Lynx Aug 31 '15 at 19:32
  • This question is a duplicate of http://stackoverflow.com/questions/36543301/detecting-windows-10-version/36543774#36543774. In there you'll find a proper implementation too. – Stefano Buora Mar 17 '17 at 15:56
  • 1
    @ZanLynx one reason could be to _show_ the current Windows version without putting up with the "niceties" the `GetVersionEx` offers, especially with the deprecation warning and the "unique" numbering which is really unhelpful to end-users. I can understand MS was annoyed by people getting version _checks_ wrong. But there are more uses for retrieving the Windows version than version _checks_. – 0xC0000022L Oct 15 '19 at 20:44

4 Answers4

15

This is pretty ironic, but...

BOOL WINAPI IsWindows10OrGreater(void);

Docs here.

Edit: The geniuses from Redmond appear to have problems thinking with prototypes, or in other words, the OP gets an undefined symbol error as stated in the comments. There's also this function:

BOOL WINAPI IsWindowsVersionOrGreater(
    WORD wMajorVersion,
    WORD wMinorVersion,
    WORD wServicePackMajor
);

And, for Windows 10, wMajorVersion, wMinorVersion, and wServicePackMajor appear to be, respectively, 10, 0, and 0.

Docs for that function here.

Second edit: It's official: IsWindowsVersionOrGreater() and GetVersionEx() are broken from 8.1 onwards. Use IsWindowsXXXOrGreater() always instead, where XXX can be XP, XPSP1, XPSP2, XPSP3, Vista, VistaSP1, VistaSP2, 7, 7SP1, 8, 8Point1, 10, or Server.

3442
  • 8,248
  • 2
  • 19
  • 41
  • The API looks great but it's not defined, I am using VS2015 compiler platform and it's still not working. – user3732111 Aug 25 '15 at 00:54
  • Did he include VersionHelpers.h ? The docs say you have to use that header file. – Zan Lynx Aug 25 '15 at 02:16
  • Yes I VersionHelpers.h but it's still not declared, in VS 2015? I have also looked into your "Targeting your application for Windows". – user3732111 Aug 25 '15 at 03:03
  • IsWindowsVersionOrGreater() gives false in Win10 system. And GetVersionEx gives major and minor version as 6 and 2. Both not working – cosmoloc Apr 26 '16 at 06:00
  • @testit: Not sure if the functions are broken for Win10. However, [it definitively can't be major version 6](http://www.winbeta.org/news/microsoft-confirms-windows-10-kernel-version-bump-100-asks-developers-start-updating) if the functions indeed work. – 3442 Apr 28 '16 at 02:53
  • @testit: Indeed, it seems [`GetVersionEx()` is broken in 8.1+](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724451(v=vs.85).aspx). – 3442 Apr 28 '16 at 02:55
8

Following worked for me :

.
.
.
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
.
.
.

typedef void (WINAPI * RtlGetVersion_FUNC) (OSVERSIONINFOEXW *);
BOOL GetVersion(OSVERSIONINFOEX * os) {
    HMODULE hMod;
    RtlGetVersion_FUNC func;
#ifdef UNICODE
    OSVERSIONINFOEXW * osw = os;
#else
    OSVERSIONINFOEXW o;
    OSVERSIONINFOEXW * osw = &o;
#endif

    hMod = LoadLibrary(TEXT("ntdll.dll"));
    if (hMod) {
        func = (RtlGetVersion_FUNC)GetProcAddress(hMod, "RtlGetVersion");
        if (func == 0) {
            FreeLibrary(hMod);
            return FALSE;
        }
        ZeroMemory(osw, sizeof (*osw));
        osw->dwOSVersionInfoSize = sizeof (*osw);
        func(osw);
#ifndef UNICODE
        os->dwBuildNumber = osw->dwBuildNumber;
        os->dwMajorVersion = osw->dwMajorVersion;
        os->dwMinorVersion = osw->dwMinorVersion;
        os->dwPlatformId = osw->dwPlatformId;
        os->dwOSVersionInfoSize = sizeof (*os);
        DWORD sz = sizeof (os->szCSDVersion);
        WCHAR * src = osw->szCSDVersion;
        unsigned char * dtc = (unsigned char *)os->szCSDVersion;
        while (*src)
            * Dtc++ = (unsigned char)* src++;
        *Dtc = '\ 0';
#endif

    } else
        return FALSE;
    FreeLibrary(hMod);
    return TRUE;
}

.
.
.

//check win10
void mymethod() {

OSVERSIONINFOEX os;

    if (GetVersion(&os) == TRUE && os.dwMajorVersion == 10)
    {
        isWin10 = TRUE;
    }

}

Ref. : ( http://yamatyuu.net/computer/program/vc2013/rtlgetversion/index.html )

cosmoloc
  • 2,884
  • 5
  • 29
  • 48
  • There are a little defects in this implementation, please look at the accepted answer in http://stackoverflow.com/questions/36543301/detecting-windows-10-version/36543774#36543774. One example is the return type of RtlGetVersion: is not void, as well as the trick with the pointer on OSVERSIONINFOEXW/A is not clean. – Stefano Buora Mar 17 '17 at 15:58
  • I've searched so much for a way getting the OS version (and not just if it is greater that a specific version). i needed the whole details, such as build number, major and minor version, and this is the only code that worked for me! Thanks! – RK Coder Sep 07 '17 at 11:24
  • There is an issue in your code with upper and lower case `Dtc` / `dtc`. – kuga Jul 23 '19 at 12:00
3

UPDATE: checked win7, win8.1 and win10. now everything determinating. So code:

#include <windows.h>
#include <VersionHelpers.h>
#include <string>

std::string getWinVerion() {

OSVERSIONINFO info;
ZeroMemory(&info, sizeof(OSVERSIONINFO));
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

GetVersionEx(&info);

std::string version = std::to_string(info.dwMajorVersion);
version.append(".").append(std::to_string(info.dwMinorVersion));

if (IsWindows7SP1OrGreater()) {
    if (version == "6.1")
        return "6.1";
}

if (IsWindows8Point1OrGreater())
    return "6.3";
else
    return "10.0";
}
Mr.T
  • 33
  • 4
2

That is true , the only way to detect if this is Windows 10 is by using

BOOL WINAPI IsWindows10OrGreater(void);

Although you need to have the latest SDK using Visual Studio 2015. Be aware that

BOOL WINAPI IsWindowsVersionOrGreater(
WORD wMajorVersion,
WORD wMinorVersion,
WORD wServicePackMajor);

is NOT working on Windows 10, likewise the :

BOOL WINAPI GetVersionEx( _Inout_ LPOSVERSIONINFO lpVersionInfo);

Which is returning 6.2 or 6.3 sometimes. (Fully depricated on Windows 10).

igoutas
  • 135
  • 2
  • 14