Error c4996 getversionexw объявлен deprecate

I am working on VS 2013 in Win 8.1. How to solve this warning?

The basic question is «why are you calling GetVersionExW in the first place?» The answer to that question determines what you should do instead.

The deprecation warning is there to give developers a heads-up about the appcompat behavior change that started in Windows 8.1. See Windows and Windows Server compatibility cookbook: Windows 8, Windows 8.1, and Windows Server 2012. In short, that function doesn’t return what you think it returns by default.

Historically, badly written OS version checks are the primary source of appcompat bugs for Windows OS upgrades. There’ve been a number of different approaches to trying to mitigate this problem (the AppVerifier version lie, the VerifyVersionInfo API, etc.), and this is the most aggressive to date.

The VersionHelpers.h mentioned in the comments are in the Windows 8.1 SDK that comes with Visual Studio 2013. They are not a new API; they are just utility code that makes use of the VerifyVersionInfo API introduced back in Windows 2000. These functions are for doing «You must be this high to ride this ride» style checks which are the class of version checks that are most often badly written. The code is pretty simple. For example, the IsWindowsVistaSP2OrGreater test is:

VERSIONHELPERAPI
IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
{
    OSVERSIONINFOEXW osvi = {};
    osvi.dwOSVersionInfoSize = sizeof(osvi);
    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;
}

VERSIONHELPERAPI
IsWindowsVistaSP2OrGreater()
{
    return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 2);
}

You don’t need to use VersionHelpers.h as you could just do this kind of code yourself, but they are convenient if you are already using the VS 2013 compiler. For games, I have an article What’s in a version number? which uses VerifyVersionInfo to do the kind of reasonable checks one should for game deployment.

Note if you are using VS 2013 with the v120_xp platform toolset to target Windows XP, you’ll actually be using the Windows 7.1A SDK and #include <VersionHelpers.h> won’t work. You can of course use VerifyVersionInfo directly.

The other major use of GetVersionExW is diagnostic logs and telemetry. In this case, one option is to continue to use that API and make sure you have the right manifest entries in your application to ensure reasonably accurate results. See Manifest Madness for details on what you do here to achieve this. The main thing to keep in mind is that unless you routinely update your code, you will eventually stop getting fully accurate information in a future version of the OS.

Note that it is recommended you put the <compatibility> section in an embedded manifest whether or not you care about the results of GetVersionEx as general best practice. This allows the OS to automatically apply future appcompat fixes based on knowing how the app was originally tested.

For diagnostic logs, another approach that might be a bit more robust is to grab the version number out of a system DLL like kernel32.dll using GetFileVersionInfoW. This approach has a major caveat: Do not try parsing, doing comparisons, or making code assumptions based on the file version you obtain this way; just write it out somewhere. Otherwise you risk recreating the same bad OS version check problem that is better solved with VerifyVersionInfo. This option is not available to Windows Store apps, Windows phone apps, etc. but should work for Win32 desktop apps.

#include <Windows.h>
#include <cstdint>
#include <memory>

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

