The API GetVersionEx() continues to work in Windows 8.1+, but Microsoft has altered its functionality. From MSDN (emphasis mine):
With the release of Windows 8.1, the behavior of the GetVersionEx API
has changed in the value it will return for the operating system
version. The value returned by the GetVersionEx function now depends
on how the application is manifested.
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.
What you need to do is add the proper GUID(s) to your application (.exe/.dll) binaries (via manifest XML information). In other words, if you specifically state your application supports 8.1, GetVersionEx() will return proper information when running on Windows 8.1. If you do not, GetVersionEx() will lie to you.
See Targeting your application For Windows 8.1 for a list of GUIDs.
Also covered here and here.
GUID List for the Lazy
- Vista / Server 2008:
{e2011457-1546-43c5-a5fe-008deee3d3f0}
- Windows 7 / Server 2008 R2:
{35138b9a-5d96-4fbd-8e2d-a2440225f93a}
- Windows 8 / Server 2012:
{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}
- Windows 8.1 / Server 2012 R2 :
{1f676c76-80e1-4239-95bb-83d0f6d0da78}
- Windows 10 / Server 2016:
{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}
As for Windows Server 2019, I'm not sure that a new GUID has been released. Please comment if you know more!