Click here to Skip to main content
15,884,047 members
Articles / Desktop Programming / Win32

Part1: Overcoming Windows 8.1's deprecation of GetVersionEx and GetVersion APIs

Rate me:
Please Sign up or sign in to vote.
4.73/5 (18 votes)
6 Nov 2013CPOL5 min read 143.5K   41   31
GetWindows Version on Windows 8.1

Introduction

Starting With Windows 8.1 you can no longer use a block of code that looks like this.

C++
OSVERSIONINFOEX  versionInfo;
   versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
OSVERSIONINFO*  pVersionInfo = (POSVERSIONINFO)&versionInfo;   
if(::GetVersionEx(pVersionInfo))
{
  wcout<<_T("MajorVersion:")<<versionInfo.dwMajorVersion<<endl;
  wcout<<_T("MinorVersion:")<<versionInfo.dwMinorVersion<<endl;
}

Please Look Update Section for better ways to achieve this.

Background

I recently upgraded my development box to Windows8.1 from Windows 8. I was trying to log the version of Windows to the product’s logfile and suddenly I am faced with an issue where the Windows Version I retrieve from GetVersionEx API is actually associated with Windows 8. That is I expected Version 6.3 = Windows8.1 but I was getting Version 6.2 = Windows8. It was impossible to believe such an important API would be malfunctioning, so using Hyper-V I created a Windows8.1 Image from scratch to make sure this was not an issue associated with Windows Upgrade. But the issue persisted, so I upgraded to Visual Studio 2013, hoping that would solve the issue. The issue persisted and that’s when I found the following Article on msdn describing Microsoft’s deprecation of GetVersionEx API. Actually Visual 2013 Marks GetVersionEx and GetVersion APIs as deprecated and throws an Error if you reference it. Moreover .Net Framework’s API to retrieve OS version is also “deprecated” (returning inaccurate data). Let’s just say this move is a big surprise by Microsoft. How is a Web Browser Supposed to Report an accurate User Agent? how is a product supposed to report accurate Telemetry Data without obtaining Operating System version. In My particular case, how am I supposed to log the version of OS in Diagnostic log files that customer would be shipping to me? All these Questions led me to believe that Microsoft's Version Helper API that Ships with Windows 8.1 SDK are not sufficient. But they do provide a very good clue that VerifyVersionInfo can indeed be used to fill the void.

I decided against doing dynamic LoadLibrary and GetProcAddress Technique to use "undocumented" from Kernelbase.dll,Kernel32.dll, shell32.dll or shcore.dll and using internal APIs there. It also seemed not the best idea to load the version of Windows from someplace in Registry. Another approach would have been to load any key dll that resides in %systemroot%\ system32 folder and then use an API such as DllGetVersion to retrieve Product Version from that DLL. but I did not like that idea either because a dll itself and can get hotfixed and potentially have different version (I have not seen this occur).

Using the code

Disclaimer: This is not Production-ready code!

If you look close at VerifyVersionInfo and its sister API VerSetConditionMask there is useful flag called VER_EQUAL.

We can verify the System is Running Windows 8.1 by using VER_EQUAL FLAG.

C++
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 _tmain(int argc, _TCHAR* argv[])
{
    if (EqualsMajorVersion(6) && EqualsMinorVersion(3))
    {
        wcout << _T("System is Windows 8.1");
    }
    return 0;
}

That Works and in fact that's very similar to the Mechanism used by VersionHelpers.h From Windows 8.1 SDK.

C++
ERSIONHELPERAPI
IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
{
    OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 };
    DWORDLONG        const dwlConditionMask = VerSetConditionMask(
        VerSetConditionMask(
        VerSetConditionMask(
            0, VER_MAJORVERSION, VER_GREATER_EQUAL),
               VER_MINORVERSION, VER_GREATER_EQUAL),
               VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);

    osvi.dwMajorVersion = wMajorVersion;
    osvi.dwMinorVersion = wMinorVersion;
    osvi.wServicePackMajor = wServicePackMajor;

    return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | 
      VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
}

So You might have noticed Windows Versions have been historically predictable. By That I mean we had Windows 3.0, Windows 3.1, Windows NT, 95(4.0), Windows 2000 (5.0), Windows XP (5.1), .... Windows 7(6.1), ..... , Windows 8.1 (6.3). It's not like previous Version was 100.0 and the next version is 213.0. so it fair to say with a small number of iterations and incrementing of a base known version we should able to get the version of windows that we are running on.

