Skip to content
View in the app

A better way to browse. Learn more.

Tuts 4 You

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Getting real version number of Windows 8.1

Featured Replies

Getting real version number of Windows 8.1:

This doesn't work:
https://gist.github.com/ijat/396663fc902683f9a86be84a7fcd88c5

it returns bogus 5.1 version: 5 major 1 minor


        RtlGetVersionPtr fxPtr = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion");
        if (fxPtr != NULL) {
          rovi.dwOSVersionInfoSize = sizeof(rovi);
          if ( STATUS_SUCCESS == fxPtr(&rovi) ) {
		OSVERSIONINFO os;
        ZeroMemory(&os, sizeof(OSVERSIONINFO));
        os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
		os.dwMajorVersion = rovi.dwMajorVersion;
		os.dwMinorVersion = rovi.dwMinorVersion;
		int sheetmajor = os.dwMajorVersion;  // 5
		int sheetminor = os.dwMinorVersion;  // 1
		return os;
            }
        }

for Windows 10 I use this and it works:
https://codereview.stackexchange.com/questions/107898/get-os-name-in-c

char* majorv_str = TryReadRegistryKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "CurrentMajorVersionNumber");

char* minorv_str = TryReadRegistryKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "CurrentMinorVersionNumber");

  • Author

Use the reg query command in Command Prompt or PowerShell to display registry values. The basic syntax is reg query "KeyName" /v "ValueName". To see all values under a key, omit /v.

So I've used:

reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v CurrentVersion
in command prompt return "6.3" proper value but in the program return 5.1 value.
WTF is going on?

This works as expected for Windows 8.1...

; ***********************************************************************************************************************
;- Global System Libraries
; ***********************************************************************************************************************

Global NtDLL                        = OpenLibrary(#PB_Any, "ntdll.dll")

; ***********************************************************************************************************************
;- Prototypes - NtDLL
; ***********************************************************************************************************************

Prototype.i RtlGetVersion_(dlpVersionInformation)
Global RtlGetVersion_.RtlGetVersion_

RtlGetVersion_ = GetFunction(NtDLL, "RtlGetVersion")

; The RtlGetVersion routine returns version information about the currently running operating system.

Procedure.s GetWindowsVersion()
  Protected RTL.OSVERSIONINFOEX
  
  #STATUS_SUCCESS = #Null
  
  RTL\dwOSVersionInfoSize = SizeOf(RTL)
  
  If RtlGetVersion_
    If RtlGetVersion_(@RTL.OSVERSIONINFOEX) = #STATUS_SUCCESS
      
      OS_dwMajor = RTL\dwMajorVersion
      OS_dwMinor = RTL\dwMinorVersion
      OS_dwBuild = RTL\dwBuildNumber
      
      ProcedureReturn Str(OS_dwMajor) + "." + OS_dwMinor + "." + OS_dwBuild
    EndIf
  EndIf
  
  ProcedureReturn "#NULL"
EndProcedure

Debug GetWindowsVersion()

image.png

Ted.

  • Author
15 minutes ago, Teddy Rogers said:

This works as expected for Windows 8.1...

; ***********************************************************************************************************************
;- Global System Libraries
; ***********************************************************************************************************************

Global NtDLL                        = OpenLibrary(#PB_Any, "ntdll.dll")

; ***********************************************************************************************************************
;- Prototypes - NtDLL
; ***********************************************************************************************************************

Prototype.i RtlGetVersion_(dlpVersionInformation)
Global RtlGetVersion_.RtlGetVersion_

RtlGetVersion_ = GetFunction(NtDLL, "RtlGetVersion")

; The RtlGetVersion routine returns version information about the currently running operating system.

Procedure.s GetWindowsVersion()
  Protected RTL.OSVERSIONINFOEX
  
  #STATUS_SUCCESS = #Null
  
  RTL\dwOSVersionInfoSize = SizeOf(RTL)
  
  If RtlGetVersion_
    If RtlGetVersion_(@RTL.OSVERSIONINFOEX) = #STATUS_SUCCESS
      
      OS_dwMajor = RTL\dwMajorVersion
      OS_dwMinor = RTL\dwMinorVersion
      OS_dwBuild = RTL\dwBuildNumber
      
      ProcedureReturn Str(OS_dwMajor) + "." + OS_dwMinor + "." + OS_dwBuild
    EndIf
  EndIf
  
  ProcedureReturn "#NULL"
EndProcedure

Debug GetWindowsVersion()

image.png

Ted.

Thanks. I think that my Windows 8.1 is corrupted or something,
I can't even find Windows Defender on that Windows,
unfortunately I only have 2 backups of Windows with Windows 8.1.

  • Author
Here is my code:
	RTL_OSVERSIONINFOW rovi = { 0 };
    HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
    if (hMod)
	{
        RtlGetVersionPtr fxPtr = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion");
        if (fxPtr != NULL)
		{

          rovi.dwOSVersionInfoSize = sizeof(rovi);
          if ( STATUS_SUCCESS == fxPtr(&rovi) )
		  {
		OSVERSIONINFO os;
        ZeroMemory(&os, sizeof(OSVERSIONINFO));
        os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
		os.dwMajorVersion = rovi.dwMajorVersion;
		os.dwMinorVersion = rovi.dwMinorVersion;

		int sheetmajor = os.dwMajorVersion;  // 5
		int sheetminor = os.dwMinorVersion;  // 1

		return os;
            }
        }
    }
returns v5.1
Here is registry key read:
char* version_str = TryReadRegistryKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "CurrentVersion");

char* TryReadRegistryKey(HKEY hkey,char* regpath, char* valuename)
{
LONG lResult;
HKEY hKey2;
DWORD dwType;
DWORD dwBytes = 100;

lResult = RegOpenKeyEx(hkey, regpath, 0, KEY_READ|KEY_QUERY_VALUE|KEY_WOW64_32KEY, &hKey2);  
if (lResult != ERROR_SUCCESS)   
    return 0;

lResult = RegQueryValueEx(hKey2, valuename, 0, &dwType, (LPBYTE)buffer_keep, &dwBytes);  

RegCloseKey(hKey2);

if (lResult == ERROR_SUCCESS)
return buffer_keep;

return 0;
}

also return v5.1.

@Teddy Rogers I will be very great-full if you post an compiled exe if that is possible.

) src & exe ...

