OSVersion for Windows 11 reports as 8

Post bugreports for the Windows version here
User avatar
DeanH
Enthusiast
Enthusiast
Posts: 223
Joined: Wed May 07, 2008 4:57 am
Location: Adelaide, South Australia
Contact:

OSVersion for Windows 11 reports as 8

Post by DeanH »

I have a user with a Windows 11 system which PB is reporting as Windows 8.

OSVersion() in PB 6.00 x 64 reports Windows 8.

The Kernel file version shows 10.0.22000.708 (WinBuild.160101.0800).
The registry shows Major version 10, Current version 6.3, Display version 21H2, Product name Windows 10 Pro.

But the Windows specifications dialog clearly shows Windows 11 Pro, 21H2, OS Build 22000.1098 and the screen display is obviously Win 11. (Taskbar in the middle, changes to File Explorer, etc.) I do not know if this is a new PC or an upgrade.

Below is my procedure:

Code: Select all

Procedure$ WinVer()
	Protected A$="Unidentified Windows version"
	Select OSVersion()
		Case #PB_OS_Windows_NT3_51 : A$="Windows NT 3.5"
		Case #PB_OS_Windows_95 : A$="Windows 95"
		Case #PB_OS_Windows_NT_4 : A$="Windows NT 4"
		Case #PB_OS_Windows_98 : A$="Windows 98"
		Case #PB_OS_Windows_ME : A$="Windows ME"
		Case #PB_OS_Windows_2000 : A$="Windows 2000"
		Case #PB_OS_Windows_XP : A$="Windows XP"
		Case #PB_OS_Windows_Server_2003 : A$="Windows Sever 2003"
		Case #PB_OS_Windows_Vista : A$="Windows Vista"
		Case #PB_OS_Windows_Server_2008 : A$="Windows Server 2008"
		Case #PB_OS_Windows_7 : A$="Windows 7"
		Case #PB_OS_Windows_Server_2008_R2 : A$="Windows Server 2008 R2"
		Case #PB_OS_Windows_8 : A$="Windows 8"
		Case #PB_OS_Windows_Server_2012 : A$="Windows Server 2012"
		Case #PB_OS_Windows_8_1 : A$="Windows 8.1"
		Case #PB_OS_Windows_Server_2012_R2 : A$="Windows Server 2012 R2"
		Case #PB_OS_Windows_10 : A$="Windows 10"
		CompilerIf #PB_Compiler_Version>=600
			Case #PB_OS_Windows_11 : A$="Windows 11"
		CompilerEndIf
	EndSelect
	ProcedureReturn A$
EndProcedure

Debug WinVer()

RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4636
Joined: Sun Apr 12, 2009 6:27 am

Re: OSVersion for Windows 11 reports as 8

Post by RASHAD »

Hi
PB 6.0 x64 - Windows 11 x64
Works like charm
BTW:
Why CompilerIf #PB_Compiler_Version>=600 ,PB v 6 support OSVersion() for Windows 11 right away
Egypt my love
User avatar
DeanH
Enthusiast
Enthusiast
Posts: 223
Joined: Wed May 07, 2008 4:57 am
Location: Adelaide, South Australia
Contact:

Re: OSVersion for Windows 11 reports as 8

Post by DeanH »

Further to the above:

The user's PC is brand new, purchased last August.

I found the registry entry Software\Microsoft\Windows\CurrentVersion\EditionVersion "EditionBuildNumber" shows the correct build version 22000 and "EditionBuildQfe" shows the .1098 part. Build 22000 is Win 11. The Kernel product version reports 10.0 but has the .22000 build after.

This article helped: https://www.codeproject.com/Articles/53 ... -Detection

The CompilerIf is in the code because I worked on the procedure while still using PB5.73. It could be removed.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4636
Joined: Sun Apr 12, 2009 6:27 am

Re: OSVersion for Windows 11 reports as 8

Post by RASHAD »

Hi again
It's not quit right because if there is a problem to detect Windows version the conflict will be between Windows 11 and Window 10 but NOT between 11 and 8
Most probably it's the User mistake

Compile the next and let the User run it and report back the result

Code: Select all