So Here are three More Helper Functions to Get ServicePack and ascertain whether this Windows is Workstation or Windows Server.

C++
BOOL EqualsServicePack(WORD servicePackMajor)
{
    OSVERSIONINFOEX osVersionInfo;
    ::ZeroMemory(&osVersionInfo, sizeof(OSVERSIONINFOEX));
    osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
    osVersionInfo.wServicePackMajor = servicePackMajor;
    ULONGLONG maskCondition = ::VerSetConditionMask(0, VER_SERVICEPACKMAJOR, VER_EQUAL);
    return ::VerifyVersionInfo(&osVersionInfo, VER_SERVICEPACKMAJOR, maskCondition);
}

BOOL EqualsProductType(BYTE productType)
{
    OSVERSIONINFOEX osVersionInfo;
    ::ZeroMemory(&osVersionInfo, sizeof(OSVERSIONINFOEX));
    osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
    osVersionInfo.wProductType = productType;
    ULONGLONG maskCondition = ::VerSetConditionMask(0, VER_PRODUCT_TYPE, VER_EQUAL);
    return ::VerifyVersionInfo(&osVersionInfo, VER_PRODUCT_TYPE, maskCondition);
}

BYTE GetProductType()
{
    if (EqualsProductType(VER_NT_WORKSTATION))
    {
        return VER_NT_WORKSTATION;
    }
    else if (EqualsProductType(VER_NT_SERVER))
    {
        return VER_NT_SERVER;
    }
    else if (EqualsProductType(VER_NT_DOMAIN_CONTROLLER))
    {
        return VER_NT_DOMAIN_CONTROLLER;
    }
    return 0;//unkown
}  

VerifyVersionInfo API was relased on Windows 2000 (Windows 5.0) so we can setup an array that contains known version of Windows back to Windows 200 and use this API to verify them.

C++
struct WindowsNTOSInfo
{
    DWORD dwMajorVersion;
    DWORD dwMinorVersion;
    WORD wServicePackMajor;    
    //const TCHAR * pcszOSDisplayName;
};

struct WindowsNTOSInfoEx :WindowsNTOSInfo
{
    BYTE ProductType;
};

const WindowsNTOSInfo KnownVersionsOfWindows[] =
{
    { 6, 3, 0,   },//win8.1,server2012 r2
    { 6, 2, 0,   },//win8,server2012

    { 6, 1, 1,  },//win7,win2008r2 sp1
    { 6, 1, 0,  },//win7,win2008r2

    { 5, 1, 3,  },//winxp sp3
    { 5, 1, 2,  },//winxp sp2
    { 5, 1, 1,  },//winxp sp1
    { 5, 1, 0,  },//winxp

    { 6, 0, 2,  },//WinVista,server2008 SP2
    { 6, 0, 1,  },//WinVista,Server2008 Sp1
    { 6, 0, 0,  },//WinVista,Server2008

    { 5, 2, 2,  },//Windows Server 2003 Sp2
    { 5, 2, 1,  },//Windows Server 2003 Sp1
    { 5, 2, 0,  },//Windows Server 2003


    { 5, 1, 4,  }, //Windows Server 2000 Sp4
    { 5, 1, 3,  }, //Windows Server 2000 Sp3
    { 5, 1, 2,  }, //Windows Server 2000 Sp2
    { 5, 1, 2,  }, //Windows Server 2000 Sp1
    { 5, 1, 0,  }, //Windows Server 2000
};

const size_t n_KnownVersionofWindows = sizeof(KnownVersionsOfWindows) / sizeof(WindowsNTOSInfo);

So Here the Code that retrieves a known Version of Windows.

C++
bool GetKnownWindowsVersion(WindowsNTOSInfoEx& osInfo)
{
    for (size_t i = 0; i < n_KnownVersionofWindows; i++)
    {
        if (EqualsMajorVersion(KnownVersionsOfWindows[i].dwMajorVersion))
        {
            if (EqualsMinorVersion(KnownVersionsOfWindows[i].dwMinorVersion))
            {
                if (EqualsServicePack(KnownVersionsOfWindows[i].wServicePackMajor))
                {
                    osInfo.dwMajorVersion = KnownVersionsOfWindows[i].dwMajorVersion;
                    osInfo.dwMinorVersion = KnownVersionsOfWindows[i].dwMinorVersion;
                    osInfo.wServicePackMajor = KnownVersionsOfWindows[i].wServicePackMajor;
                    osInfo.ProductType = GetProductType();
                    return true;
                }
            }
        }
    }
    return false;
}

