Results 1 to 40 of 76

Thread: [VB6/VBA/twinBASIC] The quickest way to the real Windows version: KUSER_SHARED_DATA

Threaded View

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,667

    [VB6/VBA/twinBASIC] The quickest way to the real Windows version: KUSER_SHARED_DATA

    The simplest version APIs all lie unless you have a manifest. If you want to be sure you get the real version no matter what, there's various more complicated techniques. The one I had been using involved reading the version info from kernel32.dll. This way is easier, and involves a neat technique. The KUSER_SHARED_DATA type is always resident in memory. You can declare it, then copy it, with no APIs besides CopyMemory.

    The version info can be extracted directly. To use this, you need no declares besides CopyMemory:

    Code:
            Dim dwMajor As Long, dwMinor As Long, dwBuild As Long
            CopyMemory dwMajor, ByVal &H7FFE026C, 4
            CopyMemory dwMinor, ByVal &H7FFE0270, 4
            CopyMemory dwBuild, ByVal &H7FFE0260, 4
            Debug.Print dwMajor & "." & dwMinor & "." & dwBuild
    That's based on the offsets of the members of the full type.

    If you're interested in the full type, the following is the expanded form: It also returns a ton of other info.

    Code:
    Public Type LARGE_INTEGER
    #If (TWINBASIC = 1) Or (Win64 = 1) Then
        QuadPart As LongLong
    #Else
       lowpart As Long
       highpart As Long
    #End If
    End Type
    Public Type KSYSTEM_TIME
        LowPart As Long '0x0
        High1Time As Long '0x4
        High2Time As Long '0x8
    End Type
    Public Enum NT_PRODUCT_TYPE
        NtProductWinNt = 1
        NtProductLanManNt = 2
        NtProductServer = 3
    End Enum
    Public Enum ALTERNATIVE_ARCHITECTURE_TYPE
        StandardDesign = 0
        NEC98x86 = 1
        EndAlternatives = 2
    End Enum
    Public Enum VER_SUITE_VALUES
        VER_SERVER_NT = &H80000000
        VER_WORKSTATION_NT = &H40000000
        VER_SUITE_SMALLBUSINESS = &H00000001
        VER_SUITE_ENTERPRISE = &H00000002
        VER_SUITE_BACKOFFICE = &H00000004
        VER_SUITE_COMMUNICATIONS = &H00000008
        VER_SUITE_TERMINAL = &H00000010
        VER_SUITE_SMALLBUSINESS_RESTRICTED = &H00000020
        VER_SUITE_EMBEDDEDNT = &H00000040
        VER_SUITE_DATACENTER = &H00000080
        VER_SUITE_SINGLEUSERTS = &H00000100
        VER_SUITE_PERSONAL = &H00000200
        VER_SUITE_BLADE = &H00000400
        VER_SUITE_EMBEDDED_RESTRICTED = &H00000800
        VER_SUITE_SECURITY_APPLIANCE = &H00001000
        VER_SUITE_STORAGE_SERVER = &H00002000
        VER_SUITE_COMPUTE_SERVER = &H00004000
        VER_SUITE_WH_SERVER = &H00008000&
        VER_SUITE_MULTIUSERTS = &H00020000
    End Enum
    
    Public Type KUSER_SHARED_DATA
        TickCountLowDeprecated As Long '0x0
        TickCountMultiplier As Long '0x4
        InterruptTime As KSYSTEM_TIME '0x8
        SystemTime As KSYSTEM_TIME '0x14
        TimeZoneBias As KSYSTEM_TIME '0x20
        ImageNumberLow As Integer '0x2c
        ImageNumberHigh As Integer '0x2e
        NtSystemRoot(0 To 259) As Integer '0x30
        MaxStackTraceDepth As Long '0x238
        CryptoExponent As Long '0x23c
        TimeZoneId As Long '0x240
        LargePageMinimum As Long '0x244
        ' Reserved2(0 To 6) As Long '0x248
        AitSamplingValue As Long '0x24C
        AppCompatFlag As Long '0x250
        #If (TWINBASIC = 1) Or (Win64 = 1) Then
        RNGSeedVersion As LongLong
        #Else
        RNGSeedVersion As Currency
        #End If
        GlobalValidationRunlevel As Long
        TimeZoneBiasStamp As Long
        NtBuildNumber As Long
        NtProductType As NT_PRODUCT_TYPE '0x264
        ProductTypeIsValid As Byte '0x268
        Reserved0 As Byte
        NativeProcessorArchitecture As Integer
        NtMajorVersion As Long '0x26c
        NtMinorVersion As Long '0x270
        ProcessorFeatures(0 To 63) As Byte '0x274
        Reserved1 As Long '0x2b4
        Reserved3 As Long '0x2b8
        TimeSlip As Long '0x2bc
        AlternativeArchitecture As ALTERNATIVE_ARCHITECTURE_TYPE '0x2c0
        BootId As Long 'Windows 10+ only
        SystemExpirationDate As LARGE_INTEGER '0x2c8
        SuiteMask As VER_SUITE_VALUES '0x2d0
        KdDebuggerEnabled As Byte '0x2d4
        MitigationPolicies As Byte '0x2d5
        CyclesPerYield As Integer 'Only on Win10 1903 and higher
        ActiveConsoleId As Long '0x2d8
        DismountCount As Long '0x2dc
        ComPlusPackage As Long '0x2e0
        LastSystemRITEventTickCount As Long '0x2e4
        NumberOfPhysicalPages As Long '0x2e8
        SafeBootMode As Byte '0x2ec
        VirtualizationFlags As Byte
        Reserved12(1) As Byte
        SharedDataFlags As Long '0x2f0 NOTE: TraceLogging on 2k/XP
        DataFlagsPad(0) As Long
        #If (TWINBASIC = 1) Or (Win64 = 1) Then
        TestRetInstruction As LongLong '0x2f8
        #Else
        TestRetInstruction As Currency
        #End If
        SystemCall As Long '0x300
        SystemCallReturn As Long '0x304
        #If (TWINBASIC = 1) Or (Win64 = 1) Then
        SystemCallPad(0 To 2) As LongLong '0x308
        TickCountQuad As LongLong '0x320
        #Else
        SystemCallPad(0 To 2) As Currency    
        TickCountQuad As Currency
        #End If
        'union
        '{
        '    volatile struct _KSYSTEM_TIME TickCount;                            //0x320
        'TickCount As KSYSTEM_TIME
        ReservedTickCountOverlay(1) As Long 'Since not using _KSYSTEM_TIME
        '};
        Cookie As Long '0x330
        'Wow64SharedInformation(0 To 15) As Long '0x334
    End Type
    There's a lot more on the end, but it's not particularly useful, varies from version to version. The one given will work on XP-11.
    Then using it is as simple as:

    Code:
    #If VBA7 Then
    Public Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
    #Else
    Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
    #End If
    
        Private Sub ReadRealVersion()
            Dim kusd As KUSER_SHARED_DATA
            CopyMemory kusd, ByVal &H7ffe0000, LenB(kusd)
            Debug.Print kusd.NtMajorVersion & "." & kusd.NtMinorVersion & "." & kusd.NtBuildNumber
        End Sub
    The address is the same for both 32bit and 64bit, so need for an alternate version.

    The type as provided here is compatible with XP through 11. Build number is only correct on 10/11, but it's much less significant earlier anyway. The type can be truncated after ProcessorFeatures for Windows 2000 and NT4 compatibility-- the top snippet without declares works on NT4-11.
    Last edited by fafalone; Mar 21st, 2024 at 04:28 AM.

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