GetWinVer_src.zip

2026-04-10_014128.jpg

Edited by boot

4 hours ago, boot said:

) src & exe ...

GetWinVer_src.zip

2026-04-10_014128.jpg

@boot , I was unable to compile your code for x86 on VS 2022, so I wrote my own based off of what you provided. I was able to compile (x86/x64) and run this code on WIN7+:

// 
// Windows Version Reader by Stingered (2026)
// Compatible: Windows 7 through Windows 11 (hopefully)
//

#include <Windows.h>
#include <stdio.h>
#include <iostream>

typedef NTSTATUS(NTAPI* pfnRtlGetVersion)(PRTL_OSVERSIONINFOW);

void GetRealVersion(DWORD* major, DWORD* minor, DWORD* build, DWORD* revision) {
	HMODULE hMod = GetModuleHandleW(L"ntdll.dll");
	if (hMod) {
		pfnRtlGetVersion RtlGetVersion = (pfnRtlGetVersion)GetProcAddress(hMod, "RtlGetVersion");
		if (RtlGetVersion) {
			OSVERSIONINFOEXW osvi = { 0 };
			osvi.dwOSVersionInfoSize = sizeof(osvi);

			if (RtlGetVersion((PRTL_OSVERSIONINFOW)&osvi) == 0) { // STATUS_SUCCESS
				if (major) *major = osvi.dwMajorVersion;
				if (minor) *minor = osvi.dwMinorVersion;
				if (build) *build = osvi.dwBuildNumber;
			}
		}
	}

	HKEY hKey;
	if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) {
		DWORD ubr = 0;
		DWORD size = sizeof(ubr);
		if (RegQueryValueExW(hKey, L"UBR", NULL, NULL, (LPBYTE)&ubr, &size) == ERROR_SUCCESS) {
			if (revision) *revision = ubr;
		}
		RegCloseKey(hKey);
	}
}

int main() {
	std::cout << "\r\n  Windows OS Version Reader\r\n";
	std::cout << "  Compatibility: Windows 7 through Windows 11 (hopefully)\r\n";

	DWORD major = 0;
	DWORD minor = 0;
	DWORD build = 0;
	DWORD revision = 0;

	GetRealVersion(&major, &minor, &build, &revision);

	printf("\r\n  Windows Version -> %u.%u.%u.%u\r\n",
		major,
		minor,
		build,
		revision);

	printf("\n");
	system("pause");
	return 0;
}

