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()