But What about checking unkown version of Windows?

well for that we need to write a few loops and call our helper functions to Verify Major,Minor and Service Pack.

MC++
const DWORD MajorVersion_Start = 6;
const DWORD MinorVersion_Start = 3;
const WORD ServicePackVersion_Start = 1;

const DWORD MajorVersion_Max = 10;
const DWORD MinorVersion_Max = 5;
const WORD ServicePackVersion_Max = 4;

bool GetUnkownVersion(WindowsNTOSInfoEx& osInfo)
{
    DWORD minorVersionCounterSeed = MinorVersion_Start;
    DWORD servicePackCounterSeed = ServicePackVersion_Start;
    //by design, if we can't find the right service pack we will return true;
    for (DWORD majorVersion = MajorVersion_Start; majorVersion <= MajorVersion_Max; majorVersion++)
    {
        if (EqualsMajorVersion(majorVersion))
        {
            for (DWORD minorVersion = minorVersionCounterSeed; 
                    minorVersion <= MinorVersion_Max; minorVersion++)
            {
                if (EqualsMinorVersion(minorVersion))
                {
                    osInfo.dwMajorVersion = majorVersion;
                    osInfo.dwMinorVersion = minorVersion;
                    osInfo.ProductType = GetProductType();
                    for (WORD servicePack = servicePackCounterSeed; 
                           servicePack <= ServicePackVersion_Max; servicePack++)
                    {
                        if (EqualsServicePack(servicePack))
                        {                            
                            osInfo.wServicePackMajor = servicePack;
                            break;
                        }
                    }
                    return true;
                }
                else
                {
                    //reset servicepack version counter to 0 because
                    //we are going to increment our minor version.
                    servicePackCounterSeed = 0;
                }                
            }
        }
        else
        {
            //reset minor version to start from 0 because we are going to increment majorVersion;
            minorVersionCounterSeed = 0;
        }
    }
    return false;
}

So then let's just call the before mentioned code with a function to glue them together.

C++
bool GetWindowsVersion(WindowsNTOSInfoEx& osInfo)
{
    bool capturedWinVersion = GetKnownWindowsVersion(osInfo);
    if (!capturedWinVersion)
    {
        return GetUnkownVersion(osInfo);
    }
    return capturedWinVersion;
}



int _tmain(int argc, _TCHAR* argv[])
{
    WindowsNTOSInfoEx osInfo;
    ::ZeroMemory(&osInfo,sizeof(WindowsNTOSInfoEx));
    if (GetWindowsVersion(osInfo))
    {
        wcout << _T("MajorVersion:") << osInfo.dwMajorVersion << 
            _T(" VersionMinor:") << osInfo.dwMinorVersion << 
            _T(" ServicePackMajor:") << osInfo.wServicePackMajor << 
            _T(" ProductType:") << osInfo.ProductType << endl;
    }
    else
    {
        wcout << _T("Failed to Detect Windows Version") << endl;
    }
    return 0;
}

Note:I have only smoke tested this code on Windows 8.1 and Windows XP SP3.

Points of Interest

Performance: This code is actually quite slow!

It can take anywhere from 5-15 Milliseconds on a Physical System. It took upward of 30 Milliseconds on a Virtual Machine to Execute. Since This API can be can called many times during an Application's life cycle I have included a High Resolution Timer code to measure how lengthy of an operation this is. It appears Calling VerifyVersionInfo is much more expensive the first time. The cost of subsequent calls appear to be significantly less than the First Call.

BuildNumber: I have not seen people attach significant importance to the BuildNumber of Windows and with this approach retrieving BuildNumber can become really expensive. so I skipped over BuildNumber.

I will include another article to fetch Windows Version. But that approach uses COM and may not be desired by some.

 Update:

A User on this board has provided a better way to do this.

if you include an embeded manifest file as part of your .exe program.  GetVersionEx will return the right version on Windows8.1. Note that you can support other operating systems as well. but you must make sure Windows 8.1 is inclucded.

XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">

  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!--This Id value indicates the application supports Windows 8.1 functionality-->
      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
      
    </application>
  </compatibility>

  <assemblyIdentity type="win32"
                    name="SampleCode.GetWindowsVersionInfo"
                    version="1.0.0.0"
                    processorArchitecture="x86"
                    publicKeyToken="0000000000000000"
  />