bool GetOSVersionString( WCHAR* version, size_t maxlen )
{
    WCHAR path[ _MAX_PATH ] = {};
    if ( !GetSystemDirectoryW( path, _MAX_PATH ) )
        return false;

    wcscat_s( path, L"\kernel32.dll" );

    //
    // Based on example code from this article
    // http://support.microsoft.com/kb/167597
    //

    DWORD handle;
#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
    DWORD len = GetFileVersionInfoSizeExW( FILE_VER_GET_NEUTRAL, path, &handle );
#else
    DWORD len = GetFileVersionInfoSizeW( path, &handle );
#endif
    if ( !len )
        return false;

    std::unique_ptr<uint8_t> buff( new (std::nothrow) uint8_t[ len ] );
    if ( !buff )
        return false;

#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
    if ( !GetFileVersionInfoExW( FILE_VER_GET_NEUTRAL, path, 0, len, buff.get() ) )
#else
    if ( !GetFileVersionInfoW( path, 0, len, buff.get() ) )
#endif
        return false;

    VS_FIXEDFILEINFO *vInfo = nullptr;
    UINT infoSize;

    if ( !VerQueryValueW( buff.get(), L"\", reinterpret_cast<LPVOID*>( &vInfo ), &infoSize ) )
        return false;

    if ( !infoSize )
        return false;

    swprintf_s( version, maxlen, L"%u.%u.%u.%u",
                HIWORD( vInfo->dwFileVersionMS ),
                LOWORD(vInfo->dwFileVersionMS),
                HIWORD(vInfo->dwFileVersionLS),
                LOWORD(vInfo->dwFileVersionLS) );
    
    return true;
}

If there is some other reason you are calling GetVersionExW, you probably shouldn’t be calling it. Checking for a component that might be missing shouldn’t be tied to a version check. For example, if your application requires Media Foundation, you should set a «You must be this high to ride this ride check» like the VersionHelpers.h IsWindowsVistaOrGreater for deployment, but at runtime you should use explicit linking via LoadLibrary or LoadLibaryEx to report an error or use a fallback if MFPLAT.DLL is not found.

Explicit linking is not an option for Windows Store apps. Windows 8.x solves this
particular problem by having a stub MFPLAT.DLL and MFStartUp will return E_NOTIMPL.
See «Who moved my [Windows Media] Cheese»?

Another example: if your application wants to use Direct3D 11.2 if it is available and otherwise uses DirectX 11.0, you’d use set a IsWindowsVistaSP2OrGreater minimum bar for deployment perhaps using the D3D11InstallHelper. Then at runtime, you’d create the DirectX 11.0 device and if it fails, you’d report an error. If you obtain a ID3D11Device, then you’d QueryInterface for a ID3D11Device2 which if it succeeds means you are using an OS that supports DirectX 11.2. See Anatomy of Direct3D 11 Create Device.

If this hypothetical Direct3D application supports Windows XP, you’d use a deployment bar of IsWindowsXPSP2OrGreater or IsWindowsXPSP3OrGreater, and then at run time use explicit linking to try to find the D3D11.DLL. If it wasn’t present, you’d fall back to using Direct3D 9—since we set the minimum bar, we know that DirectX 9.0c or later is always present.

They key point here is that in most cases, you should not use GetVersionEx.

Note that with Windows 10, VerifyVersionInfo and getting the file version stamp via GetFileVersionInfo for kernel32.lib are now subject to the same manifest based behavior as GetVersionEx (i.e. without the manifest GUID for Windows 10, it returns results as if the OS version were 6.2 rather than 10.0).

For universal Windows apps on Windows 10, you can a new WinRT API AnalyticsInfo to get a version stamp string for diagnostic logs and telemetry.

Senum

3 / 2 / 1

Регистрация: 02.05.2014

Сообщений: 92

1

10.04.2015, 01:24. Показов 14311. Ответов 4

Метки нет (Все метки)


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <locale>
using namespace std;
 
 
void VersionWindows1()
{
    OSVERSIONINFO osvi;
    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    GetVersionEx((OSVERSIONINFO*)&osvi);
    cout << "индификатор Ос:" << osvi.dwMajorVersion << endl;
    cout << "Версия:" << osvi.dwMinorVersion << endl;
    cout << "Платформа:" << osvi.dwPlatformId << endl;
    if (osvi.dwMajorVersion == 6)
    {
 
        if (osvi.dwMinorVersion == 0)
        {
            if (osvi.dwPlatformId == 2)
                cout << "Windows Vista";
            else cout << "Windows server 2008";
        }
        if (osvi.dwMinorVersion == 1)
        {
            if (osvi.dwPlatformId == 2)
                cout << "Windows 7";
            else cout << "Windows server 2008 R2";
        }
    }
    if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
    {
        if (GetSystemMetrics(SM_SERVERR2))
            cout << "Windows server 2003 R2";
        else if (osvi.dwPlatformId == VER_SUITE_STORAGE_SERVER)
            cout << "Windows storage Server 2003";
        else if (osvi.dwPlatformId == VER_SUITE_WH_SERVER)
            cout << "Windows home server";
        else if (osvi.dwPlatformId == 2)
            cout << "Windows XP Professional x64 editon";
        else cout << "Windows server 2003";
    }
    if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
        cout << "Windows XP";
    if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
        cout << "Windows 2000";
    cout << endl;
    cout << "сборка:" << osvi.dwBuildNumber << endl;
    cout << "Доп.Инфо:" << osvi.szCSDVersion << endl;
}

ошибка
Ошибка 1 error C4996: ‘GetVersionExA’: объявлен deprecate

пытался использовать

C++
1
2
3
4
#ifdef _MSC_VER
#pragma warning( push )
#pragma warning( once: 4996 )
#endif

не помогло

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



rao

902 / 423 / 159

Регистрация: 02.04.2014

Сообщений: 1,206

10.04.2015, 19:17

2

Лучший ответ Сообщение было отмечено schdub как решение

Решение

Так это же не ошибка, а только предупреждение. В MSDN’е написано как отключить:

C++
1
#pragma warning(disable : 4996)



0



3 / 2 / 1

Регистрация: 02.05.2014

Сообщений: 92

10.04.2015, 21:02

 [ТС]

3

При добавлении этого кода возникают две другие ошибки

Ошибка 2 error LNK1120: неразрешенных внешних элементов: 1
Ошибка 1 error LNK2019: ссылка на неразрешенный внешний символ _main в функции ___tmainCRTStartup



0



902 / 423 / 159

Регистрация: 02.04.2014

Сообщений: 1,206

10.04.2015, 21:58

4



1



3 / 2 / 1

Регистрация: 02.05.2014

Сообщений: 92

10.04.2015, 22:26

 [ТС]

5

Спс,разобрался



0



Better than disabling warnings, you can just disable the relevant code as it is intended to be disabled by adding to the file’s preprocessor defines.

Right-click on sqlite3.c, click Properties, Configuration Properties->C/C++->Preprocessor. Make sure you have «all configurations» selected for the configuration and platform dropdowns (unless you only have one platform, then just select the one that’s available) and edit the Preprocessor Definitions to be

SQLITE_WIN32_GETVERSIONEX=0;%(PreprocessorDefinitions)

This will skip the NTDDI_VERSION check since that symbol isn’t defined or is defined incorrectly when your compiler hits sqlite3.c.

There’s this comment in there, too, which may be interesting:

/*
** NOTE: All sub-platforms where the GetVersionEx[AW] functions are
**       deprecated are always assumed to be based on the NT kernel.
*/

The net effect of setting that #define is that your OS is always assumed to be based on Win NT, which it is since you’re Win 8.1 or Win 10 (or greater). ;)

So basically by disabling that warning you’re just making your code slower because it needs to do work to figure out if it’s on WinNT or not.

Better than disabling warnings, you can just disable the relevant code as it is intended to be disabled by adding to the file’s preprocessor defines.

Right-click on sqlite3.c, click Properties, Configuration Properties->C/C++->Preprocessor. Make sure you have «all configurations» selected for the configuration and platform dropdowns (unless you only have one platform, then just select the one that’s available) and edit the Preprocessor Definitions to be

SQLITE_WIN32_GETVERSIONEX=0;%(PreprocessorDefinitions)

This will skip the NTDDI_VERSION check since that symbol isn’t defined or is defined incorrectly when your compiler hits sqlite3.c.

There’s this comment in there, too, which may be interesting:

/*
** NOTE: All sub-platforms where the GetVersionEx[AW] functions are
**       deprecated are always assumed to be based on the NT kernel.
*/

The net effect of setting that #define is that your OS is always assumed to be based on Win NT, which it is since you’re Win 8.1 or Win 10 (or greater). ;)

So basically by disabling that warning you’re just making your code slower because it needs to do work to figure out if it’s on WinNT or not.

Introduction

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

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 Productionready 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.

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.

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.

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;}  

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.

struct WindowsNTOSInfo
{
    DWORD dwMajorVersion;
    DWORD dwMinorVersion;
    WORD wServicePackMajor;    
    };

struct WindowsNTOSInfoEx :WindowsNTOSInfo
{
    BYTE ProductType;
};

const WindowsNTOSInfo KnownVersionsOfWindows[] =
{
    { 6, 3, 0,   },    { 6, 2, 0,   },
    { 6, 1, 1,  },    { 6, 1, 0,  },
    { 5, 1, 3,  },    { 5, 1, 2,  },    { 5, 1, 1,  },    { 5, 1, 0,  },
    { 6, 0, 2,  },    { 6, 0, 1,  },    { 6, 0, 0,  },
    { 5, 2, 2,  },    { 5, 2, 1,  },    { 5, 2, 0,  },

    { 5, 1, 4,  },     { 5, 1, 3,  },     { 5, 1, 2,  },     { 5, 1, 2,  },     { 5, 1, 0,  }, };

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

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

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.

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;
        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
                {
                                                            servicePackCounterSeed = 0;
                }                
            }
        }
        else
        {
                        minorVersionCounterSeed = 0;
        }
    }
    return false;
}

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

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.

="1.0"="UTF-8"="yes"
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">

  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      
      <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.

#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.

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;
}

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

When downloading http://www.microsoft.com/en-us/download/confirmation.aspx?id=42643 on Windows 8.1, the installer failed

image

Well the most obvious thing, is the installer for some reason is set into compatibility mode. Clicking EXE and looking at properties shows this is not the case:

image

First I tried ProcMon (http://live.sysinternals.com/ProcMon.exe)

Using the Target icon in ProcMon I drag it over the error message, and we find setup.exe is showing the error

image

In the properties we get the path

image

Well no compatibility mode on that EXE either.

From ProcMon we do see an HTML file is written (This is what clicking the link “More Information about blocked .NET Framework 4.5.2 installations” will open)

image

Opening it we see in log:

image

Well that’s helpful.

While setup.exe was still open I copied the entire extracted install contents into a temporary folder, so I would still have them after the folder was deleted.

So I used a file search utility to search the extracted install folder (I used http://www.nirsoft.net/utils/search_my_files.html ) for

cannot run in compatibility mode

and found file 1033LocalizedData.xml

<Text ID=”#(loc.Blocker_in_OS_Compatibility_Mode)” LocalizedText=”The setup cannot run in compatibility mode.” />

In then searched for files with content Blocker_in_OS_Compatibility_Mode

This found ParameterInfo.xml which found

<BlockIf DisplayText=”#(loc.Blocker_in_OS_Compatibility_Mode)” ID=”AppCompatMode”>
      <Exists>
        <IsInOSCompatibilityMode />
      </Exists>
    </BlockIf>

Now possibly we could just remove this from the XML file to get rid of the check. But let’s investigate further

Searching files for content with IsInOSCompatibilityMode found SetupEngine.dll

Opening DLL in IDA we see functions with IsInOSCompatibilityMode in the name

image

Examining function  we this this – we click the jmp link to follow it to function :

Mode::IsOSCompatibilityMode(IronMan::IsInOSCompatibilityMode *__hidden this)
?IsOSCompatibilityMode@IsInOSCompatibilityMode@IronMan@@EAE_NXZ proc near
jmp   
?IsInOSCompatibilityMode@CSystemUtil@IronMan@@SG_NXZ ; IronMan::CSystemUtil::IsInOSCompatibilityMode(void)
?IsOSCompatibilityMode@IsInOSCompatibilityMode@IronMan@@EAE_NXZ endp

We can see this function

1) retreives OS version via GetVersionEx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms724451(v=vs.85).aspx) then calls

