Share your advanced PureBasic knowledge/code with the community.
Little John
Addict
Posts: 4527 Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany
Post
by Little John » Sat Jun 17, 2017 9:20 am
The return value of the built-in Function
OSVersion() is not always reliable, when a program which was compiled with an older PB version runs on newer Windows versions.
For instance,
OSVersion() of PB 5.31 returns 90 when running on Windows 8 ... but it also returns 90 when running on Windows 10. So it's not possible for the program to distinguish between Windows 8 and Windows 10. The following code can do so.
//edit 2022-11-14:
See
updated version below by ChrisR , which also covers Windows 11.
BTW, in case you wonder at the post below in this thread by that "expert" (who has repeatedly been banned from the forum): In contrast to his belief, it's not me who is responsible for his confusion.
Code: Select all
; after
; https://msdn.microsoft.com/en-us/library/windows/hardware/ff563620(v=vs.85).aspx
; https://stackoverflow.com/questions/38102565/how-can-a-vb-6-app-determine-if-it-is-running-on-windows-10
; tested with PB 5.31, 5.44 LTS, 5.60
EnableExplicit
Prototype.i protoRtlGetVersion (*ver.OSVERSIONINFOEX)
Procedure.s WindowsVersion()
Protected ver.OSVERSIONINFOEX
Protected RtlGetVersion.protoRtlGetVersion
Protected hDLL.i
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
ProcedureReturn "Windows 8"
Else
ProcedureReturn "Windows Server 2012"
EndIf
Case 3
If ver\wProductType = #VER_NT_WORKSTATION
ProcedureReturn "Windows 8.1"
Else
ProcedureReturn "Windows Server 2012 R2"
EndIf
EndSelect
Case 10
If ver\wProductType = #VER_NT_WORKSTATION
ProcedureReturn "Windows 10"
Else
ProcedureReturn "Windows Server 2016"
EndIf
EndSelect
ProcedureReturn "Unknown Windows version"
EndProcedure
Debug WindowsVersion()
Last edited by
Little John on Mon Nov 14, 2022 5:37 pm, edited 2 times in total.
freak
PureBasic Team
Posts: 5929 Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany
Post
by freak » Sat Jun 17, 2017 1:30 pm
Kindergarden fight deleted. This section is for code snippets, not flame wars.
quidquid Latine dictum sit altum videtur
Little John
Addict
Posts: 4527 Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany
Post
by Little John » Sat Jun 17, 2017 1:44 pm
Thank you, freak.
luis
Addict
Posts: 3876 Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy
Post
by luis » Sat Jun 17, 2017 1:52 pm
There is also this older thread discussing the problem of the false version returned by the OS if interested ->
http://www.purebasic.fr/english/viewtop ... =5&t=57368
About "my point" for citing the other thread, since someone
may angrily ask
I did that because in that thread there are mentioned the historical reasons why this OS behavior has been implemented with a link to a MS page explaining that. Also the same kernel API is used there with some comments about its relation to other higher lever os API which use it.
Also alternative methods are shown to solve the same problem using WMI and more.
So, if someone is interested in what shown in this thread because he's using an older PB version for whatever reason he may be interested in what shown there too.
Fair enough ?
skywalk
Addict
Posts: 4003 Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA
Post
by skywalk » Sat Jun 17, 2017 3:39 pm
Thanks Little John.
#ERRORAPI = 0, is already defined in PB's constants.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
RSBasic
Moderator
Posts: 1218 Joined: Thu Dec 31, 2009 11:05 pm
Location: Gernsbach (Germany)
Contact:
Post
by RSBasic » Sat Jun 17, 2017 6:38 pm
Hello Little John
Thank you for your code.
skywalk
Addict
Posts: 4003 Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA
Post
by skywalk » Sat Jun 17, 2017 6:44 pm
@Fluid Byte...you require much explanations lately. I use #ERRORAPI with getlasterror_().
Code: Select all
Procedure.s SL_GetLastError(LastError.i)
; SetLastError_(#ERROR_ACCESS_DENIED)
; Debug SL_GetLastError(#ERROR_ACCESS_DENIED)
; or
; SL_GetLastError(GetLastError_())
Protected.i *e, lene
Protected.s e$
lene = FormatMessage_(#FORMAT_MESSAGE_ALLOCATE_BUFFER | #FORMAT_MESSAGE_FROM_SYSTEM, 0, LastError, GetUserDefaultLangID_(), @*e, 0, 0)
If lene
e$ = RemoveString(PeekS(*e), #CRLF$)
LocalFree_(*e)
e$ = "Error " + Str(LastError) + ": " + e$
Else
e$ = "Error " + Str(LastError)
EndIf
ProcedureReturn e$
EndProcedure
;// snippet
Protected SL_RtlGetVersion.SL_RtlGetVersion = GetFunction(hDLL, "RtlGetVersion")
ri = SL_RtlGetVersion(@ver)
If ri <> #ERRORAPI
winVer$ = "ntdll.dll - RtlGetVersion() - " + SL_GetLastError(ri)
Else
;// snippet
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Little John
Addict
Posts: 4527 Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany
Post
by Little John » Sun Jun 18, 2017 12:21 am
Hi,
thanks for your replies.
Luis, I appreciate your comments and the link to additional information.
skywalk wrote: Thanks Little John.
#ERRORAPI = 0, is already defined in PB's constants.
Well,
So I used that.
Didn't know about #ERRORAPI, thanks for the information.
RSBasic, please feel free to include this code into your Win API library, if you think it makes sense.
Fluid Byte
Addict
Posts: 2336 Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany
Post
by Fluid Byte » Sun Jun 25, 2017 7:40 pm
Since freak abused his moderator rights and deleted all my post whilst having valid criticism I need to clarify that this code is still f***** pointless. You couldn't name a single example where you would have to back so many previous releases that would force you to use the broken bulit-in OSVersion() function.
It's a weak, or rather non-existent argument to begin with since by that logic you would have to provide EVERY PB-Command ever introduced as an alternative API solution for the case that they MIGHT not work properly in older versions.
Again, you are confusing new and old users alike by providing a solution to a problem that doesn't exist.
Rings
Moderator
Posts: 1427 Joined: Sat Apr 26, 2003 1:11 am
Post
by Rings » Sun Jun 25, 2017 9:00 pm
Fluid Byte wrote: Since freak abused his moderator rights and deleted all my post whilst having valid criticism I need to clarify that this code is still f****** pointless. You couldn't name a single example where you would have to back so many previous releases that would force you to use the broken bulit-in OSVersion() function.
It's a weak, or rather non-existent argument to begin with since by that logic you would have to provide EVERY PB-Command ever introduced as an alternative API solution for the case that they MIGHT not work properly in older versions.
Again, you are confusing new and old users alike by providing a solution to a problem that doesn't exist.
banned again,
greets
SPAMINATOR NR.1
ChrisR
Addict
Posts: 1154 Joined: Sun Jan 08, 2017 10:27 pm
Location: France
Post
by ChrisR » Mon Nov 14, 2022 10:45 am
The major and minor version numbers have remained the same between Windows 10 and Windows 11 (10.0).
It is also the same for Windows Server 2016, 2019 and 2022.
Here is a small addition to differentiate them via the Build number:
See:
Windows 10 release information
Windows 11 release information
Windows Server release information
Code: Select all
; after
; https://msdn.microsoft.com/en-us/library/windows/hardware/ff563620(v=vs.85).aspx
; https://stackoverflow.com/questions/38102565/how-can-a-vb-6-app-determine-if-it-is-running-on-windows-10
; tested with PB 5.31, 5.44 LTS, 5.60
EnableExplicit
Prototype.i protoRtlGetVersion (*ver.OSVERSIONINFOEX)
Procedure.s WindowsVersion()
Protected ver.OSVERSIONINFOEX
Protected RtlGetVersion.protoRtlGetVersion
Protected hDLL.i
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
ProcedureReturn "Windows 8"
Else
ProcedureReturn "Windows Server 2012"
EndIf
Case 3
If ver\wProductType = #VER_NT_WORKSTATION
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
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()
Little John
Addict
Posts: 4527 Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany
Post
by Little John » Mon Nov 14, 2022 5:40 pm
Many thanks, ChrisR
I added a link to the first post of this thread, that points to your extended version.