Getting OS build version from Win32 Api C++
Option 0: (per RbMm) Use [RtlGetVersion] from the driver development kit.
Option 1: [Updated] Grab the version number of a system DLL like kernel32.dll. MSDN used to bless this approach, saying:
To obtain the full version number for the operating system, call the GetFileVersionInfo function on one of the system DLLs, such as Kernel32.dll, then call VerQueryValue to obtain the \StringFileInfo\\ProductVersion subblock of the file version information. [From an Internet Archive snapshot of MSDN circa 2017]
That would look something like this:
// Quick hack without error checking.
#include <cassert>
#include <iomanip>
#include <iostream>
#include <vector>
#include <Windows.h>
int main() {
const auto system = L"kernel32.dll";
DWORD dummy;
const auto cbInfo =
::GetFileVersionInfoSizeExW(FILE_VER_GET_NEUTRAL, system, &dummy);
std::vector<char> buffer(cbInfo);
::GetFileVersionInfoExW(FILE_VER_GET_NEUTRAL, system, dummy,
buffer.size(), &buffer[0]);
void *p = nullptr;
UINT size = 0;
::VerQueryValueW(buffer.data(), L"\\", &p, &size);
assert(size >= sizeof(VS_FIXEDFILEINFO));
assert(p != nullptr);
auto pFixed = static_cast<const VS_FIXEDFILEINFO *>(p);
std::cout << HIWORD(pFixed->dwFileVersionMS) << '.'
<< LOWORD(pFixed->dwFileVersionMS) << '.'
<< HIWORD(pFixed->dwFileVersionLS) << '.'
<< LOWORD(pFixed->dwFileVersionLS) << '\n';
return 0;
}
Note that the original MSDN link now redirects to a newer documentation set that doesn't mention this approach. I suppose that means this is no longer a supported technique, and, presumably, all the compatibility hacks for older code might prevent an application from getting the actual answer.
Option 2: Query the registry, specifically:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
which has values for CurrentMajorVersionNumber
, CurrentMinorVersionNumber
, and CurrentBuildNumber
.
I can't find official documentation for these values, so this may not be MSDN-approved or future-proof.
Option 3: Use GetProductInfo if available and fall back to GetVersionInfo if it's not.
anon
Updated on June 18, 2022Comments
-
anon almost 2 years
I am trying to find the build version of Windows Server 2016 machines, for example RS1 or RS3. There was an API to do this -
GetVersionEx()
- but is now deprecated.MSDN says to use Version Helper Functions instead.
I want the build version, for ex: 1607 for RS1.
Is there an API to get this?
-
David Heffernan over 6 yearsUse the version helper functions
-
anon over 6 yearsIs there a way to get the version or not? If not why is that not clearly stated anywhere? Like I said I don't want the helper version stuff. How am I suppose to differentiate between the WS 2016 RS1 and RS3 image.
-
Richard Chambers over 6 years
-
anon over 6 yearsAlready looked at that. IsWindowsServer() doesn't solve my problem.
-
Richard Chambers over 6 yearsFrom Targeting your application for Windows there is this function VerifyVersionInfo function though in "Windows 10, the VerifyVersionInfo function has also been deprecated."
-
Remy Lebeau over 6 yearsThe version helper functions dont return the actual version number, like
GetVersion/Ex()
does. They compare the version number to a requested version and return the result of the comparison. To learn the exact version number, you would have to make several comparisons, which is tedious. -
Remy Lebeau over 6 yearsIf you need to discover the exact version number, you can use
RtlGetVersion()
,NetServerGetInfo()
orNetWkstaGetInfo()
, which are not deprecated or subject to manifestation (yet?). Or, do what MSDN suggests. -
Mike Vine over 6 yearsThis seems like an X/Y problem. What do you want the version number for?
-
anon over 6 yearsRtlGetVersion works for me. Loaded the ntdll.dll and got the RtlGetVersion. %HMODULE ntDll = GetModuleHandleW(L"ntdll.dll"); rtlGetVersion getVersion = (rtlGetVersion)GetProcAddress(ntDll, "RtlGetVersion"); %
-
-
RbMm over 6 yearswhy not use option 0 - call
RtlGetVersion
or undocumentedRtlGetNtVersionNumbers
. anyway this more simply and fast compare this way -
zett42 over 6 years@RbMm So
RtlGetVersion
does not lie likeGetVersionEx
if you don't have the latestCompatibility
entries in manifest? -
RbMm over 6 years@zett42 - no,
RtlGetVersion
until always return true windows version, and not look for manifest -
RbMm over 6 years@zett42 - however the latest build windows number, where i look this is 15063 (and here RtlGetVersion still read correct values from PEB), not look more resent builds. interesting link, but no more resent build under hand now
-
Anders over 6 years@RbMm I think RtlGetVersion is affected by the compatibility tab settings on a .exe.
-
RbMm over 6 years@Anders - you can look binary code of
RtlGetVersion
(under debugger or disassembler) - it enough simply - unconditionally read this values from processPEB
. however i not view the latest build, but on 15063 stil true version -
Anders over 6 years@RbMm And who fills the PEB (You can mess with the PE file to set some of these values)? Anyway, looking at the code is pointless because those functions get hooked by aclayers.dll.
-
RbMm over 6 years@Anders yes :) you was correct. the
RtlGetVersion
is hooked by aclayer.dll and return "compatible" version. butRtlGetNtVersionNumbers
not hooked and return correct version number. in the process PEB also real values -
Anders over 6 years@RbMm But you can hex-edit the PE file so that those PEB fields have whatever number you want. I'm sure it is only a matter of time until RtlGetNtVersionNumbers is hooked as well.
-
RbMm over 6 years@Anders - no, PEB this is not part of pe file but semi-documented structure in memory (process environment block) - allocated by kernel in process creation time. think here always must be correct values, which need for internal system work. are
RtlGetNtVersionNumbers
will be hooked - don't know. may be yes. interesting that before win10 this function simply return values hard-coded in ntdll.dll. now (win 10) it read it from peb -
Anders over 6 years@RbMM I know perfectly well what the PEB is. The PEB can be filled with values from the PE file if you tweak it correctly.
-
RbMm over 6 years@Anders - what you mean ? that ntdll or shim under some case can read major/minor values from exe optionalheader and write it to peb ?
-
Anders over 6 years@RbMm IMAGE_LOAD_CONFIG_DIRECTORY::CSDVersion (if not zero) is written to the PEB etc. I assume it is ntdll that does it when you create the process. The major/minor version PE fields are somewhere else and not documented AFAIK.
-
RbMm over 6 years@Anders - dont know. even if use not 0 MajorVersion, MinorVersion, CSDVersion i view under peb real os values. however may be i not set some flags/etc. not research this early, but until not view visible effect from play with
IMAGE_LOAD_CONFIG_DIRECTORY
in this direction. however this already some offtopic for original question - theIMAGE_LOAD_CONFIG_DIRECTORY
control who build of exe. if it patched.. but any code can be patched. -
Charles Oppermann over 4 years" MSDN blesses this approach" I don't see anything on the linked page that discusses using the build number of kernel32.dll as being "blessed" or otherwise endorsed. Maybe it was previously discussed, but not as of this writing. I've had cases where the build number of kernel32.dll was different from what's reported via winver.exe.
-
Adrian McCarthy over 4 years@CharlesOppermann: The MSDN link is now redirected to Microsoft's newer documentation set, and the newer version doesn't have it. I'll update the answer with the relevant bit as captured by the Wayback Machine.
-
ceztko over 3 yearsGreat there's
RtlGetVersion
! Requiring installing DDK just for one function may be overkill, though. Can you integrate the answer pointing to this gist that has just the useful declarations?