MessageRequester("Info",Str(OSVersion()),#MB_OK)
Egypt my love
BarryG
Addict
Addict
Posts: 3292
Joined: Thu Apr 18, 2019 8:17 am

Re: OSVersion for Windows 11 reports as 8

Post by BarryG »

Weird, but likely your customer's error. OSVersion() correctly reports Win 11 for me. Could be that the customer got scammed with a Win 8 machine dressed up as Win 11.
User avatar
ChrisR
Addict
Addict
Posts: 1127
Joined: Sun Jan 08, 2017 10:27 pm
Location: France

Re: OSVersion for Windows 11 reports as 8

Post by ChrisR »

Windows 10 and Windows 11 share the same Major and Minor version number (10.0)
For PB<6.0, I made a small addition in [Windows] WindowsVersion() subject to differentiate them via the Build number (>=22000).
And in the same way for Windows Server 2016, 2019 and 2022.
User avatar
DeanH
Enthusiast
Enthusiast
Posts: 223
Joined: Wed May 07, 2008 4:57 am
Location: Adelaide, South Australia
Contact:

Re: OSVersion for Windows 11 reports as 8

Post by DeanH »

The user's machine definitely reports Win 11. I have a screenshot of WinVer and it reports 11 with build 22000.

I have read that GetVersion(Ex) can report v6.2 - which is Windows 8 - on a Win 11 system.

From a Microsoft article dated June 30, 2021:
https://learn.microsoft.com/en-us/windo ... getversion
Applications not manifested for Windows 8.1 or Windows 10 will return the Windows 8 OS version value (6.2).
This is in the GetVersion function info and applies to GetVersion(Ex).

I have other users in which Windows 11 is correctly reported by OSVersion(), so I know it works in many cases. I saw one just yesterday, correctly reported. But I have one user where OSVersion reports Win 8 and I have read that is possible. It may be rare, and may be due to the underlying change Microsoft has made to identifying the Windows version, but it means OSVersion() cannot be completely relied on. It isn't a "bug" as such in PB but maybe something that can be looked at.

Rashan, I will make a mod to my software to see the actual value reported by OSVersion. The user works part-time so I don't know how soon I can find out. ChrisR, I'll have a look when I get a chance.
User avatar
DeanH
Enthusiast
Enthusiast
Posts: 223
Joined: Wed May 07, 2008 4:57 am
Location: Adelaide, South Australia
Contact:

Re: OSVersion for Windows 11 reports as 8

Post by DeanH »

Chris$ thank you! Your code has identified Win 11 on the user's odd machine and also Server 2022 on my Azure webserver.
User avatar
DeanH
Enthusiast
Enthusiast
Posts: 223
Joined: Wed May 07, 2008 4:57 am
Location: Adelaide, South Australia
Contact:

Re: OSVersion for Windows 11 reports as 8

Post by DeanH »

Unfortunately, even with ChrisR's code, the user's system still showed Windows 8 even though it is a Win 11 system.

In the code, the parameter ver\dwBuildNumber returns 9200, which is incorrect. ver\dwMajorVersion=6 and ver\dwMinorVersion=2.

The user is a private school in Coffs Harbour, New South Wales, Australia. The computer is a laptop purchased new just last August.

The value returned by OSVersion() in PureBasic is 90.
The registry shows Windows 10, current version 6.3.
But the file info on kernel.dll is 10.0.22000.708 .
CurrentBuildNumber in the registry shows 22000 but there is nothing that says Windows 11.
That key does not exist on my Win 10 system.

To solve this problem, I added code to get the product version of kernel.dll and assume it is Win 11 if the 3rd field value is > 20347.
Thanks to akee for the GetFileVersionInfo procedure.
viewtopic.php?p=324893&hilit=GetFileVersionInfo#p324893

Here is my slightly modified code:

Code: Select all


;{ GetFileVersionInfo_ElementName
Enumeration
	#FVI_FileVersion      = $0001
	#FVI_FileDescription  = $0002
	#FVI_LegalCopyright   = $0004
	#FVI_InternalName     = $0008
	#FVI_OriginalFilename = $0010
	#FVI_ProductName      = $0020
	#FVI_ProductVersion   = $0040
	#FVI_CompanyName      = $0080
	#FVI_LegalTrademarks  = $0100
	#FVI_SpecialBuild     = $0200
	#FVI_PrivateBuild     = $0400
	#FVI_Comments         = $0800
	#FVI_Language         = $1000
	#FVI_Email            = $1001
	#FVI_Website          = $1002
	#FVI_Special          = $1003
EndEnumeration

Procedure.s GetFileVersionInfo_ElementName(ElementFlag)
	Protected TempString$ = ""
	Select ElementFlag
		Case #FVI_FileVersion
			TempString$ = "FileVersion"
		Case #FVI_FileDescription
			TempString$ = "FileDescription"
		Case #FVI_LegalCopyright
			TempString$ = "LegalCopyright"
		Case #FVI_InternalName
			TempString$ = "InternalName"
		Case #FVI_OriginalFilename
			TempString$ = "OriginalFilename"
		Case #FVI_ProductName
			TempString$ = "ProductName"
		Case #FVI_ProductVersion
			TempString$ = "ProductVersion"
		Case #FVI_CompanyName
			TempString$ = "CompanyName"
		Case #FVI_LegalTrademarks
			TempString$ = "LegalTrademarks"
		Case #FVI_SpecialBuild
			TempString$ = "SpecialBuild"
		Case #FVI_PrivateBuild
			TempString$ = "PrivateBuild"
		Case #FVI_Comments
			TempString$ = "Comments"
		Case #FVI_Language
			TempString$ = "Language"
		Case #FVI_Email
			TempString$ = "Email"
		Case #FVI_Website
			TempString$ = "Website"
		Case #FVI_Special
			TempString$ = "Special"
	EndSelect
	ProcedureReturn TempString$
EndProcedure

CompilerIf #PB_Compiler_Unicode
	Prototype.l GetFileVersionInfoSizeW(lptstrFilename.p-unicode, lpdwHandle.l)
	Prototype.l GetFileVersionInfoW(lptstrFilename.p-unicode, dwHandle.l, dwLen.l, lpData.l)
	Prototype.l VerQueryValueW(pBlock.l, lpSubBlock.p-unicode, lplpBuffer.l, puLen.w)
	Prototype.l VerLanguageNameW(wLang.l, szLang.p-unicode, cchLang.l)
CompilerElse
	Prototype.l GetFileVersionInfoSizeA(lptstrFilename.p-ascii, lpdwHandle.l)
	Prototype.l GetFileVersionInfoA(lptstrFilename.p-ascii, dwHandle.l, dwLen.l, lpData.l)
	Prototype.l VerQueryValueA(pBlock.l, lpSubBlock.p-ascii, lplpBuffer.l, puLen.w)
	Prototype.l VerLanguageNameA(wLang.l, szLang.p-ascii, cchLang.l)
CompilerEndIf

Procedure$ GetFileVersionInfoString(lptstrFilename$, FVI_Flag)
	Protected TempString$ = "", TempPtr, TempBlkSize, *TempBlk
	Protected TempLibHandle, TempBuff, TempBuffSize, TempCPLI$, TempLangSize = 128, TempLang$ = Space(TempLangSize)
	;Protected GetFileVersionInfoSize.GetFileVersionInfoSizeA
	;Protected GetFileVersionInfo.GetFileVersionInfoA
	;Protected VerQueryValue.VerQueryValueA
	;Protected VerLanguageName.VerLanguageNameA
	
	If FileSize(lptstrFilename$) >= 0
		TempLibHandle = OpenLibrary(#PB_Any, "version.dll")
		If TempLibHandle
			CompilerIf #PB_Compiler_Unicode
				GetFileVersionInfoSize.GetFileVersionInfoSizeW = GetFunction(TempLibHandle, "GetFileVersionInfoSizeW")
				GetFileVersionInfo.GetFileVersionInfoW = GetFunction(TempLibHandle, "GetFileVersionInfoW")
				VerQueryValue.VerQueryValueW = GetFunction(TempLibHandle, "VerQueryValueW")
				VerLanguageName.VerLanguageNameW = GetFunction(TempLibHandle, "VerLanguageNameW")
			CompilerElse
				GetFileVersionInfoSize.GetFileVersionInfoSizeA = GetFunction(TempLibHandle, "GetFileVersionInfoSizeA")
				GetFileVersionInfo.GetFileVersionInfoA = GetFunction(TempLibHandle, "GetFileVersionInfoA")
				VerQueryValue.VerQueryValueA = GetFunction(TempLibHandle, "VerQueryValueA")
				VerLanguageName.VerLanguageNameA = GetFunction(TempLibHandle, "VerLanguageNameA")
			CompilerEndIf
			
			TempBlkSize = GetFileVersionInfoSize(lptstrFilename$, @TempPtr)
			If TempBlkSize > 0
				*TempBlk = AllocateMemory(TempBlkSize)
				If *TempBlk > 0
					If GetFileVersionInfo(lptstrFilename$, 0, TempBlkSize, *TempBlk)
						If VerQueryValue(*TempBlk, "\\VarFileInfo\\Translation", @TempBuff, @TempBuffSize)
							TempCPLI$ = RSet(Hex(PeekW(TempBuff)), 4, "0") + RSet(Hex(PeekW(TempBuff + 2)), 4, "0")
							VerLanguageName(PeekW(TempBuff), TempLang$, TempLangSize)
						EndIf
						If VerQueryValue(*TempBlk, "\\StringFileInfo\\" + TempCPLI$ + "\\" + GetFileVersionInfo_ElementName(FVI_Flag), @TempBuff, @TempBuffSize)
							TempString$ = PeekS(TempBuff, TempBuffSize)
						EndIf
						If FVI_Flag = #FVI_Language
							TempString$ = TempLang$
						EndIf
					EndIf
				EndIf
				FreeMemory(*TempBlk)
			EndIf
		EndIf
		CloseLibrary(TempLibHandle)
	EndIf
	
	ProcedureReturn(TempString$)
EndProcedure

;}

;{ Get Windows Version (Chris$)

Prototype.i protoRtlGetVersion (*ver.OSVERSIONINFOEX)

Procedure.s WindowsVersion()
	Protected ver.OSVERSIONINFOEX
	Protected RtlGetVersion.protoRtlGetVersion
	Protected hDLL.i
	Protected size.i,buffer$,p$,o$,File$,WindowsDirectory$,KernelVersionInfo.i
	
	;Added by DeanH to pick up the file version info of kernel.dll
	size=255
	buffer$=Space(size)
	WindowsDirectory$=""
	GetWindowsDirectory_(@buffer$,@size)
	WindowsDirectory$=Trim(buffer$)
	File$=WindowsDirectory$+"\system32\kernel32.dll"
	p$=GetFileVersionInfoString(File$, #FVI_ProductVersion)
	o$=StringField(p$,3,".")
	KernelVersionInfo=Val(o$)
	
	ver\dwOSVersionInfoSize = SizeOf(ver)
	
	hDLL = OpenLibrary(#PB_Any, "ntdll.dll")     
	If hDLL   
		RtlGetVersion = GetFunction(hDLL, "RtlGetVersion")
		CloseLibrary(hDLL)       
	EndIf
	
	If RtlGetVersion = 0 Or RtlGetVersion(@ver) <> 0
		ProcedureReturn "Error: Can't call Windows API function RtlGetVersion()."
	EndIf
	
	If ver\dwPlatformId <> #VER_PLATFORM_WIN32_NT
		ProcedureReturn "No Windows NT-based operating system"
	EndIf     
	
	Select ver\dwMajorVersion
		Case 3
			If ver\wProductType = #VER_NT_WORKSTATION
				ProcedureReturn "Windows NT 3.5 Workstation"
			Else
				ProcedureReturn "Windows NT 3.5 Server"
			EndIf
			
		Case 4
			If ver\wProductType = #VER_NT_WORKSTATION
				ProcedureReturn "Windows NT 4.0 Workstation"
			Else
				ProcedureReturn "Windows NT 4.0 Server"
			EndIf
			
		Case 5
			Select ver\dwMinorVersion
				Case 0
					If ver\wProductType = #VER_NT_WORKSTATION
						ProcedureReturn "Windows 2000 Workstation"
					Else
						ProcedureReturn "Windows 2000 Server"
					EndIf
				Case 1
					If (ver\wSuiteMask & #VER_SUITE_PERSONAL)
						ProcedureReturn "Windows XP Home Edition"
					Else
						ProcedureReturn "Windows XP Professional"
					EndIf
				Case 2
					If ver\wProductType = #VER_NT_WORKSTATION
						ProcedureReturn "Windows XP 64-bit Edition"
					Else
						ProcedureReturn "Windows Server 2003"
					EndIf
			EndSelect
			
		Case 6
			Select ver\dwMinorVersion
				Case 0
					If ver\wProductType = #VER_NT_WORKSTATION
						ProcedureReturn "Windows Vista"
					Else
						ProcedureReturn "Windows Server 2008"
					EndIf
				Case 1
					If ver\wProductType = #VER_NT_WORKSTATION
						ProcedureReturn "Windows 7"
					Else
						ProcedureReturn "Windows Server 2008 R2"
					EndIf
				Case 2
					If ver\wProductType = #VER_NT_WORKSTATION
						If KernelVersionInfo>=20348
							ProcedureReturn "Windows 11"
						EndIf
						ProcedureReturn "Windows 8"
					Else
						ProcedureReturn "Windows Server 2012"
					EndIf
				Case 3
					If ver\wProductType = #VER_NT_WORKSTATION
						If KernelVersionInfo>=20348
							ProcedureReturn "Windows 11"
						EndIf
						ProcedureReturn "Windows 8.1"
					Else
						ProcedureReturn "Windows Server 2012 R2"
					EndIf
			EndSelect
			
		Case 10
			If ver\wProductType = #VER_NT_WORKSTATION
				; https://learn.microsoft.com/en-us/windows/release-health/windows11-release-information
				; https://learn.microsoft.com/en-us/windows/release-health/release-information
				If ver\dwBuildNumber >= 22000 Or KernelVersionInfo>=20348
					ProcedureReturn "Windows 11"
				ElseIf ver\dwBuildNumber >= 10240
					ProcedureReturn "Windows 10"
				EndIf
			Else
				; https://learn.microsoft.com/en-us/windows-server/get-started/windows-server-release-info
				If ver\dwBuildNumber >= 20348
					ProcedureReturn "Windows Server 2022"
				ElseIf ver\dwBuildNumber >= 17763
					ProcedureReturn "Windows Server 2019"
				ElseIf ver\dwBuildNumber >= 14393
					ProcedureReturn "Windows Server 2016"
				EndIf  
			EndIf
	EndSelect
	
	ProcedureReturn "Unknown Windows version"
EndProcedure

;}

Debug WindowsVersion()

Fred
Administrator
Administrator
Posts: 16617
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: OSVersion for Windows 11 reports as 8

Post by Fred »

I added the new OS Id in the manifest as explained here: https://stackoverflow.com/questions/333 ... ng-version so RtlGetVersion() should returns the correct value. Could you test to see if it solves the issue
(it's was correctly reporting windows 11 here) ? Probably because the PC was upgraded from Windows 8.1
User avatar
DeanH
Enthusiast
Enthusiast
Posts: 223
Joined: Wed May 07, 2008 4:57 am
Location: Adelaide, South Australia
Contact:

Re: OSVersion for Windows 11 reports as 8

Post by DeanH »

I have contacted the school with the Win 11 PC that was reporting Win 8 and asked them to test. Will get back with results when I hear from them.

I also tested on our Azure server and it reported Windows 10. It is Server 2022. Is there a chance the OS id for Servers 2016, 2019 and 2022 can also be added?
User avatar
DeanH
Enthusiast
Enthusiast
Posts: 223
Joined: Wed May 07, 2008 4:57 am
Location: Adelaide, South Australia
Contact:

Re: OSVersion for Windows 11 reports as 8

Post by DeanH »

Just had a remote connection session with the school.

Sorry, it still identifies as Windows 8.

Here is the little program I used to test, compiled with the ASM compiler PB 6.01 Beta 2 (downloaded this week).

Code: Select all

a=OSVersion()
a$="Unidentified Windows version"
Select a
	Case #PB_OS_Windows_NT3_51 : a$="Windows NT 3.5"
	Case #PB_OS_Windows_95 : a$="Windows 95"
	Case #PB_OS_Windows_NT_4 : a$="Windows NT 4"
	Case #PB_OS_Windows_98 : a$="Windows 98"
	Case #PB_OS_Windows_ME : a$="Windows ME"
	Case #PB_OS_Windows_2000 : a$="Windows 2000"
	Case #PB_OS_Windows_XP : a$="Windows XP"
	Case #PB_OS_Windows_Server_2003 : a$="Windows Sever 2003"
	Case #PB_OS_Windows_Vista : a$="Windows Vista"
	Case #PB_OS_Windows_Server_2008 : a$="Windows Server 2008"
	Case #PB_OS_Windows_7 : a$="Windows 7"
	Case #PB_OS_Windows_Server_2008_R2 : a$="Windows Server 2008 R2"
	Case #PB_OS_Windows_8 : a$="Windows 8"
	Case #PB_OS_Windows_Server_2012 : a$="Windows Server 2012"
	Case #PB_OS_Windows_8_1 : a$="Windows 8.1"
	Case #PB_OS_Windows_Server_2012_R2 : a$="Windows Server 2012 R2"
	Case #PB_OS_Windows_10 : a$="Windows 10"
	Case #PB_OS_Windows_11 : a$="Windows 11"
	Case #PB_OS_Windows_Future : a$="Unidentified Windows version"
EndSelect
MessageRequester("Win version",Str(a)+" "+a$)
It reports OSVersion() as 90. Windows 8.
Their computer is definitely Windows 11. It was purchased new last August. Not an upgrade.

Some other info:
The Kernel file version is 10.0.22000.708 (WinBuild 160101.0800)
The Product version for the Kernel file is also 10.0.22000.708
The registry reports the major version as 10.
Current version as 6.3
Display version 21H2
Product name "Windows 10 Enterprise"

The work-around code I'm using, based on code by ChrisR, is correctly reporting Windows 11.
Here is the work-around code.

Code: Select all

;This work around returns the correct version of Windows. It is using the file version info from kernel32.dll to identify
; GetFileVersionInfo_ElementName
Enumeration
	#FVI_FileVersion      = $0001
	#FVI_FileDescription  = $0002
	#FVI_LegalCopyright   = $0004
	#FVI_InternalName     = $0008
	#FVI_OriginalFilename = $0010
	#FVI_ProductName      = $0020
	#FVI_ProductVersion   = $0040
	#FVI_CompanyName      = $0080
	#FVI_LegalTrademarks  = $0100
	#FVI_SpecialBuild     = $0200
	#FVI_PrivateBuild     = $0400
	#FVI_Comments         = $0800
	#FVI_Language         = $1000
	#FVI_Email            = $1001
	#FVI_Website          = $1002
	#FVI_Special          = $1003
EndEnumeration

Procedure.s GetFileVersionInfo_ElementName(ElementFlag)
	Protected TempString$ = ""
	Select ElementFlag
		Case #FVI_FileVersion
			TempString$ = "FileVersion"
		Case #FVI_FileDescription
			TempString$ = "FileDescription"
		Case #FVI_LegalCopyright
			TempString$ = "LegalCopyright"
		Case #FVI_InternalName
			TempString$ = "InternalName"
		Case #FVI_OriginalFilename
			TempString$ = "OriginalFilename"
		Case #FVI_ProductName
			TempString$ = "ProductName"
		Case #FVI_ProductVersion
			TempString$ = "ProductVersion"
		Case #FVI_CompanyName
			TempString$ = "CompanyName"
		Case #FVI_LegalTrademarks
			TempString$ = "LegalTrademarks"
		Case #FVI_SpecialBuild
			TempString$ = "SpecialBuild"
		Case #FVI_PrivateBuild
			TempString$ = "PrivateBuild"
		Case #FVI_Comments
			TempString$ = "Comments"
		Case #FVI_Language
			TempString$ = "Language"
		Case #FVI_Email
			TempString$ = "Email"
		Case #FVI_Website
			TempString$ = "Website"
		Case #FVI_Special
			TempString$ = "Special"
	EndSelect
	ProcedureReturn TempString$
EndProcedure

CompilerIf #PB_Compiler_Unicode
	Prototype.l GetFileVersionInfoSizeW(lptstrFilename.p-unicode, lpdwHandle.l)
	Prototype.l GetFileVersionInfoW(lptstrFilename.p-unicode, dwHandle.l, dwLen.l, lpData.l)
	Prototype.l VerQueryValueW(pBlock.l, lpSubBlock.p-unicode, lplpBuffer.l, puLen.w)
	Prototype.l VerLanguageNameW(wLang.l, szLang.p-unicode, cchLang.l)
CompilerElse
	Prototype.l GetFileVersionInfoSizeA(lptstrFilename.p-ascii, lpdwHandle.l)
	Prototype.l GetFileVersionInfoA(lptstrFilename.p-ascii, dwHandle.l, dwLen.l, lpData.l)
	Prototype.l VerQueryValueA(pBlock.l, lpSubBlock.p-ascii, lplpBuffer.l, puLen.w)
	Prototype.l VerLanguageNameA(wLang.l, szLang.p-ascii, cchLang.l)
CompilerEndIf

Procedure$ GetFileVersionInfoString(lptstrFilename$, FVI_Flag)
	Protected TempString$ = "", TempPtr, TempBlkSize, *TempBlk
	Protected TempLibHandle, TempBuff, TempBuffSize, TempCPLI$, TempLangSize = 128, TempLang$ = Space(TempLangSize)
	;Protected GetFileVersionInfoSize.GetFileVersionInfoSizeA
	;Protected GetFileVersionInfo.GetFileVersionInfoA
	;Protected VerQueryValue.VerQueryValueA
	;Protected VerLanguageName.VerLanguageNameA
	
	If FileSize(lptstrFilename$) >= 0
		TempLibHandle = OpenLibrary(#PB_Any, "version.dll")
		If TempLibHandle
			CompilerIf #PB_Compiler_Unicode
				GetFileVersionInfoSize.GetFileVersionInfoSizeW = GetFunction(TempLibHandle, "GetFileVersionInfoSizeW")
				GetFileVersionInfo.GetFileVersionInfoW = GetFunction(TempLibHandle, "GetFileVersionInfoW")
				VerQueryValue.VerQueryValueW = GetFunction(TempLibHandle, "VerQueryValueW")
				VerLanguageName.VerLanguageNameW = GetFunction(TempLibHandle, "VerLanguageNameW")
			CompilerElse
				GetFileVersionInfoSize.GetFileVersionInfoSizeA = GetFunction(TempLibHandle, "GetFileVersionInfoSizeA")
				GetFileVersionInfo.GetFileVersionInfoA = GetFunction(TempLibHandle, "GetFileVersionInfoA")
				VerQueryValue.VerQueryValueA = GetFunction(TempLibHandle, "VerQueryValueA")
				VerLanguageName.VerLanguageNameA = GetFunction(TempLibHandle, "VerLanguageNameA")
			CompilerEndIf
			
			TempBlkSize = GetFileVersionInfoSize(lptstrFilename$, @TempPtr)
			If TempBlkSize > 0
				*TempBlk = AllocateMemory(TempBlkSize)
				If *TempBlk > 0
					If GetFileVersionInfo(lptstrFilename$, 0, TempBlkSize, *TempBlk)
						If VerQueryValue(*TempBlk, "\\VarFileInfo\\Translation", @TempBuff, @TempBuffSize)
							TempCPLI$ = RSet(Hex(PeekW(TempBuff)), 4, "0") + RSet(Hex(PeekW(TempBuff + 2)), 4, "0")
							VerLanguageName(PeekW(TempBuff), TempLang$, TempLangSize)
						EndIf
						If VerQueryValue(*TempBlk, "\\StringFileInfo\\" + TempCPLI$ + "\\" + GetFileVersionInfo_ElementName(FVI_Flag), @TempBuff, @TempBuffSize)
							TempString$ = PeekS(TempBuff, TempBuffSize)
						EndIf
						If FVI_Flag = #FVI_Language
							TempString$ = TempLang$
						EndIf
					EndIf
				EndIf
				FreeMemory(*TempBlk)
			EndIf
		EndIf
		CloseLibrary(TempLibHandle)
	EndIf
	
	ProcedureReturn(TempString$)
EndProcedure

Prototype.i protoRtlGetVersion (*ver.OSVERSIONINFOEX)

;Procedure.s WindowsVersion()
Procedure$ WINVER()
	Protected ver.OSVERSIONINFOEX
	Protected RtlGetVersion.protoRtlGetVersion
	Protected hDLL.i
	Protected size.i,buffer$,p$,o$,File$,WindowsDirectory$
	
	size=255
	buffer$=Space(size)
	WindowsDirectory$=""
	GetWindowsDirectory_(@buffer$,@size)
	WindowsDirectory$=Trim(buffer$)
	File$=WindowsDirectory$+"\system32\kernel32.dll"
	p$=GetFileVersionInfoString(File$, #FVI_ProductVersion)	;10.0.19041.1741
	o$=StringField(p$,3,".")
	KernelVersionInfo=Val(o$)
	
	ver\dwOSVersionInfoSize = SizeOf(ver)
	
	hDLL = OpenLibrary(#PB_Any, "ntdll.dll")     
	If hDLL   
		RtlGetVersion = GetFunction(hDLL, "RtlGetVersion")
		CloseLibrary(hDLL)       
	EndIf
	
	If RtlGetVersion = 0 Or RtlGetVersion(@ver) <> 0
		ProcedureReturn "Error: Can't call Windows API function RtlGetVersion()."
	EndIf
	
	If ver\dwPlatformId <> #VER_PLATFORM_WIN32_NT
		ProcedureReturn "No Windows NT-based operating system"
	EndIf     
	
	Select ver\dwMajorVersion
		Case 3
			If ver\wProductType = #VER_NT_WORKSTATION
				ProcedureReturn "Windows NT 3.5 Workstation"
			Else
				ProcedureReturn "Windows NT 3.5 Server"
			EndIf
			
		Case 4
			If ver\wProductType = #VER_NT_WORKSTATION
				ProcedureReturn "Windows NT 4.0 Workstation"
			Else
				ProcedureReturn "Windows NT 4.0 Server"
			EndIf
			
		Case 5
			Select ver\dwMinorVersion
				Case 0
					If ver\wProductType = #VER_NT_WORKSTATION
						ProcedureReturn "Windows 2000 Workstation"
					Else
						ProcedureReturn "Windows 2000 Server"
					EndIf
				Case 1
					If (ver\wSuiteMask & #VER_SUITE_PERSONAL)
						ProcedureReturn "Windows XP Home Edition"
					Else
						ProcedureReturn "Windows XP Professional"
					EndIf
				Case 2
					If ver\wProductType = #VER_NT_WORKSTATION
						ProcedureReturn "Windows XP 64-bit Edition"
					Else
						ProcedureReturn "Windows Server 2003"
					EndIf
			EndSelect
			
		Case 6
			Select ver\dwMinorVersion
				Case 0
					If ver\wProductType = #VER_NT_WORKSTATION
						ProcedureReturn "Windows Vista"
					Else
						ProcedureReturn "Windows Server 2008"
					EndIf
				Case 1
					If ver\wProductType = #VER_NT_WORKSTATION
						ProcedureReturn "Windows 7"
					Else
						ProcedureReturn "Windows Server 2008 R2"
					EndIf
				Case 2
					If ver\wProductType = #VER_NT_WORKSTATION
						If KernelVersionInfo>=20348
							ProcedureReturn "Windows 11"
						EndIf
						ProcedureReturn "Windows 8"
					Else
						ProcedureReturn "Windows Server 2012"
					EndIf
				Case 3
					If ver\wProductType = #VER_NT_WORKSTATION
						If KernelVersionInfo>=20348
							ProcedureReturn "Windows 11"
						EndIf
						ProcedureReturn "Windows 8.1"
					Else
						ProcedureReturn "Windows Server 2012 R2"
					EndIf
			EndSelect
			
		Case 10
			If ver\wProductType = #VER_NT_WORKSTATION
				; https://learn.microsoft.com/en-us/windows/release-health/windows11-release-information
				; https://learn.microsoft.com/en-us/windows/release-health/release-information
				If ver\dwBuildNumber >= 22000 Or KernelVersionInfo>=20348
					ProcedureReturn "Windows 11"
				ElseIf ver\dwBuildNumber >= 10240
					ProcedureReturn "Windows 10"
				EndIf
			Else
				; https://learn.microsoft.com/en-us/windows-server/get-started/windows-server-release-info
				If ver\dwBuildNumber >= 20348
					ProcedureReturn "Windows Server 2022"
				ElseIf ver\dwBuildNumber >= 17763
					ProcedureReturn "Windows Server 2019"
				ElseIf ver\dwBuildNumber >= 14393
					ProcedureReturn "Windows Server 2016"
				EndIf  
			EndIf
	EndSelect
	
	ProcedureReturn "Unknown Windows version"
EndProcedure
User avatar
DeanH
Enthusiast
Enthusiast
Posts: 223
Joined: Wed May 07, 2008 4:57 am
Location: Adelaide, South Australia
Contact:

Re: OSVersion for Windows 11 reports as 8

Post by DeanH »

Oops...forgot to add the last line of the work-around code to show it works.

MessageRequester("Win ver",WINVER())
Post Reply