2) sets mask with VerSetConditionMask (http://msdn.microsoft.com/en-us/library/windows/desktop/ms725493(v=vs.85).aspx)

3) Calls VerifyVersionInfoW (http://msdn.microsoft.com/en-us/library/windows/desktop/ms725492(v=vs.85).aspx)

text:10028537 ; bool __stdcall IronMan::CSystemUtil::IsInOSCompatibilityMode() .text:10028537 ?IsInOSCompatibilityMode@CSystemUtil@IronMan@@SG_NXZ proc near .text:10028537 ; CODE XREF: IronMan::IsInOSCompatibilityMode::IsOSCompatibilityMode(void)j .text:10028537 ; IronMan::UxT<IronMan::Sqm>::GetOSComplete(_OSVERSIONINFOEXW &,_SYSTEM_INFO &)+4Ap .text:10028537 .text:10028537 var_129 = byte ptr -129h .text:10028537 VersionInformation= _OSVERSIONINFOW ptr -128h .text:10028537 var_4 = dword ptr -4 .text:10028537 .text:10028537 push ebp .text:10028538 mov ebp, esp .text:1002853A and esp, 0FFFFFFF8h .text:1002853D sub esp, 130h .text:10028543 mov eax, ___security_cookie .text:10028548 xor eax, esp .text:1002854A mov [esp+130h+var_4], eax .text:10028551 push ebx .text:10028552 push esi .text:10028553 xor ebx, ebx .text:10028555 push 118h ; Size .text:1002855A lea eax, [esp+13Ch+VersionInformation.dwMajorVersion] .text:1002855E push ebx ; Val .text:1002855F push eax ; Dst .text:10028560 mov [esp+144h+var_129], bl .text:10028564 call _memset .text:10028569 add esp, 0Ch .text:1002856C lea eax, [esp+138h+VersionInformation] .text:10028570 push eax ; lpVersionInformation .text:10028571 mov [esp+13Ch+VersionInformation.dwOSVersionInfoSize], 11Ch .text:10028579 call ds:__imp__GetVersionExW@4 ; GetVersionExW(x) .text:1002857F test eax, eax .text:10028581 jz short loc_100285BF .text:10028583 mov esi, ds:__imp__VerSetConditionMask@16 ; VerSetConditionMask(x,x,x,x) .text:10028589 push 1 ; Condition .text:1002858B push 2 ; TypeMask .text:1002858D push ebx .text:1002858E push ebx ; ConditionMask .text:1002858F call esi ; VerSetConditionMask(x,x,x,x) ; VerSetConditionMask(x,x,x,x) .text:10028591 push 1 ; Condition .text:10028593 push 1 ; TypeMask .text:10028595 push edx .text:10028596 push eax ; ConditionMask .text:10028597 call esi ; VerSetConditionMask(x,x,x,x) ; VerSetConditionMask(x,x,x,x) .text:10028599 push 1 ; Condition .text:1002859B push 20h ; TypeMask .text:1002859D push edx .text:1002859E push eax ; ConditionMask .text:1002859F call esi ; VerSetConditionMask(x,x,x,x) ; VerSetConditionMask(x,x,x,x) .text:100285A1 push 1 ; Condition .text:100285A3 push 10h ; TypeMask .text:100285A5 push edx .text:100285A6 push eax ; ConditionMask .text:100285A7 call esi ; VerSetConditionMask(x,x,x,x) ; VerSetConditionMask(x,x,x,x) .text:100285A9 push edx .text:100285AA push eax ; dwlConditionMask .text:100285AB push 33h ; dwTypeMask .text:100285AD lea eax, [esp+144h+VersionInformation] .text:100285B1 push eax ; lpVersionInformation .text:100285B2 call ds:__imp__VerifyVersionInfoW@16 ; VerifyVersionInfoW(x,x,x,x) .text:100285B8 test eax, eax .text:100285BA setnz [esp+138h+var_129] .text:100285BF .text:100285BF loc_100285BF: ; CODE XREF: IronMan::CSystemUtil::IsInOSCompatibilityMode(void)+4Aj .text:100285BF mov ecx, [esp+138h+var_4] .text:100285C6 xor eax, eax .text:100285C8 cmp [esp+138h+var_129], bl .text:100285CC pop esi .text:100285CD setz al .text:100285D0 pop ebx .text:100285D1 xor ecx, esp .text:100285D3 call @__security_check_cookie@4 ; __security_check_cookie(x) .text:100285D8 mov esp, ebp .text:100285DA pop ebp .text:100285DB retn .text:100285DB ?IsInOSCompatibilityMode@CSystemUtil@IronMan@@SG_NXZ endp

We search these two APIs in Rohitab API Monitor (http://www.rohitab.com/apimonitor) and make sure they are monitored:

image

Then we monitor it with API monitor:

image

The GetVersionExW that comes just before VerifyVersionInfoW succeeds

image

The call to VerifyVersionInfoW

image

Breakpoint after the call we can see error:

image

In the “After” break point, if we change the return value to TRUE the installer starts

image

image

The “before” our fix API trace looked like:

#    Time of Day    Thread    Module    API    Return Value    Error    Duration
84887    7:31:13.077 PM    1    SetupEngine.dll    GetVersionExW ( 0x00a3ee60 )    TRUE        0.0000070
84888    7:31:13.077 PM    1    vfcompat.dll    LoadStringA ( 0x5e260000, 1003, 0x00a3ed08, 64 )    4        0.0000008
84889    7:31:13.077 PM    1    vrfcore.dll    _vsnwprintf ( 0x6abaf438, 2047, “Returned %lu.%lu build number: %lu, service pack: %lu.%lu, suite mask: 0x%08X, product type: %hs.”, 0x00a3ece0 )    97        0.0000025
84890    7:31:13.077 PM    1    vrfcore.dll    _wcsicmp ( “Returned 7.0 build number: 8000, service pack: 0.0, suite mask: 0x00000000, product type: (null).”, “Returned 7.0 build number: 8000, service pack: 0.0, suite mask: 0x00000000, product type: (null).” )    0        0.0000004
84891    7:31:13.077 PM    1    SetupEngine.dll    VerSetConditionMask ( 0, VER_MAJORVERSION, VER_EQUAL )    9223372036854775816        0.0000000
84892    7:31:13.077 PM    1    SetupEngine.dll    VerSetConditionMask ( 9223372036854775816, VER_MINORVERSION, VER_EQUAL )    9223372036854775817        0.0000000
84893    7:31:13.077 PM    1    SetupEngine.dll    VerSetConditionMask ( 9223372036854775817, VER_SERVICEPACKMAJOR, VER_EQUAL )    9223372036854808585        0.0000004
84894    7:31:13.077 PM    1    SetupEngine.dll    VerSetConditionMask ( 9223372036854808585, VER_SERVICEPACKMINOR, VER_EQUAL )    9223372036854812681        0.0000000
84895    7:31:13.077 PM    1    SetupEngine.dll    VerifyVersionInfoW ( 0x00a3ee60, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, 9223372036854812681 )    FALSE    1150 = The specified program requires a newer version of Windows.     0.0000086

After we “modified” the value the result looked like:

#    Time of Day    Thread    Module    API    Return Value    Error    Duration
85790    7:25:08.561 PM    1    SetupEngine.dll    VerifyVersionInfoW ( 0x00a3ef00, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, 9223372036854812681 )    TRUE        0.0000094

The cause of this issue is documented in http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx

GetVersion(Ex) lies to you unless you explicitly embed a manifest to indicate your app is compatible with Windows 8.1.

Or is it the cause? Resource Hacker, shows the EXE has explicitly declared Windows 8.1 support:

image

We can reproduce the issue with simple code, from a new Win32 Console C++ template in Visual Studio 2013. By default you can no longer call GetVersionEx, you will get error C4996: ‘GetVersionExW’: was declared deprecated, so we must disable this warning before the code will compile. For a more overcomplicated solution check http://www.codeproject.com/Articles/678606/Part-Overcoming-Windows-s-deprecation-of-GetVe

#include "stdafx.h"
#include <Windows.h>

#pragma warning(disable : 4996)  // to disable deprecated error on GetVersionEx

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

    ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);

    GetVersionEx((LPOSVERSIONINFO)&osvi);    
    ULONGLONG mask= VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
    mask = VerSetConditionMask(mask, VER_MINORVERSION, VER_EQUAL);
    mask = VerSetConditionMask(mask, VER_SERVICEPACKMAJOR, VER_EQUAL);
    mask = VerSetConditionMask(mask, VER_SERVICEPACKMINOR, VER_EQUAL);
    bool result = VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, mask);
    if (result)
    {
        printf("OS Version OK!");
    }
    else
    {
        DWORD errorCode = GetLastError();
        printf("Bad os version Error: %d", errorCode);
    }

    return 0;
}


