Quantcast
Channel: VBForums - CodeBank - Visual Basic 6 and earlier
Viewing all articles
Browse latest Browse all 1449

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

$
0
0
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.

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.

Viewing all articles
Browse latest Browse all 1449

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>