</assembly>

The Great thing about this approach is that the performance  of GetVersionEx is fantastic. 

But the issue still remains that your binaries will always missbehave on Newer Version of Windows (since you don't know newever Version of Windows Guid ahead of time).

Also One More issue is that you can not create an application that runs in Compatiblity Mode with previous Windows OS.

you will have to get rid of Visual Studio Deprecation Errors by disabling by doing something like this.

C++
#pragma warning (disable : 4996)
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
POSVERSIONINFO pVersionInfo = (POSVERSIONINFO)&versionInfo;
if (::GetVersionEx(pVersionInfo))
{
    if (6 == versionInfo.dwMajorVersion && 3 == versionInfo.dwMinorVersion)
    {
        wcout << _T("Windows 8.1 Detected") << endl;
    }
    else if (6 == versionInfo.dwMajorVersion && 2 == versionInfo.dwMinorVersion)
    {
        wcout << _T("Windows 8.0 Detected") << endl;
    }
}
#pragma warning (default : 4996)

 

I have also discovered another API that still returns Windows Version without any compatability Manifests required.  But it takes a 2-3 miliseconds to execute so it is significantly slower than GetVersionEx API.

 

C++
bool GetWindowsVersion(DWORD& major, DWORD& minor)
{	
	LPBYTE pinfoRawData;
	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);
		return true;
	}
	return false;
}
int _tmain(int argc, _TCHAR* argv[])
{	
	DWORD major = 0;
	DWORD minor = 0;
	if (GetWindowsVersion(major, minor))
	{
		wcout << _T("Major:") << major << _T("Minor:") << minor << endl;
	}	
	return 0;
}

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
CEO NanoToolkit, Inc
United States United States
I have been doing some sort of Software Development since 1998. I started with C Programming but quickly upgraded to C++. I am proficient in Windows UI, Windows Server/Service, COM, C# and WinForms, C# and Asp.net. I can also claim some know-how in VB.NET and java. Every once in a while I hone in my scripting skills by doing more JQuery and Powershell but I quickly forget it all. I also have a working knowledge of CSS and HTML as well.
check out my Blog

Comments and Discussions

 
GeneralThrowing some ideas to the community Pin
SolarNigerija5-Nov-18 10:36
SolarNigerija5-Nov-18 10:36 
Had issue porting some old DRIVER to WDK 10.* that was using GetVersion() to determine OS version so...
was experimenting on my own using Windows 7 to see what I could get out of newer API's.
Hope someone else get's some better bulb how to properly replace NOT_BUILD_WINDOWS_DEPRECATE GetVersion() functionality.
Notice: GetVersion() is the one that fails in kernel driver on WDK 10.* + platform tools v141 even when driver is built for windows 7, but this seems to work so far.
Notice: if using code inside kernel driver GetVersionReplacement() replace VerifyVersionInfo with RtlVerifyVersionInfo.
Notice: if using code inside kernel driver GetVersionRtl() just call RtlGetVersion(&info) and return DWORD value.

code:
// file: stdafx.h
#pragma once

#include "targetver.h"

#include <stdio.h>
#include <tchar.h>
// file: targetver.h
#pragma once

// Including SDKDDKVer.h defines the highest available Windows platform.

// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.

#include <SDKDDKVer.h>
// file: stdafx.cpp
#include "stdafx.h"
#include <Windows.h>

DWORD GetVersionReplacement();
DWORD GetVersionRtl();

int _tmain(int argc, _TCHAR* argv[])
{

  char tmp[100] = {0};
  DWORD v;

  v = GetVersion();
  int major = (v >> 0) & 0xff;
  int minor = (v >> 8) & 0xff;
  int build = (v >> 16) & 0xffff;
  sprintf_s(tmp, 100, "org: %d.%d.%d\r\n", major, minor, build);
  printf_s(tmp);
  OutputDebugStringA(tmp);
  
  v = GetVersionReplacement();
  int major_r = (v >> 0) & 0xff;
  int minor_r = (v >> 8) & 0xff;
  int build_r = (v >> 16) & 0xffff;
  sprintf_s(tmp, 100, "rep: %d.%d.%d\r\n", major_r, minor_r, build_r);
  printf_s(tmp);
  OutputDebugStringA(tmp);

  v = GetVersionRtl();
  int major_rtl = (v >> 0) & 0xff;
  int minor_rtl = (v >> 8) & 0xff;
  int build_rtl = (v >> 16) & 0xffff;
  sprintf_s(tmp, 100, "rtl: %d.%d.%d\r\n", major_r, minor_r, build_r);
  printf_s(tmp);
  OutputDebugStringA(tmp);

	return 0;
}

