Lazarus

Programming => General => Topic started by: dculp on April 06, 2025, 03:55:35 pm

Title: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: dculp on April 06, 2025, 03:55:35 pm
I'm trying to determine the Windows version on my Windows 11 computer. I use the following code from BobDog (https://forum.lazarus.freepascal.org/index.php/topic,60982.15.html - page 2, reply 18). However, although my computer is Win11, RtlGetNtVersionNumbers returns -
Major version 10
Minor version 0
build number 26100

Thanks.

Lazarus 3.8 (rev lazarus_3_8) FPC 3.2.2 i386-win32-win32/win64

Code: Pascal  [Select][+][-]
  1. program Windows_version_100a;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. procedure RtlGetNtVersionNumbers(major:pointer;minor:pointer;build:pointer)cdecl external 'ntdll.dll' name 'RtlGetNtVersionNumbers';
  6.  
  7. procedure getversion(var maj,min,bld:dword);
  8. begin
  9. RtlGetNtVersionNumbers(@maj,@min,@bld);
  10. bld:=lo(bld);
  11. end;
  12.  
  13. var
  14. maj,min,bld:dword;
  15. begin
  16. maj:=0;min:=0;bld:=0;
  17. getversion(maj,min,bld);
  18. writeln('Major version ',maj);
  19. writeln('Minor version ',min);
  20. writeln('build number ',bld);
  21. writeln('press return to end . . .');
  22. readln;
  23. end.                
  24.  
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: TRon on April 06, 2025, 04:02:01 pm
https://www.lifewire.com/windows-version-numbers-2625171
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: dculp on April 06, 2025, 04:13:29 pm
@TRon - Your link gives a list of the Windows versions. I need the Pascal code (or code that I can modify to Pascal) that will return the Windows 11 version (rather than returning Win10 when I'm actually running Win11).
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: TRon on April 06, 2025, 04:16:40 pm
Code: Pascal  [Select][+][-]
  1. if bld >= 22000 then writeln('windows 11');
  2.  
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: AlexTP on April 06, 2025, 04:39:19 pm
I just added some info to the wiki, https://wiki.freepascal.org/Windows_version .
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: 440bx on April 06, 2025, 06:57:33 pm
It used to be that RtlGetNtVersionNumbers returned the true Windows version but, no longer :(

Somewhere along Win 10, the implementation changed and now the function returns values that are stored "somewhere" (likely the PEB), telling the calling program the version is whatever Windows wants the program to think it is.

I don't run Windows 11 (and never will) but, if I were running it and needed some way of finding out the version number, I'd check the product version of csrss.exe, that exe is a critical component of Windows and usually accurate information about Windows can be had by "inspecting" that file.

Try this, use Explorer to go to system32, find csrss.exe, right click on it and select properties.  The properties window has a "version" tab.  Look in that tab.  If the product version says "10.xx.xx" then, it's quite likely cumbersome and possibly difficult to tell Win11 from Win10 (but, there is probably a way, fortunately, I don't have to find out and, won't have to find out either :) )

HTH.
 
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: dculp on April 06, 2025, 07:20:33 pm
@AlexTP - I tried the code from your link but I get numerous compiler errors linked the closing "end." statement. It seems to think this is a Windows program but I want to run it as a console. (I've added LCL package as a required package for Win32Proc.) It makes no difference whether WindowsVersionName is actually called (can comment out).

Code: Pascal  [Select][+][-]
  1. program windows_version_200a;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses    Win32Proc;
  6.  
  7. var VersionName: string;
  8.  
  9. function WindowsVersionName: string;
  10. begin
  11.   Result:= '?';
  12.  
  13.   case WindowsVersion of
  14.     wv95:     Result:= 'Windows 95';
  15.     wvNT4:    Result:= 'Windows NT v.4';
  16.     wv98:     Result:= 'Windows 98';
  17.     wvMe:     Result:= 'Windows Me';
  18.     wv2000:   Result:= 'Windows 2000';
  19.     wvXP:     Result:= 'Windows XP';
  20.     wvServer2003: Result:= 'Windows Server 2003';
  21.     wvVista:  Result:= 'Windows Vista';
  22.     wv7:      Result:= 'Windows 7';
  23.     wv8:      Result:= 'Windows 8';
  24.     wv8_1:    Result:= 'Windows 8.1';
  25.     wv10:     Result:= 'Windows 10';
  26.     wv11:     Result:= 'Windows 11';
  27.     //etc.
  28.     //see possible values in the unit "win32proc" in "lcl/interfaces/win32/win32proc.pp"
  29.   end;
  30. end;
  31.  
  32. begin
  33.   VersionName:= WindowsVersionName;
  34. end.                          
  35.  


Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: dculp on April 06, 2025, 07:41:15 pm
@440bx - There is no csrss.exe in my Windows\System32 folder. It is only in the following folder (doesn't look promising) and the Properties doesn't have a Version tab.
C:\Windows\WinSxS\amd64_microsoft-windows-csrss_31bf3856ad364e35_10.0.26100.1_none_55d78c384ca248d1\
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: 440bx on April 06, 2025, 09:53:56 pm
@dculp

if not under system32 then maybe syswow64.  There should definitely be a copy of csrss.exe somewhere in a Windows subdirectory. 

I am amazed that csrss.exe would not have version information.  That would be quite a departure.

Would you please check again for a copy of csrss.exe in some Windows subdirectory ? and then try getting the version from that file.

Just in case, if you use Process Hacker, System Informer or Process Explorer, you can find the running copy of csrss.exe and get information about it by right clicking on it and selecting properties.  In the worst case, check out the "Strings" tab, one of the listed strings should reveal the csrss.exe version.

The Windows little system utilities often fall very short of providing relevant information, that's why I don't even mention them.

HTH.

Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: dculp on April 06, 2025, 11:33:56 pm
@440bx -
I searched my entire C: drive for csrss*. (I use FreeCommander with "Show hidden files".) Only 2 files were found -
csrss.exe.mui in C:\Windows\WinSxS\amd64_microsoft-windows-csrss.resources_31bf3856ad364e35_10.0.26100.1_en-us_d784b37749fd398a\
csrss.exe in C:\Windows\WinSxS\amd64_microsoft-windows-csrss_31bf3856ad364e35_10.0.26100.1_none_55d78c384ca248d1\

In the Properties\Details tab for the latter file, the version is 10.0.26100.1, date modified 4/1/2024. Per my original post, 26100 is the build number returned by RtlGetNtVersionNumbers; however, RtlGetNtVersionNumbers also indicates that the Major Version is 10.

Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: 440bx on April 07, 2025, 12:26:39 am
@dculp,

Thank you for checking.

I have to say, I am very surprised that no csrss.exe is found in a subdirectory of Windows. 

Another question for you: when you ask for system information from the Control Panel, does it say you're running Win 10 or Win 11 ?   

The reason I ask is because if it says Win 11, a disassembly of the .cpl file might show where it's getting that value from.  Who knows, maybe it checks that the build number is greater than some value and if it is, it shows Win 11.  I wouldn't put it past MS to do something like that.

Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: dculp on April 07, 2025, 03:17:27 am
Actually csrss.exe was found in Windows subdirectory WinSxS\amd64_microsoft-windows-csrss_31bf3856ad364e35_10.0.26100.1_none_55d78c384ca248d1\
Note that the subdirectory name contains the Windows version number 10.0.26100.1.

My Win11 System Information shows -
   OS Name   Microsoft Windows 11 Pro
   Version      10.0.26100 Build 26100
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: 440bx on April 07, 2025, 04:16:44 am
Actually csrss.exe was found in Windows subdirectory WinSxS\amd64_microsoft-windows-csrss_31bf3856ad364e35_10.0.26100.1_none_55d78c384ca248d1\
Note that the subdirectory name contains the Windows version number 10.0.26100.1.
I expected a copy in Windows\system32 because that's where it resides in the original installation.  Strange that it isn't there.

My Win11 System Information shows -
   OS Name   Microsoft Windows 11 Pro
   Version      10.0.26100 Build 26100
That makes sense.  The "OS Name" is _not_ the same thing as the OS Version.  Notice that the OS Version still says 10.  The OS Name is probably in the registry.

Maybe regedit can find a string "Microsoft Windows 11 Pro" somewhere in there. Might be worth a try.

Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: Khrys on April 07, 2025, 07:05:53 am
I've been successfully using the following function to check for specific build numbers. Not exactly what you asked for, but maybe it helps:

Code: Pascal  [Select][+][-]
  1. {$push}{$packrecords C}
  2.  
  3. function VerSetConditionMask(ConditionMask: ULONGLONG; TypeMask: DWORD; Condition: BYTE): ULONGLONG; stdcall;
  4.          external kernel32 name 'VerSetConditionMask';
  5. function VerifyVersionInfo(lpVersionInformation: LPVOID; dwTypeMask: DWORD; dwlConditionMask: DWORDLONG): BOOL; stdcall;
  6.          external kernel32 name 'VerifyVersionInfoA';
  7.  
  8. /// Returns True if the build number of the currently running Windows version is greater than or equal to [BuildNumber].
  9. function WindowsBuildNewerThan(BuildNumber: DWORD): Boolean;
  10. const
  11.   VER_BUILDNUMBER = $00000004;
  12.   VER_GREATER_EQUAL = $03;
  13. type
  14.   OSVERSIONINFOEX = record
  15.     dwOSVersionInfoSize, dwMajorVersion, dwMinorVersion: DWORD;
  16.     dwBuildNumber, dwPlatformId: DWORD;
  17.     szCSDVersion: array[0..127] of CHAR;
  18.     wServicePackMajor, wServicePackMinor: WORD;
  19.     wSuiteMask: WORD;
  20.     wProductType: BYTE;
  21.     wReserved: BYTE;
  22.   end;
  23. var
  24.   Version: OSVERSIONINFOEX;
  25. begin
  26.   Version := Default(OSVERSIONINFOEX);
  27.   Version.dwOSVersionInfoSize := SizeOf(Version);
  28.   Version.dwBuildNumber := BuildNumber;
  29.   Result := VerifyVersionInfo(@Version, VER_BUILDNUMBER, // Make sure the .exe has a manifest (i.e. at .rsrc/MANIFEST/1)
  30.                               VerSetConditionMask(0, VER_BUILDNUMBER, VER_GREATER_EQUAL));
  31. end;
  32.  
  33. {$pop}
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: Zvoni on April 07, 2025, 10:06:27 am
Errr..... Look it up in the Registry?
Code: [Select]
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: dseligo on April 07, 2025, 10:28:43 am
Errr..... Look it up in the Registry?
Code: [Select]
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion

This is from my Windows' System, About:
Code: Text  [Select][+][-]
  1. Edition Windows 11 Pro
  2. Version 24H2
  3. Installed on    ‎07.‎12.‎2024.
  4. OS build        26100.3476
  5. Experience      Windows Feature Experience Pack 1000.26100.54.0

In attachment is screenshot of registry key you suggested.
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: Zvoni on April 07, 2025, 11:31:46 am
You're right.
Just found other sites reporting that the "Product Name" Reg-Keys for Win11 still report Win10.

OTOH, "10.0.22000" is the initial Build for Windows 11
Soooo... Query above Reg-Keys (in my Screenshot WinREVersion resp. LCUVer in dseligo's Screenshot) additionally to Reg-Key "CurrentBuild"/"CurrentBuildNumber"?
Code: Pascal  [Select][+][-]
  1. If Major='10' And Minor='0' And Build>='22000' Then Win11 Else Win10

Which is basically what TRon posted in Reply 3
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: dculp on April 07, 2025, 12:00:48 pm
I just added some info to the wiki, https://wiki.freepascal.org/Windows_version .

In your code "Using Win32Proc Lazarus unit", I stripped everything out except the uses statement and begin..end (code #1 below). I still get the attached compiler error messages. If I remove the Win32Proc uses then it compiles without errors.

When I hover over Win32Proc I get -
   unit Win32Proc
   D:\Lazarus_32bit_3.8.x\lcl\interfaces\win32\win32proc.pp(17,6)
   Package LCL

In win32proc.pp it specifically says, "This file is part of the Lazarus Component Library (LCL)".

In the Project Inspector I have the LCL package installed under Required Packages (see attached) so I assume that I wouldn't need Win32Proc in my uses statement. However, if I remove it (code #2)  then I get compiler errors "Identifier not found" for WindowsVersion and all of the identifiers in the case statement (which are all in win32proc.pp). Also, "duplicate case label" and other errors.

What am I missing?

Code #1 -
Code: Pascal  [Select][+][-]
  1. program windows_version_211a;
  2.  
  3. uses  Win32Proc;
  4.  
  5. begin
  6. end.
  7.  


Code #2 -
Code: Pascal  [Select][+][-]
  1. program windows_version_200a;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. // uses    Win32Proc;
  6.  
  7. var VersionName: string;
  8.  
  9. function WindowsVersionName: string;
  10. begin
  11.   Result:= '?';
  12.  
  13.   case WindowsVersion of
  14.     wv95:     Result:= 'Windows 95';
  15.     wvNT4:    Result:= 'Windows NT v.4';
  16.     wv98:     Result:= 'Windows 98';
  17.     wvMe:     Result:= 'Windows Me';
  18.     wv2000:   Result:= 'Windows 2000';
  19.     wvXP:     Result:= 'Windows XP';
  20.     wvServer2003: Result:= 'Windows Server 2003';
  21.     wvVista:  Result:= 'Windows Vista';
  22.     wv7:      Result:= 'Windows 7';
  23.     wv8:      Result:= 'Windows 8';
  24.     wv8_1:    Result:= 'Windows 8.1';
  25.     wv10:     Result:= 'Windows 10';
  26.     wv11:     Result:= 'Windows 11';
  27.     //etc.
  28.     //see possible values in the unit "win32proc" in "lcl/interfaces/win32/win32proc.pp"
  29.   end;
  30. end;
  31.  
  32. begin
  33.   VersionName:= WindowsVersionName;
  34. end.                    
  35.  
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: Zvoni on April 07, 2025, 12:05:57 pm
What am I missing?
That TRon and me basically gave you the Solution in regards to using the WinApi-Solution from your first post
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: dculp on April 07, 2025, 12:31:19 pm
@Zvoni -
I agree. However, I still want to understand why my code won't compile, even if it may not be the best solution to my original question.
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: Zvoni on April 07, 2025, 12:48:05 pm
@Zvoni -
I agree. However, I still want to understand why my code won't compile, even if it may not be the best solution to my original question.
Just because you declared a required Package, doesn't mean, that your Program "USES" the units within....
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: dculp on April 07, 2025, 01:02:40 pm
So what do I need to do to get this to compile?

Code: Pascal  [Select][+][-]
  1. program windows_version_211a;
  2.  
  3. uses  Win32Proc;
  4.  
  5. begin
  6. end.
  7.  
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: Fibonacci on April 07, 2025, 02:58:29 pm
So what do I need to do to get this to compile?

Code: Pascal  [Select][+][-]
  1. program windows_version_211a;
  2.  
  3. uses  Win32Proc;
  4.  
  5. begin
  6. end.
  7.  

1. Add LCL to the project packages
2. Add unit Interfaces to the uses

On my Windows 10, it shows Windows 8



Code: Pascal  [Select][+][-]
  1. uses Windows;
  2.  
  3. procedure RtlGetNtVersionNumbers(MajorVersion, MinorVersion, BuildNumber: PDWORD); stdcall; external 'ntdll.dll';
  4.  
  5. function winGetVersion: dword;
  6. var
  7.   major, minor: dword;
  8. begin
  9.   RtlGetNtVersionNumbers(@major, @minor, nil);
  10.   result := (major*100)+(minor*10);
  11. end;
  12.  
  13. function winGetBuild: dword;
  14. var
  15.   build: dword;
  16. begin
  17.   RtlGetNtVersionNumbers(nil, nil, @build);
  18.   result := pword(@build)^;
  19. end;
  20.  
  21. begin
  22.   writeln('Windows 10 or newer? ', winGetVersion >= 1000);
  23.   writeln('Windows 11 or newer? ', (winGetVersion >= 1000) and (winGetBuild >= 22000));
  24.   readln;
  25. end.
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: LV on April 07, 2025, 04:07:30 pm
I'm using Windows 11, and I think it would be interesting to check it out.  ;)

Code: Pascal  [Select][+][-]
  1. program DetectWindows11;
  2.  
  3. uses
  4.   Windows, SysUtils;
  5.  
  6. procedure RtlGetNtVersionNumbers(out MajorVersion, MinorVersion, BuildNumber: DWORD); stdcall; external 'ntdll.dll';
  7.  
  8. function IsWindows11OrNewer: Boolean;
  9. var
  10.   Major, Minor, BuildNumberPart: DWORD;
  11.   BuildNumber: DWORD;
  12. begin
  13.   RtlGetNtVersionNumbers(Major, Minor, BuildNumberPart);
  14.   BuildNumber := BuildNumberPart shr 16; // Extract build number from high 16 bits
  15.   Result := (Major = 10) and (Minor = 0) and (BuildNumber >= 22000);
  16. end;
  17.  
  18. begin
  19.   if IsWindows11OrNewer then
  20.     Writeln('Windows 11 or newer detected.')
  21.   else
  22.     Writeln('Windows 10 or older detected.');
  23.   Readln;
  24. end.
  25.  

output:

Code: Text  [Select][+][-]
  1. Windows 11 or newer detected.
  2.  

or

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Windows, Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
  9.  
  10. type
  11.   { TForm1 }
  12.   TForm1 = class(TForm)
  13.     Memo1: TMemo;
  14.     Button1: TButton;
  15.     procedure Button1Click(Sender: TObject);
  16.   private
  17.     procedure DetectWindowsVersion;
  18.   end;
  19.  
  20. var
  21.   Form1: TForm1;
  22.  
  23. implementation
  24.  
  25. {$R *.lfm}
  26.  
  27. procedure RtlGetNtVersionNumbers(out MajorVersion, MinorVersion, BuildNumber: DWORD); stdcall; external 'ntdll.dll';
  28.  
  29. { TForm1 }
  30.  
  31. // Procedure to detect Windows version and output the result to Memo1
  32. procedure TForm1.DetectWindowsVersion;
  33. var
  34.   Major, Minor, BuildPart, Build: DWORD;
  35. begin
  36.   // Get version numbers
  37.   RtlGetNtVersionNumbers(Major, Minor, BuildPart);
  38.  
  39.   // Extract build number from high 16 bits
  40.   Build := BuildPart shr 16;
  41.  
  42.   Memo1.Lines.Add('Windows version detected:');
  43.   Memo1.Lines.Add(Format('Major: %d, Minor: %d, Build: %d', [Major, Minor, Build]));
  44.  
  45.   // Determine if Windows 11 or newer
  46.   if (Major = 10) and (Minor = 0) then
  47.   begin
  48.     if Build >= 22000 then
  49.       Memo1.Lines.Add('Windows 11 or newer detected.')
  50.     else
  51.       Memo1.Lines.Add('Windows 10 detected.');
  52.   end
  53.   else
  54.     Memo1.Lines.Add('Older than Windows 10 detected.');
  55. end;
  56.  
  57. procedure TForm1.Button1Click(Sender: TObject);
  58. begin
  59.   Memo1.Clear;
  60.   DetectWindowsVersion;
  61. end;
  62.  
  63. end.
  64.  

output:

Code: Text  [Select][+][-]
  1. Windows version detected:
  2. Major: 10, Minor: 0, Build: 61440
  3. Windows 11 or newer detected.
  4.  
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: LV on April 07, 2025, 04:24:03 pm
Sorry, the program has an error with the Windows build.  :(
Needs to be corrected.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Windows, Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
  9.  
  10. type
  11.   { TForm1 }
  12.   TForm1 = class(TForm)
  13.     Memo1: TMemo;
  14.     Button1: TButton;
  15.     procedure Button1Click(Sender: TObject);
  16.   private
  17.     procedure DetectWindowsVersion;
  18.   end;
  19.  
  20. var
  21.   Form1: TForm1;
  22.  
  23. procedure RtlGetNtVersionNumbers(out MajorVersion, MinorVersion, BuildNumber: DWORD); stdcall;
  24.   external 'ntdll.dll';
  25.  
  26. implementation
  27.  
  28. {$R *.lfm}
  29.  
  30. procedure TForm1.DetectWindowsVersion;
  31. var
  32.   Major, Minor, Build: DWORD;
  33. begin
  34.   // Get version numbers from ntdll.dll
  35.   RtlGetNtVersionNumbers(Major, Minor, Build);
  36.  
  37.   // Correct build number (mask to low 16 bits)
  38.   Build := Build and $FFFF;
  39.  
  40.   Memo1.Lines.Add('Windows version detected:');
  41.   Memo1.Lines.Add('Major: ' + UIntToStr(Major) + ', Minor: ' + UIntToStr(Minor) + ', Build: ' + UIntToStr(Build));
  42.  
  43.   if (Major = 10) and (Minor = 0) then
  44.   begin
  45.     if Build >= 22000 then
  46.       Memo1.Lines.Add('Windows 11 or newer detected.')
  47.     else
  48.       Memo1.Lines.Add('Windows 10 detected.');
  49.   end
  50.   else
  51.     Memo1.Lines.Add('Older than Windows 10 detected.');
  52. end;
  53.  
  54. procedure TForm1.Button1Click(Sender: TObject);
  55. begin
  56.   Memo1.Clear;
  57.   DetectWindowsVersion;
  58. end;
  59.  
  60. end.
  61.  

output:

Code: Text  [Select][+][-]
  1. Windows version detected:
  2. Major: 10, Minor: 0, Build: 26100
  3. Windows 11 or newer detected.
  4.  
  :)
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: Ericktux on April 08, 2025, 08:32:19 am
Hi friend, this works for me so far:  :)

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils,
  9.   ComObj, ComCtrls, ActiveX,
  10.   Forms, Controls, Graphics, Dialogs, StdCtrls;
  11.  
  12. type
  13.  
  14.   { TForm1 }
  15.  
  16.   TForm1 = class(TForm)
  17.     Button1: TButton;
  18.     procedure Button1Click(Sender: TObject);
  19.   private
  20.  
  21.   public
  22.       function nombre_windows:string;
  23.   end;
  24.  
  25. var
  26.   Form1: TForm1;
  27.  
  28. implementation
  29.  
  30. {$R *.lfm}
  31.  
  32. { TForm1 }
  33.  
  34. function TForm1.nombre_windows: string;
  35. const
  36.   wbemFlagForwardOnly = $00000020;
  37. var
  38.   FSWbemLocator : OLEVariant;
  39.   FWMIService   : OLEVariant;
  40.   FWbemObjectSet: OLEVariant;
  41.   FWbemObject   : OLEVariant;
  42.   oEnum         : IEnumvariant;
  43.   iValue        : LongWord;
  44. begin;
  45.   FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
  46.   FWMIService   := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
  47.   FWbemObjectSet:= FWMIService.ExecQuery('SELECT Caption FROM Win32_OperatingSystem','WQL',wbemFlagForwardOnly);
  48.   //FWbemObjectSet:= FWMIService.ExecQuery('SELECT Name, Version FROM Win32_OperatingSystem','WQL',wbemFlagForwardOnly);  // ORIGINAL
  49.   oEnum         := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
  50.   if oEnum.Next(1, FWbemObject, iValue) = 0 then
  51.   begin
  52.     if DirectoryExists('c:\windows\syswow64') then
  53.     Result:=FWbemObject.Caption+' x64'
  54.     else
  55.     Result:=FWbemObject.Caption+' x86';
  56.     FWbemObject:=Unassigned;
  57.   end;
  58. End;
  59.  
  60. procedure TForm1.Button1Click(Sender: TObject);
  61. begin
  62.   ShowMessage('Sistema Operativo : '#13+nombre_windows);
  63. end;
  64.  
  65. end.
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: VisualLab on April 08, 2025, 11:44:17 am
@440bx -
I searched my entire C: drive for csrss*. (I use FreeCommander with "Show hidden files".) Only 2 files were found -
csrss.exe.mui in C:\Windows\WinSxS\amd64_microsoft-windows-csrss.resources_31bf3856ad364e35_10.0.26100.1_en-us_d784b37749fd398a\
csrss.exe in C:\Windows\WinSxS\amd64_microsoft-windows-csrss_31bf3856ad364e35_10.0.26100.1_none_55d78c384ca248d1\

In the Properties\Details tab for the latter file, the version is 10.0.26100.1, date modified 4/1/2024. Per my original post, 26100 is the build number returned by RtlGetNtVersionNumbers; however, RtlGetNtVersionNumbers also indicates that the Major Version is 10.

Hmm... Strange. I checked Windows 11 Professional 64-bit (installed on a virtual machine). The file "csrss.exe" is present in the directory "C:\Windows\System32". Maybe something broke in your installation?
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: 440bx on April 08, 2025, 11:53:46 am
Hmm... Strange. I checked Windows 11 Professional 64-bit (installed on a virtual machine). The file "csrss.exe" is present in the directory "C:\Windows\System32".
yes, it's really strange he can't find csrss.exe there.
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: Zvoni on April 08, 2025, 11:58:39 am
Irrespective of above:
I'm wondering how long it will take TS to finally get it, that the Major Version Number for Win11 is still 10?????
The difference between Win10 and Win11 is the BUILD-Number (as many times already mentioned!)
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: jcmontherock on April 08, 2025, 12:06:41 pm
I have the same thing: I found 'csrss.exe' in my native windows. When I try to execute it I received the following error msg:

'csrss.exe' n’est pas reconnu en tant que commande interne
ou externe, un programme exécutable ou un fichier de commandes.
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: dculp on April 08, 2025, 04:24:25 pm
For https://wiki.freepascal.org/Windows_version (https://wiki.freepascal.org/Windows_version) I get the following for Win10 and Win11 -

VersionName = Windows 8

From sysutils
   Win32MajorVersion = 6
   Win32MinorVersion = 2
   Win32BuildNumber = 9200 (the site shows 22000)

Tracing the code backward indicates that the problem with the link's code lies in GetVersionEx(versioninfo) in redef.inc -

  {SysUtils initialization calls Procedure LoadVersionInfo; which establishes -
    GetVersionEx(versioninfo); (redef.inc)
      where versioninfo establishes the values in the next lines (global vars in SysUtils) -
        Win32Platform:=versionInfo.dwPlatformId;
        Win32MajorVersion:=versionInfo.dwMajorVersion;
        Win32MinorVersion:=versionInfo.dwMinorVersion;
        Win32BuildNumber:=versionInfo.dwBuildNumber;

  Win32Proc.pp initialization calls procedure UpdateWindowsVersion;
  which uses the above info to establish WindowsVersion}



Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: Fibonacci on April 08, 2025, 04:35:58 pm
Tracing the code backward indicates that the problem with the link's code lies in GetVersionEx(versioninfo) in redef.inc -

GetVersionEx is deprecated

Quote
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 or Windows 10 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.
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: dculp on April 08, 2025, 04:52:21 pm
Tracing the code backward indicates that the problem with the link's code lies in GetVersionEx(versioninfo) in redef.inc -

GetVersionEx is deprecated

Quote
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 or Windows 10 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.

Does "application" refer to Lazarus itself or the app that I generate with Lazarus?
What is "manifested"?
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: Fibonacci on April 08, 2025, 04:57:39 pm
Your app

Manifest is a resource embedded in the application. See Project Options -> Application - Use manifest resource

Manifested = contains an embedded manifest (or  as a separate .manifest file (https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests))
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: dculp on April 08, 2025, 05:12:46 pm
Checking "Use manifest resource" now shows correct Windows version -

VersionName = Windows 11

From sysutils
   Win32MajorVersion = 10
   Win32MinorVersion = 0
   Win32BuildNumber = 26100

Why isn't "Use manifest resource" the default? Does it cause problems?
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: Fibonacci on April 08, 2025, 06:17:59 pm
It is the default for the GUI app template, which is the default when you open Lazarus
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: Remy Lebeau on April 08, 2025, 07:40:08 pm
Checking "Use manifest resource" now shows correct Windows version -

An app manifest must explicitly declare which individual Windows versions are supported by your app.  Windows Vista, 7, 8, 8.11, and 10/112 have distinct supportedOS guids defined. When your app runs on a given Windows version and your app manifest does not declare support for that version, then version-reporting APIs will not behave as expected.  That is why your app thought Windows 11 was Windows 8 v6.2.9200 until you added a manifest that declared support for Windows 11.

1: Windows 8.1 has its own supportedOS guid, likely because it introduced major API behavioral changes.

2: Windows 10 and 11 share the same supportedOS guid, likely because Windows 11 is v10.0.22000+ and not v11.0.0+, as you might expect.

When Microsoft eventually releases a new Windows version that increases the major version number, or otherwise introduces major behavioral changes, then there will likely be a new supportedOS guid defined, which your existing app manifest will not refer to yet, and so all version-reporting APIs will not behave as expected again when your app is run on those newer Windows versions, until you update your app manifest accordingly.  This is why you should not rely on OS version numbers being accurate.  And certainly don't rely on them for detecting available OS functionality, only for logging at best.
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: VisualLab on April 09, 2025, 11:01:39 am
An app manifest must explicitly declare which individual Windows versions are supported by your app.  Windows Vista, 7, 8, 8.11, and 10/112 have distinct supportedOS guids defined. When your app runs on a given Windows version and your app manifest does not declare support for that version, then version-reporting APIs will not behave as expected.  That is why your app thought Windows 11 was Windows 8 v6.2.9200 until you added a manifest that declared support for Windows 11.

1: Windows 8.1 has its own supportedOS guid, likely because it introduced major API behavioral changes.

2: Windows 10 and 11 share the same supportedOS guid, likely because Windows 11 is v10.0.22000+ and not v11.0.0+, as you might expect.

When Microsoft eventually releases a new Windows version that increases the major version number, or otherwise introduces major behavioral changes, then there will likely be a new supportedOS guid defined, which your existing app manifest will not refer to yet, and so all version-reporting APIs will not behave as expected again when your app is run on those newer Windows versions, until you update your app manifest accordingly.  This is why you should not rely on OS version numbers being accurate.  And certainly don't rely on them for detecting available OS functionality, only for logging at best.

People at Microsoft (decision makers) are causing more and more chaos (mess) in the system (including WinAPI). They started to break more than they fix or improve with Windows 8. They let up a bit with the first versions of version 10. And then the system breakdown accelerated again. There are probably too many clerks and "managers" in this company and not enough real IT engineers. The effects of the generational change are clearly visible.
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: paule32 on April 10, 2025, 02:44:11 pm
I don't know: how to use Windows 10 or 11 anymore ?
The Support is ending 23. October 2025 !

No cumulative Updates
No more secured Support
No more right mind thinkings, if Microsoft jumps to ARM CPU.

This means, you need new Hardware.
This means, you need new Software.
This means, you need new Lessons for the Employees for Seminat's of the new Software.

This means, you have new Costs - either lesser or more ...

I would not sugget to use Linux - because Linux is Free, but using tailored Software, and you have too many Derivates - the Jungle of Software with different binary Format each together.

This means, you need Money to buy a CD with a Linux Distribution of your desire.

This means: Windows Users should stay on Microsoft and NOT jumping like a Frog from one System to the next - that would be give QUARK -___-

I don't dislike Linux, but on my Expierences Windows is the better thing...

Conclusion:
- each System has its own pros and cons.
- Windows is backward compatible in the most cases.
- This means: a Windows 7 Application can be run in Windows 8
- to jump to an other System is dumb
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: Nicole on April 10, 2025, 05:05:06 pm
when I hit Win + R and there "Winver", - I get it.
So there shall be a way to run one of the Windows shells by "run".
Case you should not prefer Zvonis solution, which looks very elegant to me, I search you my notes howTo call the shells.
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: paule32 on April 10, 2025, 08:13:45 pm
Hello Nicole,

I have bundle a Python Console Application that you can download there:
https://github.com/paule32/WindowsVersion (https://github.com/paule32/WindowsVersion)

It comes with Python Code Script and a compiled Windows 11 Pro EXE Application.
The EXE was build with a github.com CI Workflow File.

Feel free to use it, and send me a like :-)

HTH - Hope this Helps.
Title: Re: How to determine Windows version 11? (RtlGetNtVersionNumbers returns Windows 10)
Post by: PascalDragon on April 10, 2025, 08:45:49 pm
I have the same thing: I found 'csrss.exe' in my native windows. When I try to execute it I received the following error msg:

csrss.exe is not a Windows application, but a native NT application as this is what provides the Windows subsystem on top of the NT kernel.
TinyPortal © 2005-2018