Which get same error as our install:

image

We can see the version is wrong:

image

So this is expected behavior.

Applications not manifested for Windows 8.1 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. To manifest your applications for Windows 8.1 please refer to Targeting your application for Windows 8.1.

As soon as I added the manifest into my EXE the code worked OK.

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level='asInvoker' uiAccess='false' />
      </requestedPrivileges>
    </security>
  </trustInfo>
    <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> 
        <application> 
            <!-- Windows 8.1 -->
            <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
            <!-- Windows Vista -->
            <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> 
            <!-- Windows 7 -->
            <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
            <!-- Windows 8 -->
            <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
        </application> 
    </compatibility>
</assembly>

image

Monitoring our own exe comes back with correct value:

image

Compared to the setup.exe which is returning Major Version 7 and Minor Version 0 (Windows 9?)

image 

So I launched with WinDbg, and set broke into application after the error. By viewing the import address table, we can see that the Version Lie SHIM has been applied:

0:001> lmv m setup
start    end        module name
00400000 00415000   Setup      (deferred)            
    Image path: Setup.exe
    Image name: Setup.exe
    Timestamp:        Sat Apr 12 12:40:15 2014 (5348A78F)
    CheckSum:         0001C78F
    ImageSize:        00015000
    File version:     12.0.51209.34209
    Product version:  12.0.51209.34209
    File flags:       0 (Mask 3F)
    File OS:          4 Unknown Win32
    File type:        1.0 App
    File date:        00000000.00000000
    Translations:     0409.04b0
    CompanyName:      Microsoft Corporation
    ProductName:      Microsoft® .NET Framework
    InternalName:     Setup.exe
    OriginalFilename: SetupUI.exe
    ProductVersion:   12.0.51209.34209
    FileVersion:      12.0.51209.34209 built by: FX452RTMGDR
    FileDescription:  Setup Installer
    LegalCopyright:   © Microsoft Corporation. All rights reserved.
0:001> !dh 00400000

File Type: EXECUTABLE IMAGE
FILE HEADER VALUES
     14C machine (i386)
       5 number of sections
5348A78F time date stamp Sat Apr 12 12:40:15 2014

       0 file pointer to symbol table
       0 number of symbols
      E0 size of optional header
     122 characteristics
            Executable
            App can handle >2gb addresses
            32 bit word machine

OPTIONAL HEADER VALUES
     10B magic #
   10.00 linker version
    5E00 size of code
    C400 size of initialized data
       0 size of uninitialized data
    2A82 address of entry point
    1000 base of code
         —– new —–
00400000 image base
    1000 section alignment
     200 file alignment
       2 subsystem (Windows GUI)
    5.01 operating system version
   10.00 image version
    5.01 subsystem version
   15000 size of image
     400 size of headers
   1C78F checksum
00100000 size of stack reserve
00002000 size of stack commit
00100000 size of heap reserve
00001000 size of heap commit
    8140  DLL characteristics
            Dynamic base
            NX compatible
            Terminal server aware
    6CE0 [      78] address [size] of Export Directory
    9000 [      3C] address [size] of Import Directory
    A000 [    9BB8] address [size] of Resource Directory
       0 [       0] address [size] of Exception Directory
   11800 [    3E90] address [size] of Security Directory
   14000 [     5C8] address [size] of Base Relocation Directory
    1040 [      1C] address [size] of Debug Directory
       0 [       0] address [size] of Description Directory
       0 [       0] address [size] of Special Directory
       0 [       0] address [size] of Thread Storage Directory
    27A0 [      40] address [size] of Load Configuration Directory
       0 [       0] address [size] of Bound Import Directory
    911C [      E0] address [size] of Import Address Table Directory
       0 [       0] address [size] of Delay Import Directory
       0 [       0] address [size] of COR20 Header Directory
       0 [       0] address [size] of Reserved Directory

SECTION HEADER #1
   .text name
    5D58 virtual size
    1000 virtual address
    5E00 size of raw data
     400 file pointer to raw data
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
60000020 flags
         Code
         (no align specified)
         Execute Read

Debug Directories(1)
    Type       Size     Address  Pointer
    cv           22        27e8     1be8    Format: RSDS, guid, 3, Setup.pdb

SECTION HEADER #2
   .data name
    19E0 virtual size
    7000 virtual address
     C00 size of raw data
    6200 file pointer to raw data
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
C0000040 flags
         Initialized Data
         (no align specified)
         Read Write

SECTION HEADER #3
  .idata name
     5FC virtual size
    9000 virtual address
     600 size of raw data
    6E00 file pointer to raw data
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
40000040 flags
         Initialized Data
         (no align specified)
         Read Only

SECTION HEADER #4
   .rsrc name
    9BB8 virtual size
    A000 virtual address
    9C00 size of raw data
    7400 file pointer to raw data
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
40000040 flags
         Initialized Data
         (no align specified)
         Read Only

SECTION HEADER #5
  .reloc name
     7D8 virtual size
   14000 virtual address
     800 size of raw data
   11000 file pointer to raw data
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
42000040 flags
         Initialized Data
         Discardable
         (no align specified)
         Read Only
