Results 1 to 12 of 12

Thread: Calling IsWindows10OrGreater from VB6 in Windows 10

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Oct 2014
    Posts
    94

    Calling IsWindows10OrGreater from VB6 in Windows 10

    Generally I use RtlGetVersion to check whether my VB6 app is running in Windows 10. But this time I wanted to know whether I can use IsWindows10OrGreater for this purpose and test this WinAPI function in various environments. Sadly enough, but I could not call it from VB6. My declarations like this

    Code:
    Private Declare Function IsWindows10OrGreater Lib "Kernel32" () As Boolean
    simply gave me the run-time error 453 "Can't find DLL entry point". I tried it in the VB6 IDE and in the compiled exe - nothing helped.

    Is it possible to call IsWindows10OrGreater from a VB6 app? Do we need to target our app for Win10 or do any other thing for that?

  2. #2
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: Calling IsWindows10OrGreater from VB6 in Windows 10

    IsWindows10OrGreater is an inline function, that calls other APIs in kernel32. It doesn't actually exist in the dll in a callable form.
    I think someone posted a translated version though- lemme try and fine one.


    MVersionHelpers.bas
    Code:
    ' MVersionHelpers.bas - VB translation of VersionHelpers.h
    Option Explicit
    
    Private Const WIN32_WINNT_NT4       As Integer = &H400
    Private Const WIN32_WINNT_WIN2K     As Integer = &H500
    Private Const WIN32_WINNT_WINXP     As Integer = &H501
    Private Const WIN32_WINNT_WS03      As Integer = &H502
    Private Const WIN32_WINNT_WIN6      As Integer = &H600
    Private Const WIN32_WINNT_VISTA     As Integer = &H600
    Private Const WIN32_WINNT_WS08      As Integer = &H600
    Private Const WIN32_WINNT_LONGHORN  As Integer = &H600
    Private Const WIN32_WINNT_WIN7      As Integer = &H601
    Private Const WIN32_WINNT_WIN8      As Integer = &H602
    Private Const WIN32_WINNT_WINBLUE   As Integer = &H603  ' Windows 8.1
    Private Const WIN32_WINNT_WIN10     As Integer = &HA00
    Private Const WIN32_WINNT_WIN10AU   As Integer = &HA01  ' Anniversary Update
    Private Const WIN32_WINNT_WIN10CU   As Integer = &HA02  ' Creators Update
    
    Private Type TOSVERSIONINFOEXW ' same as RTL_OSVERSIONINFOEXW
        dwOSVersionInfoSize As Long
        dwMajorVersion      As Long
        dwMinorVersion      As Long
        dwBuildNumber       As Long
        dwPlatformId        As Long
        szCSDVersion(128 * 2 - 1) As Byte
        wServicePackMajor   As Integer
        wServicePackMinor   As Integer
        wSuiteMask          As Integer
        wProductType        As Byte ' MS likes messing up type prefixes.
        wReserved           As Byte ' These last 2 are BYTE, not WORD (w). see winnt.h
    End Type
    
    Private Declare Function RtlGetVersion Lib "ntdll" (ByRef lpVersionInformation As Any) As Long
    Private Declare Function VerSetConditionMask Lib "kernel32" (ByVal dwlConditionMask As Currency, ByVal dwTypeBitMask As Long, ByVal dwConditionMask As Byte) As Currency
    Private Declare Function VerifyVersionInfoW Lib "kernel32" (ByRef lpVersionInfo As Any, ByVal dwTypeMask As Long, ByVal dwlConditionMask As Currency) As Long
    Private Const VER_PRODUCT_TYPE As Long = &H80&
    Private Const VER_GREATER_EQUAL As Long = 3
    Private Const VER_EQUAL As Long = 1
    Private Const VER_MAJORVERSION As Long = &H2
    Private Const VER_MINORVERSION As Long = &H1
    Private Const VER_SERVICEPACKMAJOR As Long = &H20
    Private Const VER_NT_WORKSTATION As Long = 1
    
    
    Public Function IsWindowsVersionOrGreater(ByVal wMajorVersion As Integer, _
                                              ByVal wMinorVersion As Integer, _
                                              ByVal wServicePackMajor As Integer, _
                                              Optional ByVal dwBuild As Long) As Boolean
    '    Dim osvi As TOSVERSIONINFOEXW
    '    osvi.dwOSVersionInfoSize = LenB(osvi)
    '
    '    Dim dwlConditionMask As Currency
    '    dwlConditionMask = VerSetConditionMask( _
    '        VerSetConditionMask( _
    '        VerSetConditionMask( _
    '            0, VER_MAJORVERSION, VER_GREATER_EQUAL), _
    '               VER_MINORVERSION, VER_GREATER_EQUAL), _
    '               VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL)
    '
    '    osvi.dwMajorVersion = wMajorVersion
    '    osvi.dwMinorVersion = wMinorVersion
    '    osvi.wServicePackMajor = wServicePackMajor
    '
    '    IsWindowsVersionOrGreater = VerifyVersionInfoW( _
    '        osvi, _
    '        VER_MAJORVERSION Or VER_MINORVERSION Or VER_SERVICEPACKMAJOR, _
    '        dwlConditionMask)
    
        Dim verInfo As TOSVERSIONINFOEXW 'RTL_OSVERSIONINFOEXW
        verInfo.dwOSVersionInfoSize = LenB(verInfo)
    
        ' Calling RtlGetVersion directly is faster and doesn't depend on
        ' a manifest or minimum subsystem. It will still lie if running
        ' with compatibility shim.
        If RtlGetVersion(verInfo) = 0 Then
            With verInfo
                Select Case True
                Case .dwMajorVersion > wMajorVersion:        IsWindowsVersionOrGreater = True
                Case .dwMajorVersion < wMajorVersion:        IsWindowsVersionOrGreater = False
                Case .dwMinorVersion > wMinorVersion:        IsWindowsVersionOrGreater = True
                Case .dwMinorVersion < wMinorVersion:        IsWindowsVersionOrGreater = False
                Case .wServicePackMajor > wServicePackMajor: IsWindowsVersionOrGreater = True
                Case .wServicePackMajor < wServicePackMajor: IsWindowsVersionOrGreater = False
                Case .dwBuildNumber >= dwBuild:              IsWindowsVersionOrGreater = True
                End Select
            End With
        End If
    End Function
    
    Private Function HIBYTE(ByVal W As Integer) As Byte
        HIBYTE = (W And &H7FFF) \ &H100
        If W < 0 Then HIBYTE = HIBYTE Or &H80
    End Function
    
    Private Function LOBYTE(ByVal W As Integer) As Byte
        LOBYTE = W And &HFF
    End Function
    
    Public Function IsWindowsXPOrGreater() As Boolean
        IsWindowsXPOrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WINXP), LOBYTE(WIN32_WINNT_WINXP), 0)
    End Function
    
    Public Function IsWindowsXPSP1OrGreater() As Boolean
        IsWindowsXPSP1OrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WINXP), LOBYTE(WIN32_WINNT_WINXP), 1)
    End Function
    
    Public Function IsWindowsXPSP2OrGreater() As Boolean
        IsWindowsXPSP2OrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WINXP), LOBYTE(WIN32_WINNT_WINXP), 2)
    End Function
    
    Public Function IsWindowsXPSP3OrGreater() As Boolean
        IsWindowsXPSP3OrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WINXP), LOBYTE(WIN32_WINNT_WINXP), 3)
    End Function
    
    Public Function IsWindowsVistaOrGreater() As Boolean
        IsWindowsVistaOrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_VISTA), LOBYTE(WIN32_WINNT_VISTA), 0)
    End Function
    
    Public Function IsWindowsVistaSP1OrGreater() As Boolean
        IsWindowsVistaSP1OrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_VISTA), LOBYTE(WIN32_WINNT_VISTA), 1)
    End Function
    
    Public Function IsWindowsVistaSP2OrGreater() As Boolean
        IsWindowsVistaSP2OrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_VISTA), LOBYTE(WIN32_WINNT_VISTA), 2)
    End Function
    
    Public Function IsWindows7OrGreater() As Boolean
        IsWindows7OrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WIN7), LOBYTE(WIN32_WINNT_WIN7), 0)
    End Function
    
    Public Function IsWindows7SP1OrGreater() As Boolean
        IsWindows7SP1OrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WIN7), LOBYTE(WIN32_WINNT_WIN7), 1)
    End Function
    
    Public Function IsWindows8OrGreater() As Boolean
        IsWindows8OrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WIN8), LOBYTE(WIN32_WINNT_WIN8), 0)
    End Function
    
    Public Function IsWindows8Point1OrGreater() As Boolean
        IsWindows8Point1OrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WINBLUE), LOBYTE(WIN32_WINNT_WINBLUE), 0)
    End Function
    
    Public Function IsWindows10OrGreater() As Boolean
        IsWindows10OrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WIN10), LOBYTE(WIN32_WINNT_WIN10), 0)
    End Function
    
    Public Function IsWindows10AnniversaryOrGreater() As Boolean
        IsWindows10AnniversaryOrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WIN10AU), LOBYTE(WIN32_WINNT_WIN10AU), 0, 14393)
    End Function
    
    Public Function IsWindows10CreatorsOrGreater() As Boolean
        IsWindows10CreatorsOrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WIN10CU), LOBYTE(WIN32_WINNT_WIN10CU), 0, 15063)
    End Function
    
    Public Function IsWindowsServer() As Boolean
        Dim osvi As TOSVERSIONINFOEXW
        osvi.dwOSVersionInfoSize = LenB(osvi)
        osvi.wProductType = VER_NT_WORKSTATION
        
        Dim dwlConditionMask As Currency
        dwlConditionMask = VerSetConditionMask(0, VER_PRODUCT_TYPE, VER_EQUAL)
        IsWindowsServer = Not CBool(VerifyVersionInfoW(osvi, VER_PRODUCT_TYPE, dwlConditionMask))
    End Function
    Last edited by DEXWERX; Jun 23rd, 2017 at 01:07 PM. Reason: replaced LongLong with Currency

  3. #3

    Thread Starter
    Lively Member
    Join Date
    Oct 2014
    Posts
    94

    Re: Calling IsWindows10OrGreater from VB6 in Windows 10

    Damn, the MSDN writers should mention that a function is inline explicitly and noticeably in the function topic - not only with a word "inline" in a sentence in the Example section.

  4. #4
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: Calling IsWindows10OrGreater from VB6 in Windows 10

    not only that - but VerifyVersionInfoW is subject to the same Manifest shenanigans that caused us to start calling RtlGetVersion in the first place.


    https://stackoverflow.com/questions/...-on-windows-10

  5. #5

    Thread Starter
    Lively Member
    Join Date
    Oct 2014
    Posts
    94

    Re: Calling IsWindows10OrGreater from VB6 in Windows 10

    Do you want to say that the best way to determine whether we are in Win10 is still RtlGetVersion? It seems the following code I have been using for a couple of years has never let me down:

    Code:
    Private Declare Function RtlGetVersion Lib "NTDLL" (ByRef lpVersionInformation As Long) As Long
    
    Public Sub NativeGetVersion(ByRef plMajorVer As Long, ByRef plMinorVer As Long)
       Dim tOSVw(&H54) As Long
       tOSVw(0) = &H54 * &H4
       RtlGetVersion tOSVw(0)
       plMajorVer = tOSVw(1)
       plMinorVer = tOSVw(2)
    End Sub
    
    Dim lOSMajorVer As Long
    Dim lOSMinorVer As Long
    NativeGetVersion lOSMajorVer, lOSMinorVer
    
    bIsWin10 = (lOSMajorVer >= 10)

  6. #6
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: Calling IsWindows10OrGreater from VB6 in Windows 10

    Quote Originally Posted by wisekat View Post
    Do you want to say that the best way to determine whether we are in Win10 is still RtlGetVersion? It seems the following code I have been using for a couple of years has never let me down:

    Code:
    Private Declare Function RtlGetVersion Lib "NTDLL" (ByRef lpVersionInformation As Long) As Long
    
    Public Sub NativeGetVersion(ByRef plMajorVer As Long, ByRef plMinorVer As Long)
       Dim tOSVw(&H54) As Long
       tOSVw(0) = &H54 * &H4
       RtlGetVersion tOSVw(0)
       plMajorVer = tOSVw(1)
       plMinorVer = tOSVw(2)
    End Sub
    
    Dim lOSMajorVer As Long
    Dim lOSMinorVer As Long
    NativeGetVersion lOSMajorVer, lOSMinorVer
    
    bIsWin10 = (lOSMajorVer >= 10)
    Definitely,
    RtlGetVersion has been the most reliable across all OS's and it's not dependent on minimum subsystem or manifest.
    Even the code I posted above has a faster version commented out that calls RtlGetVersion.

    I just don't know if it's legal to call from a Windows Store App, I thought some APIs are restricted, but if you're targeting the store, you can manifest/subsystem for windows 10 anyway.

  7. #7

    Thread Starter
    Lively Member
    Join Date
    Oct 2014
    Posts
    94

    Re: Calling IsWindows10OrGreater from VB6 in Windows 10

    Just a comment regarding one situation when RtlGetVersion can lie - or at least, I though so in the beginning

    Today RtlGetVersion returned 6 in the OSMajorVersion parameter on my pc with Windows 10 Pro. I thought Microsoft had changed something again with the Creators Update, but after some thinking I found the source of the problem:

    Name:  2017-06-23_17h53_55.jpg