Edited by Stingered

  • Author
char* version_str = TryReadRegistryKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "CurrentVersion");  // CurrentVersion"
if (version_str!=0&&((finded = strstr(version_str,".")) != NULL))

// doesn't work in Windows 8.1 neither on Windows 10.

	RTL_OSVERSIONINFOW rovi = { 0 };
    HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
    if (hMod)
	{
        RtlGetVersionPtr fxPtr = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion");
        if (fxPtr != NULL)
		{

          rovi.dwOSVersionInfoSize = sizeof(rovi);
          if ( STATUS_SUCCESS == fxPtr(&rovi) )
		  {
		OSVERSIONINFO os;
        ZeroMemory(&os, sizeof(OSVERSIONINFO));
        os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
		os.dwMajorVersion = rovi.dwMajorVersion;
		os.dwMinorVersion = rovi.dwMinorVersion;
		return os;
            }
        }
    }

// doesn't work in Windows 8.1 neither on Windows 10.


    PPEB2 pPeb = NtCurrentPeb();

	if (pPeb!=NULL)
	{
	OSVERSIONINFO os;
        ZeroMemory(&os, sizeof(OSVERSIONINFO));
        os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	os.dwMajorVersion = pPeb->OSMajorVersion;
	os.dwMinorVersion = pPeb->OSMinorVersion;
	return os;
	}
// works on all versions of Windows including Windows XP; Windows 8.1, Windows 10, Windows 11.

char* majorv_str = TryReadRegistryKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "CurrentMajorVersionNumber");
// Works on Windows 10 and Windows 11.

So RtlGetVersion doesn't work on Windows 8.1 neither TryReadRegistryKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "CurrentVersion"); "CurrentVersion" seems to be virtualized.

So I will use TryReadRegistryKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "CurrentMajorVersionNumber"); and if fails PPEB2 pPeb = NtCurrentPeb(); from now.
Thank you @boot

On 4/9/2026 at 11:20 PM, CodeExplorer said:

I will be very great-full if you post an compiled exe if that is possible.

Apologies for the late response. Let me know if this was not what you wanted...

Ted.

RtlGetVersion.zip

  • Author
12 hours ago, Teddy Rogers said:

Apologies for the late response. Let me know if this was not what you wanted...

Ted.

RtlGetVersion.zip

Thanks. Your example works, but in my Visual C++ program RtlGetVersion doesn't work, probability I'm missing some config.
I was able to fix this by @boot samples; all works fine now.

19 minutes ago, CodeExplorer said:

Thanks. Your example works, but in my Visual C++ program RtlGetVersion doesn't work, probability I'm missing some config.
I was able to fix this by @boot samples; all works fine now.

I didn't try Teddy's, but this method seems to get the same results I had earlier and is supposedly Windows 2000+ (off of stackoverflow). Seems very similar to my earlier code (tiny edits for granularity).

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

typedef LONG(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOEXW);

DWORD GetUBR()
{
	HKEY hKey;
	DWORD ubr = 0;
	DWORD size = sizeof(ubr);

	if (RegOpenKeyExW(
		HKEY_LOCAL_MACHINE,
		L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
		0,
		KEY_READ,
		&hKey) == ERROR_SUCCESS)
	{
		RegQueryValueExW(hKey, L"UBR", NULL, NULL, (LPBYTE)&ubr, &size);
		RegCloseKey(hKey);
	}

	return ubr;
}

int main()
{
	HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
	if (!ntdll) {
		printf("Failed to load ntdll.dll\n");
		return 1;
	}

	RtlGetVersionPtr RtlGetVersion =
		(RtlGetVersionPtr)GetProcAddress(ntdll, "RtlGetVersion");

	if (!RtlGetVersion) {
		printf("RtlGetVersion not found\n");
		return 1;
	}

	RTL_OSVERSIONINFOEXW ver = { 0 };
	ver.dwOSVersionInfoSize = sizeof(ver);

	if (RtlGetVersion(&ver) != 0) {
		printf("RtlGetVersion failed\n");
		return 1;
	}

	DWORD ubr = GetUBR();

	printf("Version: %lu.%lu.%lu.%lu\n",
		ver.dwMajorVersion,
		ver.dwMinorVersion,
		ver.dwBuildNumber,
		ubr
	);

	return 0;
}

Edited by Stingered

Create an account or sign in to comment

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.