0:001>
dps 00400000+911C 00400000+911C+E0
0040911c  7688cdad KERNEL32!HeapSetInformationStub
00409120  7688be1f KERNEL32!LoadLibraryW
00409124  7688980c KERNEL32!GetProcAddressStub
00409128  7688a7c6 KERNEL32!GetModuleHandleWStub
0040912c  5e262bfa
vfcompat!NS_HighVersionLie::VfHookGetVersion <- This causes GetVersionEx to return a version HIGHER than actual OS
00409130  76884eb0 KERNEL32!MultiByteToWideCharStub
00409134  7688986f KERNEL32!LCMapStringWStub
00409138  7688cfae KERNEL32!GetCommandLineWStub
0040913c  7688c460 KERNEL32!GetStartupInfoWStub
00409140  7688cf38 KERNEL32!SetUnhandledExceptionFilterStub
00409144  76897f64 KERNEL32!ExitProcessImplementation
00409148  768975fc KERNEL32!WriteFile
0040914c  7688c433 KERNEL32!GetStdHandleStub
00409150  7688ad26 KERNEL32!GetModuleFileNameWStub
00409154  7688ca7d KERNEL32!FreeEnvironmentStringsWStub
00409158  7688cda2 KERNEL32!GetEnvironmentStringsWStub
0040915c  7688cf87 KERNEL32!SetHandleCount
00409160  76897230 KERNEL32!InitializeCriticalSectionAndSpinCount
00409164  768974a0 KERNEL32!GetFileType
00409168  771f2974 ntdll!RtlDeleteCriticalSection
0040916c  7688be7e KERNEL32!TlsAllocStub
00409170  76881940 KERNEL32!TlsGetValueStub
00409174  76883560 KERNEL32!TlsSetValueStub
00409178  7688bdf2 KERNEL32!TlsFreeStub
0040917c  76888f69 KERNEL32!InterlockedIncrementStub
00409180  76883360 KERNEL32!SetLastErrorStub
00409184  76881960 KERNEL32!GetCurrentThreadId
00409188  768836c0 KERNEL32!GetLastErrorStub
0040918c  76889067 KERNEL32!InterlockedDecrementStub
00409190  7688bf1b KERNEL32!HeapCreateStub
00409194  76883760 KERNEL32!QueryPerformanceCounterStub
00409198  7689607c KERNEL32!GetTickCountStub
0040919c  76883580 KERNEL32!GetCurrentProcessId
004091a0  76884cf0 KERNEL32!GetSystemTimeAsFileTimeStub
004091a4  7688d17a KERNEL32!TerminateProcessStub
004091a8  76884ed0 KERNEL32!GetCurrentProcess
004091ac  768b3e7f KERNEL32!UnhandledExceptionFilterStub
004091b0  7688d16f KERNEL32!IsDebuggerPresentStub
004091b4  771cfd40 ntdll!RtlLeaveCriticalSection
004091b8  771cfd00 ntdll!RtlEnterCriticalSection
004091bc  76881990 KERNEL32!HeapFreeStub
004091c0  768898c0 KERNEL32!SleepStub
004091c4  7688be5c KERNEL32!GetCPInfoStub
004091c8  76889864 KERNEL32!GetACPStub
004091cc  76894c37 KERNEL32!GetOEMCPStub
004091d0  7688bc6d KERNEL32!IsValidCodePageStub
004091d4  7688c83c KERNEL32!RtlUnwindStub
004091d8  76887cf2 KERNEL32!WideCharToMultiByteStub
004091dc  771dafa9 ntdll!RtlSizeHeap
004091e0  5b88a77c vrfcore!VfCoreRtlAllocateHeap
004091e4  5b88a7c0 vrfcore!VfCoreRtlReAllocateHeap
004091e8  7688bc04 KERNEL32!IsProcessorFeaturePresentStub
004091ec  7688c2f6 KERNEL32!GetStringTypeWStub
004091f0  00000000
004091f4  0facd941 SetupEngine!Run
004091f8  00000000
004091fc  65480355

Looking at the DLL

0:001> lmv m vfcompat
start    end        module name
5e260000 5e275000   vfcompat   (pdb symbols)          c:symbolsvfcompat.pdbF265D805746240A68F5E3D2C2225463B1vfcompat.pdb
    Loaded symbol image file: C:WINDOWSSYSTEM32vfcompat.dll
    Image path: C:WINDOWSSysWOW64vfcompat.dll
    Image name: vfcompat.dll
    Timestamp:        Thu Aug 22 14:05:29 2013 (52158E09)
    CheckSum:         000185B6
    ImageSize:        00015000
    File version:     6.3.9600.16384
    Product version:  6.3.9600.16384
    File flags:       0 (Mask 3F)
    File OS:          40004 NT Win32
    File type:        2.0 Dll
    File date:        00000000.00000000
    Translations:     0409.04b0
    CompanyName:      Microsoft Corporation
    ProductName:      Microsoft® Windows® Operating System
    InternalName:     vfcompat.dll
    OriginalFilename: vfcompat.dll
    ProductVersion:   6.3.9600.16384
    FileVersion:      6.3.9600.16384 (winblue_rtm.130821-1623)
    FileDescription:  Application Verifier Provider – OS compatibility issues detection.
    LegalCopyright:   © Microsoft Corporation. All rights reserved.

Opening Application Verifier we can see the application verifier SHIM applied:

image

How did this getting get there? I didn’t put that there!!!

The Windows 8.1 App Certification Kit put it there, to check that an application would install on next version of Windows (or version 7.0 to be exact)

Senum

3 / 2 / 1

Регистрация: 02.05.2014

Сообщений: 92

1

10.04.2015, 01:24. Показов 14209. Ответов 4

Метки нет (Все метки)


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <locale>
using namespace std;
 
 
void VersionWindows1()
{
    OSVERSIONINFO osvi;
    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    GetVersionEx((OSVERSIONINFO*)&osvi);
    cout << "индификатор Ос:" << osvi.dwMajorVersion << endl;
    cout << "Версия:" << osvi.dwMinorVersion << endl;
    cout << "Платформа:" << osvi.dwPlatformId << endl;
    if (osvi.dwMajorVersion == 6)
    {
 
        if (osvi.dwMinorVersion == 0)
        {
            if (osvi.dwPlatformId == 2)
                cout << "Windows Vista";
            else cout << "Windows server 2008";
        }
        if (osvi.dwMinorVersion == 1)
        {
            if (osvi.dwPlatformId == 2)
                cout << "Windows 7";
            else cout << "Windows server 2008 R2";
        }
    }
    if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
    {
        if (GetSystemMetrics(SM_SERVERR2))
            cout << "Windows server 2003 R2";
        else if (osvi.dwPlatformId == VER_SUITE_STORAGE_SERVER)
            cout << "Windows storage Server 2003";
        else if (osvi.dwPlatformId == VER_SUITE_WH_SERVER)
            cout << "Windows home server";
        else if (osvi.dwPlatformId == 2)
            cout << "Windows XP Professional x64 editon";
        else cout << "Windows server 2003";
    }
    if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
        cout << "Windows XP";
    if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
        cout << "Windows 2000";
    cout << endl;
    cout << "сборка:" << osvi.dwBuildNumber << endl;
    cout << "Доп.Инфо:" << osvi.szCSDVersion << endl;
}

ошибка
Ошибка 1 error C4996: ‘GetVersionExA’: объявлен deprecate

пытался использовать

C++
1
2
3
4
#ifdef _MSC_VER
#pragma warning( push )
#pragma warning( once: 4996 )
#endif

не помогло

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь

0

rao

902 / 423 / 159

Регистрация: 02.04.2014

Сообщений: 1,206

10.04.2015, 19:17

2

Лучший ответ Сообщение было отмечено schdub как решение

Решение

Так это же не ошибка, а только предупреждение. В MSDN’е написано как отключить:

C++
1
#pragma warning(disable : 4996)

0

3 / 2 / 1

Регистрация: 02.05.2014

Сообщений: 92

10.04.2015, 21:02

 [ТС]

3

При добавлении этого кода возникают две другие ошибки

Ошибка 2 error LNK1120: неразрешенных внешних элементов: 1
Ошибка 1 error LNK2019: ссылка на неразрешенный внешний символ _main в функции ___tmainCRTStartup

0

902 / 423 / 159

Регистрация: 02.04.2014

Сообщений: 1,206

10.04.2015, 21:58

4

1

3 / 2 / 1

Регистрация: 02.05.2014

Сообщений: 92

10.04.2015, 22:26

 [ТС]

5

Спс,разобрался

0

The basic question is «why are you calling GetVersionExW in the first place?» The answer to that question determines what you should do instead.

The deprecation warning is there to give developers a heads-up about the appcompat behavior change that started in Windows 8.1. See Windows and Windows Server compatibility cookbook: Windows 8, Windows 8.1, and Windows Server 2012. In short, that function doesn’t return what you think it returns by default.

Historically, badly written OS version checks are the primary source of appcompat bugs for Windows OS upgrades. There’ve been a number of different approaches to trying to mitigate this problem (the AppVerifier version lie, the VerifyVersionInfo API, etc.), and this is the most aggressive to date.

The VersionHelpers.h mentioned in the comments are in the Windows 8.1 SDK that comes with Visual Studio 2013. They are not a new API; they are just utility code that makes use of the VerifyVersionInfo API introduced back in Windows 2000. These functions are for doing «You must be this high to ride this ride» style checks which are the class of version checks that are most often badly written. The code is pretty simple. For example, the IsWindowsVistaSP2OrGreater test is:

VERSIONHELPERAPI
IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
{
    OSVERSIONINFOEXW osvi = {};
    osvi.dwOSVersionInfoSize = sizeof(osvi);
    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;
}