Views: 2093
Size:  64.3 KB

    Most likely, that's right if RtlGetVersion returns the OS version number taking into account this compatibility settings...

  8. #8
    Ex-Super Mod RobDog888's Avatar
    Join Date
    Apr 2001
    Location
    LA, Calif. Raiders #1 AKA:Gangsta Yoda™
    Posts
    60,710

    Re: Calling IsWindows10OrGreater from VB6 in Windows 10

    Quote Originally Posted by wisekat View Post
    Damn, the MSDN writers should mention that a function is inline explicitly and noticeably in the function topic - not only with a word "inline" in a sentence in the Example section.
    They did mention it,

    The inline functions defined in the VersionHelpers.h header file let you verify the operating system version by returning a Boolean value when testing for a version of Windows.
    If you want to pinpoint a version you can use IsWindowsVersionOrGreater
    VB/Office Guru™ (AKA: Gangsta Yoda®)
    I dont answer coding questions via PM. Please post a thread in the appropriate forum.

    Microsoft MVP 2006-2011
    Office Development FAQ (C#, VB.NET, VB 6, VBA)
    Senior Jedi Software Engineer MCP (VB 6 & .NET), BSEE, CET
    If a post has helped you then Please Rate it!
    Reps & Rating PostsVS.NET on Vista Multiple .NET Framework Versions Office Primary Interop AssembliesVB/Office Guru™ Word SpellChecker™.NETVB/Office Guru™ Word SpellChecker™ VB6VB.NET Attributes Ex.Outlook Global Address ListAPI Viewer utility.NET API Viewer Utility
    System: Intel i7 6850K, Geforce GTX1060, Samsung M.2 1 TB & SATA 500 GB, 32 GBs DDR4 3300 Quad Channel RAM, 2 Viewsonic 24" LCDs, Windows 10, Office 2016, VS 2019, VB6 SP6

  9. #9
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: Calling IsWindows10OrGreater from VB6 in Windows 10

    Quote Originally Posted by RobDog888 View Post
    If you want to pinpoint a version you can use IsWindowsVersionOrGreater
    a translation of IsWindowsVersionOrGreater can also be found in post #2

  10. #10
    Ex-Super Mod RobDog888's Avatar
    Join Date
    Apr 2001
    Location
    LA, Calif. Raiders #1 AKA:Gangsta Yoda™
    Posts
    60,710

    Re: Calling IsWindows10OrGreater from VB6 in Windows 10

    Quote Originally Posted by DEXWERX View Post
    a translation of IsWindowsVersionOrGreater can also be found in post #2
    My oversight,
    VB/Office Guru™ (AKA: Gangsta Yoda®)
    I dont answer coding questions via PM. Please post a thread in the appropriate forum.

    Microsoft MVP 2006-2011
    Office Development FAQ (C#, VB.NET, VB 6, VBA)
    Senior Jedi Software Engineer MCP (VB 6 & .NET), BSEE, CET
    If a post has helped you then Please Rate it!
    Reps & Rating PostsVS.NET on Vista Multiple .NET Framework Versions Office Primary Interop AssembliesVB/Office Guru™ Word SpellChecker™.NETVB/Office Guru™ Word SpellChecker™ VB6VB.NET Attributes Ex.Outlook Global Address ListAPI Viewer utility.NET API Viewer Utility
    System: Intel i7 6850K, Geforce GTX1060, Samsung M.2 1 TB & SATA 500 GB, 32 GBs DDR4 3300 Quad Channel RAM, 2 Viewsonic 24" LCDs, Windows 10, Office 2016, VS 2019, VB6 SP6

  11. #11
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,852

    Re: Calling IsWindows10OrGreater from VB6 in Windows 10

    This is the one I use, especially when I want to circumvent any shims/compatibility settings I've got:

    Code:
    
    Public Function WindowsVersion() As Long
        '
        ' This is independent of any manifest or any compatibility settings.
        '
        '    OS              WindowsVersion return
        ' Windows 10                100
        ' Windows 8.1                63
        ' Windows 8.0                62
        ' Windows 7                  61
        ' Windows Vista              60
        ' Windows XP                 51
        ' Windows 2000               50
        '                            -1 failed.
        Static lVersion As Long
        Dim SystemSet As Object
        Dim System As Object
        Dim s As String
        Dim i As Long
        '
        If lVersion Then
            WindowsVersion = lVersion
            Exit Function
        End If
        '
        On Error Resume Next
            Set SystemSet = GetObject("winmgmts:").InstancesOf("Win32_OperatingSystem")
            For Each System In SystemSet: s = System.Version: Next
            '
            i = InStr(s, ".")
            s = Left$(s, i - 1) & Mid$(s, i + 1)
            i = InStr(s, ".")
            If i Then s = Left$(s, i - 1)
            lVersion = Val(s)
            WindowsVersion = lVersion
        On Error GoTo 0
    End Function
    
    
    And it works equally well in the IDE as a compiled program.

    Enjoy,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  12. #12
    New Member
    Join Date
    Feb 2019
    Posts
    1

    Re: Calling IsWindows10OrGreater from VB6 in Windows 10

    Quote Originally Posted by Elroy View Post
    This is the one I use, especially when I want to circumvent any shims/compatibility settings I've got:

    Code:
    
    Public Function WindowsVersion() As Long
        '
        ' This is independent of any manifest or any compatibility settings.
        '
        '    OS              WindowsVersion return
        ' Windows 10                100
        ' Windows 8.1                63
        ' Windows 8.0                62
        ' Windows 7                  61
        ' Windows Vista              60
        ' Windows XP                 51
        ' Windows 2000               50
        '                            -1 failed.
        Static lVersion As Long
        Dim SystemSet As Object
        Dim System As Object
        Dim s As String
        Dim i As Long
        '
        If lVersion Then
            WindowsVersion = lVersion
            Exit Function
        End If
        '
        On Error Resume Next
            Set SystemSet = GetObject("winmgmts:").InstancesOf("Win32_OperatingSystem")
            For Each System In SystemSet: s = System.Version: Next
            '
            i = InStr(s, ".")
            s = Left$(s, i - 1) & Mid$(s, i + 1)
            i = InStr(s, ".")
            If i Then s = Left$(s, i - 1)
            lVersion = Val(s)
            WindowsVersion = lVersion
        On Error GoTo 0
    End Function
    
    
    And it works equally well in the IDE as a compiled program.

    Enjoy,
    Elroy

    This is great Elroy, works like a champ from my VB6 app. Simple, yet elegant!

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width