DWORD GetVersionSinglePart(DWORD VER_FLAGS);

/// <summary>
/// extracts major version using newer/lame VerifyVersionInfo() 
/// </summary>
DWORD GetVersionMajor()
{
  return GetVersionSinglePart(VER_MAJORVERSION);
}

/// <summary>
/// extracts minor version using newer/lame VerifyVersionInfo() 
/// </summary>
DWORD GetVersionMinor()
{
  return GetVersionSinglePart(VER_MINORVERSION);
}

/// <summary>
/// extracts build version using newer/lame VerifyVersionInfo() 
/// </summary>
DWORD GetVersionBuild()
{  
  return GetVersionSinglePart(VER_BUILDNUMBER);
}

/// <summary>
/// replacement for OBSOLETE DO NOT BUILD GetVersion() using newer/lame VerifyVersionInfo() 
/// </summary>
DWORD GetVersionReplacement()
{
  return ((GetVersionMajor() << 0) | (GetVersionMinor() << 8) | (GetVersionBuild() << 16));
}

/// <summary>
/// extracts VER_* version using newer/lame VerifyVersionInfo() check code for supported VER_* FLAGS.
/// </summary>
DWORD GetVersionSinglePart(DWORD VER_FLAGS)
{
  DWORDLONG condition_greater = 0;
  DWORDLONG condition_equal   = 0;
  VER_SET_CONDITION( condition_greater, VER_FLAGS, VER_GREATER );
  VER_SET_CONDITION( condition_equal,   VER_FLAGS, VER_EQUAL   );
  OSVERSIONINFOEX info = {0};
  info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  DWORD istart = 0;
  DWORD ihalfprev = 0;
  switch(VER_FLAGS)
  {
  case VER_MAJORVERSION:
  case VER_MINORVERSION:
    istart = 256 / 2;   // max 9 iterations
    break;
  case VER_BUILDNUMBER:
    istart = 65536 / 2;   // max 17 iterations
    break;
  }
  DWORD ihalf = (istart / 2) + (istart % 2);
  while(ihalf > 0)
  {
    // we don't care it's flagged single VER_ matching
    info.dwMajorVersion = istart;
    info.dwMinorVersion = istart;
    info.dwBuildNumber = istart;
    // equ must be first, since major:6 returns true for Win7 for greater comparison due minor number (MS) =.=
    if (VerifyVersionInfo(&info, VER_FLAGS, condition_equal)) // equal
    {
      return istart;
    }
    else if (VerifyVersionInfo(&info, VER_FLAGS, condition_greater)) // it's greater
    {
      istart += ihalf; 
    }
    else // it's smaller
    {
      istart -= ihalf;
    }
    // prevent errors in stupid MS
    // second missmatch when ihalf == 1 which shouldn't be possible
    if (ihalfprev == 1) 
      break;
    ihalfprev = ihalf;
    ihalf = (ihalf / 2) + (ihalf % 2);    
  }
  return (DWORD)(-1); // not found
}

// NTDLL.DLL : RtlGetVersion not yet obsolete...
typedef __declspec(dllimport) LONG (__stdcall *T_RtlGetVersion)(PRTL_OSVERSIONINFOW lpVersionInformation);
// KERNEL32.DLL : GetVersion obsolete
typedef DWORD (*T_GetVersion)();