VERSIONHELPERAPI
IsWindowsVistaSP2OrGreater()
{
    return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 2);
}

You don’t need to use VersionHelpers.h as you could just do this kind of code yourself, but they are convenient if you are already using the VS 2013 compiler. For games, I have an article What’s in a version number? which uses VerifyVersionInfo to do the kind of reasonable checks one should for game deployment.

Note if you are using VS 2013 with the v120_xp platform toolset to target Windows XP, you’ll actually be using the Windows 7.1A SDK and #include <VersionHelpers.h> won’t work. You can of course use VerifyVersionInfo directly.

The other major use of GetVersionExW is diagnostic logs and telemetry. In this case, one option is to continue to use that API and make sure you have the right manifest entries in your application to ensure reasonably accurate results. See Manifest Madness for details on what you do here to achieve this. The main thing to keep in mind is that unless you routinely update your code, you will eventually stop getting fully accurate information in a future version of the OS.

Note that it is recommended you put the <compatibility> section in an embedded manifest whether or not you care about the results of GetVersionEx as general best practice. This allows the OS to automatically apply future appcompat fixes based on knowing how the app was originally tested.

For diagnostic logs, another approach that might be a bit more robust is to grab the version number out of a system DLL like kernel32.dll using GetFileVersionInfoW. This approach has a major caveat: Do not try parsing, doing comparisons, or making code assumptions based on the file version you obtain this way; just write it out somewhere. Otherwise you risk recreating the same bad OS version check problem that is better solved with VerifyVersionInfo. This option is not available to Windows Store apps, Windows phone apps, etc. but should work for Win32 desktop apps.

#include <Windows.h>
#include <cstdint>
#include <memory>

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

bool GetOSVersionString( WCHAR* version, size_t maxlen )
{
    WCHAR path[ _MAX_PATH ] = {};
    if ( !GetSystemDirectoryW( path, _MAX_PATH ) )
        return false;

    wcscat_s( path, L"kernel32.dll" );

    //
    // Based on example code from this article
    // http://support.microsoft.com/kb/167597
    //

    DWORD handle;
#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
    DWORD len = GetFileVersionInfoSizeExW( FILE_VER_GET_NEUTRAL, path, &handle );
#else
    DWORD len = GetFileVersionInfoSizeW( path, &handle );
#endif
    if ( !len )
        return false;

    std::unique_ptr<uint8_t> buff( new (std::nothrow) uint8_t[ len ] );
    if ( !buff )
        return false;

#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
    if ( !GetFileVersionInfoExW( FILE_VER_GET_NEUTRAL, path, 0, len, buff.get() ) )
#else
    if ( !GetFileVersionInfoW( path, 0, len, buff.get() ) )
#endif
        return false;

    VS_FIXEDFILEINFO *vInfo = nullptr;
    UINT infoSize;

    if ( !VerQueryValueW( buff.get(), L"", reinterpret_cast<LPVOID*>( &vInfo ), &infoSize ) )
        return false;

    if ( !infoSize )
        return false;

    swprintf_s( version, maxlen, L"%u.%u.%u.%u",
                HIWORD( vInfo->dwFileVersionMS ),
                LOWORD(vInfo->dwFileVersionMS),
                HIWORD(vInfo->dwFileVersionLS),
                LOWORD(vInfo->dwFileVersionLS) );
    
    return true;
}

If there is some other reason you are calling GetVersionExW, you probably shouldn’t be calling it. Checking for a component that might be missing shouldn’t be tied to a version check. For example, if your application requires Media Foundation, you should set a «You must be this high to ride this ride check» like the VersionHelpers.h IsWindowsVistaOrGreater for deployment, but at runtime you should use explicit linking via LoadLibrary or LoadLibaryEx to report an error or use a fallback if MFPLAT.DLL is not found.

Explicit linking is not an option for Windows Store apps. Windows 8.x solves this
particular problem by having a stub MFPLAT.DLL and MFStartUp will return E_NOTIMPL.
See «Who moved my [Windows Media] Cheese»?

Another example: if your application wants to use Direct3D 11.2 if it is available and otherwise uses DirectX 11.0, you’d use set a IsWindowsVistaSP2OrGreater minimum bar for deployment perhaps using the D3D11InstallHelper. Then at runtime, you’d create the DirectX 11.0 device and if it fails, you’d report an error. If you obtain a ID3D11Device, then you’d QueryInterface for a ID3D11Device2 which if it succeeds means you are using an OS that supports DirectX 11.2. See Anatomy of Direct3D 11 Create Device.

If this hypothetical Direct3D application supports Windows XP, you’d use a deployment bar of IsWindowsXPSP2OrGreater or IsWindowsXPSP3OrGreater, and then at run time use explicit linking to try to find the D3D11.DLL. If it wasn’t present, you’d fall back to using Direct3D 9—since we set the minimum bar, we know that DirectX 9.0c or later is always present.

They key point here is that in most cases, you should not use GetVersionEx.

Note that with Windows 10, VerifyVersionInfo and getting the file version stamp via GetFileVersionInfo for kernel32.lib are now subject to the same manifest based behavior as GetVersionEx (i.e. without the manifest GUID for Windows 10, it returns results as if the OS version were 6.2 rather than 10.0).

For universal Windows apps on Windows 10, you can a new WinRT API AnalyticsInfo to get a version stamp string for diagnostic logs and telemetry.

Better than disabling warnings, you can just disable the relevant code as it is intended to be disabled by adding to the file’s preprocessor defines.

Right-click on sqlite3.c, click Properties, Configuration Properties->C/C++->Preprocessor. Make sure you have «all configurations» selected for the configuration and platform dropdowns (unless you only have one platform, then just select the one that’s available) and edit the Preprocessor Definitions to be

SQLITE_WIN32_GETVERSIONEX=0;%(PreprocessorDefinitions)

This will skip the NTDDI_VERSION check since that symbol isn’t defined or is defined incorrectly when your compiler hits sqlite3.c.

There’s this comment in there, too, which may be interesting:

/*
** NOTE: All sub-platforms where the GetVersionEx[AW] functions are
**       deprecated are always assumed to be based on the NT kernel.
*/

The net effect of setting that #define is that your OS is always assumed to be based on Win NT, which it is since you’re Win 8.1 or Win 10 (or greater). ;)

So basically by disabling that warning you’re just making your code slower because it needs to do work to figure out if it’s on WinNT or not.

Better than disabling warnings, you can just disable the relevant code as it is intended to be disabled by adding to the file’s preprocessor defines.

Right-click on sqlite3.c, click Properties, Configuration Properties->C/C++->Preprocessor. Make sure you have «all configurations» selected for the configuration and platform dropdowns (unless you only have one platform, then just select the one that’s available) and edit the Preprocessor Definitions to be

SQLITE_WIN32_GETVERSIONEX=0;%(PreprocessorDefinitions)

This will skip the NTDDI_VERSION check since that symbol isn’t defined or is defined incorrectly when your compiler hits sqlite3.c.

There’s this comment in there, too, which may be interesting:

/*
** NOTE: All sub-platforms where the GetVersionEx[AW] functions are
**       deprecated are always assumed to be based on the NT kernel.
*/

The net effect of setting that #define is that your OS is always assumed to be based on Win NT, which it is since you’re Win 8.1 or Win 10 (or greater). ;)

So basically by disabling that warning you’re just making your code slower because it needs to do work to figure out if it’s on WinNT or not.

Introduction

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

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 Productionready 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.

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.

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.

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;}  

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.

struct WindowsNTOSInfo
{
    DWORD dwMajorVersion;
    DWORD dwMinorVersion;
    WORD wServicePackMajor;    
    };

struct WindowsNTOSInfoEx :WindowsNTOSInfo
{
    BYTE ProductType;
};

const WindowsNTOSInfo KnownVersionsOfWindows[] =
{
    { 6, 3, 0,   },    { 6, 2, 0,   },
    { 6, 1, 1,  },    { 6, 1, 0,  },
    { 5, 1, 3,  },    { 5, 1, 2,  },    { 5, 1, 1,  },    { 5, 1, 0,  },
    { 6, 0, 2,  },    { 6, 0, 1,  },    { 6, 0, 0,  },
    { 5, 2, 2,  },    { 5, 2, 1,  },    { 5, 2, 0,  },

    { 5, 1, 4,  },     { 5, 1, 3,  },     { 5, 1, 2,  },     { 5, 1, 2,  },     { 5, 1, 0,  }, };

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

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

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.

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;
        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
                {
                                                            servicePackCounterSeed = 0;
                }                
            }
        }
        else
        {
                        minorVersionCounterSeed = 0;
        }
    }
    return false;
}

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

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.

="1.0"="UTF-8"="yes"
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">

  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      
      <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.

#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.

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;
}

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

Лучше, чем отключать предупреждения, вы можете просто отключить соответствующий код, поскольку он предназначен для отключения путем добавления в файл препроцессора.

Щелкните правой кнопкой мыши по sqlite3.c, выберите Свойства, Свойства конфигурации → C/С++ → Препроцессор. Убедитесь, что вы выбрали «все конфигурации» для выпадающих списков конфигурации и платформы (если только у вас нет только одной платформы, а затем выберите только ту, которая доступна) и отредактируйте определения препроцессора как

SQLITE_WIN32_GETVERSIONEX=0;%(PreprocessorDefinitions)

Это пропустит проверку NTDDI_VERSION, так как этот символ не определен или определен неверно, когда ваш компилятор попадает на sqlite3.c.

Там тоже есть этот комментарий, который может быть интересным:

/*
** NOTE: All sub-platforms where the GetVersionEx[AW] functions are
**       deprecated are always assumed to be based on the NT kernel.
*/

Сетевой эффект установки #define заключается в том, что ваша ОС всегда считается основанной на Win NT, которая есть, так как вы — Win 8.1 или Win 10 (или больше).;)

Итак, в основном, отключив это предупреждение, вы просто делаете свой код медленнее, потому что ему нужно выполнить работу, чтобы выяснить, есть ли это в WinNT или нет.

The basic question is «why are you calling GetVersionExW in the first place?» The answer to that question determines what you should do instead.

The deprecation warning is there to give developers a heads-up about the appcompat behavior change that started in Windows 8.1. See Windows and Windows Server compatibility cookbook: Windows 8, Windows 8.1, and Windows Server 2012. In short, that function doesn’t return what you think it returns by default.

Historically, badly written OS version checks are the primary source of appcompat bugs for Windows OS upgrades. There’ve been a number of different approaches to trying to mitigate this problem (the AppVerifier version lie, the VerifyVersionInfo API, etc.), and this is the most aggressive to date.

The VersionHelpers.h mentioned in the comments are in the Windows 8.1 SDK that comes with Visual Studio 2013. They are not a new API; they are just utility code that makes use of the VerifyVersionInfo API introduced back in Windows 2000. These functions are for doing «You must be this high to ride this ride» style checks which are the class of version checks that are most often badly written. The code is pretty simple. For example, the IsWindowsVistaSP2OrGreater test is:

VERSIONHELPERAPI
IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
{
    OSVERSIONINFOEXW osvi = {};
    osvi.dwOSVersionInfoSize = sizeof(osvi);
    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;
}

VERSIONHELPERAPI
IsWindowsVistaSP2OrGreater()
{
    return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 2);
}

You don’t need to use VersionHelpers.h as you could just do this kind of code yourself, but they are convenient if you are already using the VS 2013 compiler. For games, I have an article What’s in a version number? which uses VerifyVersionInfo to do the kind of reasonable checks one should for game deployment.

Note if you are using VS 2013 with the v120_xp platform toolset to target Windows XP, you’ll actually be using the Windows 7.1A SDK and #include <VersionHelpers.h> won’t work. You can of course use VerifyVersionInfo directly.

The other major use of GetVersionExW is diagnostic logs and telemetry. In this case, one option is to continue to use that API and make sure you have the right manifest entries in your application to ensure reasonably accurate results. See Manifest Madness for details on what you do here to achieve this. The main thing to keep in mind is that unless you routinely update your code, you will eventually stop getting fully accurate information in a future version of the OS.

Note that it is recommended you put the <compatibility> section in an embedded manifest whether or not you care about the results of GetVersionEx as general best practice. This allows the OS to automatically apply future appcompat fixes based on knowing how the app was originally tested.

For diagnostic logs, another approach that might be a bit more robust is to grab the version number out of a system DLL like kernel32.dll using GetFileVersionInfoW. This approach has a major caveat: Do not try parsing, doing comparisons, or making code assumptions based on the file version you obtain this way; just write it out somewhere. Otherwise you risk recreating the same bad OS version check problem that is better solved with VerifyVersionInfo. This option is not available to Windows Store apps, Windows phone apps, etc. but should work for Win32 desktop apps.

#include <Windows.h>
#include <cstdint>
#include <memory>

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

bool GetOSVersionString( WCHAR* version, size_t maxlen )
{
    WCHAR path[ _MAX_PATH ] = {};
    if ( !GetSystemDirectoryW( path, _MAX_PATH ) )
        return false;

    wcscat_s( path, L"kernel32.dll" );

    //
    // Based on example code from this article
    // http://support.microsoft.com/kb/167597
    //

    DWORD handle;
#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
    DWORD len = GetFileVersionInfoSizeExW( FILE_VER_GET_NEUTRAL, path, &handle );
#else
    DWORD len = GetFileVersionInfoSizeW( path, &handle );
#endif
    if ( !len )
        return false;

    std::unique_ptr<uint8_t> buff( new (std::nothrow) uint8_t[ len ] );
    if ( !buff )
        return false;

#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
    if ( !GetFileVersionInfoExW( FILE_VER_GET_NEUTRAL, path, 0, len, buff.get() ) )
#else
    if ( !GetFileVersionInfoW( path, 0, len, buff.get() ) )
#endif
        return false;

    VS_FIXEDFILEINFO *vInfo = nullptr;
    UINT infoSize;

    if ( !VerQueryValueW( buff.get(), L"", reinterpret_cast<LPVOID*>( &vInfo ), &infoSize ) )
        return false;

    if ( !infoSize )
        return false;

    swprintf_s( version, maxlen, L"%u.%u.%u.%u",
                HIWORD( vInfo->dwFileVersionMS ),
                LOWORD(vInfo->dwFileVersionMS),
                HIWORD(vInfo->dwFileVersionLS),
                LOWORD(vInfo->dwFileVersionLS) );
    
    return true;
}

If there is some other reason you are calling GetVersionExW, you probably shouldn’t be calling it. Checking for a component that might be missing shouldn’t be tied to a version check. For example, if your application requires Media Foundation, you should set a «You must be this high to ride this ride check» like the VersionHelpers.h IsWindowsVistaOrGreater for deployment, but at runtime you should use explicit linking via LoadLibrary or LoadLibaryEx to report an error or use a fallback if MFPLAT.DLL is not found.

Explicit linking is not an option for Windows Store apps. Windows 8.x solves this
particular problem by having a stub MFPLAT.DLL and MFStartUp will return E_NOTIMPL.
See «Who moved my [Windows Media] Cheese»?

Another example: if your application wants to use Direct3D 11.2 if it is available and otherwise uses DirectX 11.0, you’d use set a IsWindowsVistaSP2OrGreater minimum bar for deployment perhaps using the D3D11InstallHelper. Then at runtime, you’d create the DirectX 11.0 device and if it fails, you’d report an error. If you obtain a ID3D11Device, then you’d QueryInterface for a ID3D11Device2 which if it succeeds means you are using an OS that supports DirectX 11.2. See Anatomy of Direct3D 11 Create Device.