/// <summary>
/// using dynamic call to RtlGetVersion() if exists with fallback to dynamic call to GetVersion().
/// </summary>
DWORD GetVersionRtl()
{
  DWORD returnValue = (DWORD)(-1);
  HMODULE hNTDLL = (HMODULE)GetModuleHandle(L"ntdll.dll");
  if (NULL != hNTDLL)
  {
    T_RtlGetVersion _RtlGetVersion = (T_RtlGetVersion)GetProcAddress(hNTDLL, "RtlGetVersion");
    if (NULL != _RtlGetVersion)
    {
      // kernel RtlGetVersion() found.
      RTL_OSVERSIONINFOW info = { 0 };
      info.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW);
      if (/*STATUS_SUCCESS*/0 == _RtlGetVersion(&info))
      {
        returnValue = (DWORD)((info.dwMajorVersion << 0) | (info.dwMinorVersion << 8) | (info.dwBuildNumber << 16));
      }
    }
    else
    {
      // let's try obsolete
      HMODULE hKERNEL = (HMODULE)GetModuleHandle(L"kernel32.dll");
      if (hKERNEL)
      {
        T_GetVersion _GetVersion = (T_GetVersion)GetProcAddress(hKERNEL, "GetVersion");
        if (NULL != _GetVersion)
        {
          returnValue = (DWORD)_GetVersion();
        }
      }
    }
  }
  return returnValue;
}
output:
org: 6.1.7601
rep: 6.1.7601
rtl: 6.1.7601

QuestionA simple solution that works on Windows 10 and Server 2012 Pin
Rahsas18-Oct-17 4:38
Rahsas18-Oct-17 4:38 
QuestionSimplest solution (if you're lazy to read this article) Pin
Tarmo Pikaro24-Nov-16 10:47
Tarmo Pikaro24-Nov-16 10:47 
SuggestionAnother way Pin
RLebeau10-Aug-15 10:29
RLebeau10-Aug-15 10:29 
SuggestionA much easier and shorter code: Pin
Elmue24-Jun-15 17:06
Elmue24-Jun-15 17:06 
GeneralRe: A much easier and shorter code: Pin
dc_200013-Jul-15 17:26
dc_200013-Jul-15 17:26 
QuestionJust use RtlGetVersion() instead of all this. Pin
User-17514729-Nov-14 11:29
User-17514729-Nov-14 11:29 
AnswerRe: Just use RtlGetVersion() instead of all this. Pin
Ehsan A Samani10-Nov-14 9:40
professionalEhsan A Samani10-Nov-14 9:40 
GeneralRe: Just use RtlGetVersion() instead of all this. Pin
Member 176990911-Nov-14 3:25
Member 176990911-Nov-14 3:25 
GeneralRe: Just use RtlGetVersion() instead of all this. Pin
User-17514725-Jan-15 9:04
User-17514725-Jan-15 9:04 
GeneralRe: Just use RtlGetVersion() instead of all this. Pin
Mosc17-Jun-15 2:47
Mosc17-Jun-15 2:47 
GeneralRe: Just use RtlGetVersion() instead of all this. Pin
User-17514723-Jul-15 23:56
User-17514723-Jul-15 23:56 
QuestionI would suggest using the WMI in stead. Pin
Member 176990921-Oct-14 2:56
Member 176990921-Oct-14 2:56 
AnswerRe: I would suggest using the WMI in stead. Pin
Ehsan A Samani21-Oct-14 3:06
professionalEhsan A Samani21-Oct-14 3:06 
GeneralI wonder... Pin
Cristian Amarie13-Sep-14 3:03
Cristian Amarie13-Sep-14 3:03 
QuestionVersion of Win2000 appears wrong? Pin
John P. Curtis30-Apr-14 12:31
John P. Curtis30-Apr-14 12:31 
AnswerRe: Version of Win2000 appears wrong? Pin
Ehsan A Samani30-Apr-14 15:09
professionalEhsan A Samani30-Apr-14 15:09 
QuestionHow to import an xml file two can? Pin
park suno27-Jan-14 18:33
park suno27-Jan-14 18:33 
QuestionArticle Title? Pin
thatraja8-Dec-13 20:11
professionalthatraja8-Dec-13 20:11 
GeneralWhen will Microsoft learn? Pin
ahmd030-Nov-13 9:20
ahmd030-Nov-13 9:20 
GeneralRe: When will Microsoft learn? Pin
Ehsan A Samani30-Nov-13 9:44
professionalEhsan A Samani30-Nov-13 9:44 
GeneralAnother way Pin
ledtech36-Nov-13 12:16
ledtech36-Nov-13 12:16 
GeneralRe: Another way Pin
Ehsan A Samani6-Nov-13 12:41
professionalEhsan A Samani6-Nov-13 12:41 
GeneralRe: Another way Pin
ledtech36-Nov-13 13:56
ledtech36-Nov-13 13:56 
GeneralMy vote of 5 Pin
Pablo Aliskevicius6-Nov-13 3:49
Pablo Aliskevicius6-Nov-13 3:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.