If this hypothetical Direct3D application supports Windows XP, you’d use a deployment bar of IsWindowsXPSP2OrGreater or IsWindowsXPSP3OrGreater, and then at run time use explicit linking to try to find the D3D11.DLL. If it wasn’t present, you’d fall back to using Direct3D 9—since we set the minimum bar, we know that DirectX 9.0c or later is always present.

They key point here is that in most cases, you should not use GetVersionEx.

Note that with Windows 10, VerifyVersionInfo and getting the file version stamp via GetFileVersionInfo for kernel32.lib are now subject to the same manifest based behavior as GetVersionEx (i.e. without the manifest GUID for Windows 10, it returns results as if the OS version were 6.2 rather than 10.0).

For universal Windows apps on Windows 10, you can a new WinRT API AnalyticsInfo to get a version stamp string for diagnostic logs and telemetry.

The basic question is «why are you calling GetVersionExW in the first place?» The answer to that question determines what you should do instead.

The deprecation warning is there to give developers a heads-up about the appcompat behavior change that started in Windows 8.1. See Windows and Windows Server compatibility cookbook: Windows 8, Windows 8.1, and Windows Server 2012. In short, that function doesn’t return what you think it returns by default.

Historically, badly written OS version checks are the primary source of appcompat bugs for Windows OS upgrades. There’ve been a number of different approaches to trying to mitigate this problem (the AppVerifier version lie, the VerifyVersionInfo API, etc.), and this is the most aggressive to date.

The VersionHelpers.h mentioned in the comments are in the Windows 8.1 SDK that comes with Visual Studio 2013. They are not a new API; they are just utility code that makes use of the VerifyVersionInfo API introduced back in Windows 2000. These functions are for doing «You must be this high to ride this ride» style checks which are the class of version checks that are most often badly written. The code is pretty simple. For example, the IsWindowsVistaSP2OrGreater test is:

VERSIONHELPERAPI
IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
{
    OSVERSIONINFOEXW osvi = {};
    osvi.dwOSVersionInfoSize = sizeof(osvi);
    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;
}

VERSIONHELPERAPI
IsWindowsVistaSP2OrGreater()
{
    return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 2);
}

You don’t need to use VersionHelpers.h as you could just do this kind of code yourself, but they are convenient if you are already using the VS 2013 compiler. For games, I have an article What’s in a version number? which uses VerifyVersionInfo to do the kind of reasonable checks one should for game deployment.

Note if you are using VS 2013 with the v120_xp platform toolset to target Windows XP, you’ll actually be using the Windows 7.1A SDK and #include <VersionHelpers.h> won’t work. You can of course use VerifyVersionInfo directly.

The other major use of GetVersionExW is diagnostic logs and telemetry. In this case, one option is to continue to use that API and make sure you have the right manifest entries in your application to ensure reasonably accurate results. See Manifest Madness for details on what you do here to achieve this. The main thing to keep in mind is that unless you routinely update your code, you will eventually stop getting fully accurate information in a future version of the OS.

Note that it is recommended you put the <compatibility> section in an embedded manifest whether or not you care about the results of GetVersionEx as general best practice. This allows the OS to automatically apply future appcompat fixes based on knowing how the app was originally tested.

For diagnostic logs, another approach that might be a bit more robust is to grab the version number out of a system DLL like kernel32.dll using GetFileVersionInfoW. This approach has a major caveat: Do not try parsing, doing comparisons, or making code assumptions based on the file version you obtain this way; just write it out somewhere. Otherwise you risk recreating the same bad OS version check problem that is better solved with VerifyVersionInfo. This option is not available to Windows Store apps, Windows phone apps, etc. but should work for Win32 desktop apps.

#include <Windows.h>
#include <cstdint>
#include <memory>

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

bool GetOSVersionString( WCHAR* version, size_t maxlen )
{
    WCHAR path[ _MAX_PATH ] = {};
    if ( !GetSystemDirectoryW( path, _MAX_PATH ) )
        return false;

    wcscat_s( path, L"kernel32.dll" );

    //
    // Based on example code from this article
    // http://support.microsoft.com/kb/167597
    //

    DWORD handle;
#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
    DWORD len = GetFileVersionInfoSizeExW( FILE_VER_GET_NEUTRAL, path, &handle );
#else
    DWORD len = GetFileVersionInfoSizeW( path, &handle );
#endif
    if ( !len )
        return false;

    std::unique_ptr<uint8_t> buff( new (std::nothrow) uint8_t[ len ] );
    if ( !buff )
        return false;

#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
    if ( !GetFileVersionInfoExW( FILE_VER_GET_NEUTRAL, path, 0, len, buff.get() ) )
#else
    if ( !GetFileVersionInfoW( path, 0, len, buff.get() ) )
#endif
        return false;

    VS_FIXEDFILEINFO *vInfo = nullptr;
    UINT infoSize;

    if ( !VerQueryValueW( buff.get(), L"", reinterpret_cast<LPVOID*>( &vInfo ), &infoSize ) )
        return false;

    if ( !infoSize )
        return false;

    swprintf_s( version, maxlen, L"%u.%u.%u.%u",
                HIWORD( vInfo->dwFileVersionMS ),
                LOWORD(vInfo->dwFileVersionMS),
                HIWORD(vInfo->dwFileVersionLS),
                LOWORD(vInfo->dwFileVersionLS) );
    
    return true;
}

If there is some other reason you are calling GetVersionExW, you probably shouldn’t be calling it. Checking for a component that might be missing shouldn’t be tied to a version check. For example, if your application requires Media Foundation, you should set a «You must be this high to ride this ride check» like the VersionHelpers.h IsWindowsVistaOrGreater for deployment, but at runtime you should use explicit linking via LoadLibrary or LoadLibaryEx to report an error or use a fallback if MFPLAT.DLL is not found.

Explicit linking is not an option for Windows Store apps. Windows 8.x solves this
particular problem by having a stub MFPLAT.DLL and MFStartUp will return E_NOTIMPL.
See «Who moved my [Windows Media] Cheese»?

Another example: if your application wants to use Direct3D 11.2 if it is available and otherwise uses DirectX 11.0, you’d use set a IsWindowsVistaSP2OrGreater minimum bar for deployment perhaps using the D3D11InstallHelper. Then at runtime, you’d create the DirectX 11.0 device and if it fails, you’d report an error. If you obtain a ID3D11Device, then you’d QueryInterface for a ID3D11Device2 which if it succeeds means you are using an OS that supports DirectX 11.2. See Anatomy of Direct3D 11 Create Device.

If this hypothetical Direct3D application supports Windows XP, you’d use a deployment bar of IsWindowsXPSP2OrGreater or IsWindowsXPSP3OrGreater, and then at run time use explicit linking to try to find the D3D11.DLL. If it wasn’t present, you’d fall back to using Direct3D 9—since we set the minimum bar, we know that DirectX 9.0c or later is always present.

They key point here is that in most cases, you should not use GetVersionEx.

Note that with Windows 10, VerifyVersionInfo and getting the file version stamp via GetFileVersionInfo for kernel32.lib are now subject to the same manifest based behavior as GetVersionEx (i.e. without the manifest GUID for Windows 10, it returns results as if the OS version were 6.2 rather than 10.0).

For universal Windows apps on Windows 10, you can a new WinRT API AnalyticsInfo to get a version stamp string for diagnostic logs and telemetry.

Понравилась статья? Поделить с друзьями:
  • Error c4996 getch
  • Error c4996 fopen this function or variable may be unsafe
  • Error c4716 должна возвращать значение
  • Error c4703 используется потенциально неинициализированная локальная переменная указатель
  • Error c4700 использована неинициализированная локальная переменная