[Done] Change GetVersionEx to RtlGetVersion Topic is solved

Report problems with documented functionality
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

[Done] Change GetVersionEx to RtlGetVersion

22 Jan 2015, 02:33

GetVersionEx has some problems go get the right Build and Minor Number in Windows 10!
Image

Operating System Version:

Code: Select all

Windows 10      6.4
Windows 8.1     6.3
Windows 8       6.2
Windows 7       6.1
RtlGetVersion function

Code: Select all

RtlGetVersion()
{
    static RTL_OSVIEX, init := VarSetCapacity(RTL_OSVIEX, 284, 0) && NumPut(284, RTL_OSVIEX, "UInt")
    if (DllCall("ntdll.dll\RtlGetVersion", "Ptr", &RTL_OSVIEX) != 0)
		return "Error in RtlGetVersion"
    return { 1 : NumGet(RTL_OSVIEX,   0, "UInt"  ),  2 : NumGet(RTL_OSVIEX,         4, "UInt"  )
           , 3 : NumGet(RTL_OSVIEX,   8, "UInt"  ),  4 : NumGet(RTL_OSVIEX,        12, "UInt"  )
           , 5 : NumGet(RTL_OSVIEX,  16, "UInt"  ),  6 : StrGet(&RTL_OSVIEX + 20, 128, "UTF-16")
           , 7 : NumGet(RTL_OSVIEX, 276, "UShort"),  8 : NumGet(RTL_OSVIEX,       278, "UShort")
           , 9 : NumGet(RTL_OSVIEX, 280, "UShort"), 10 : NumGet(RTL_OSVIEX,       282, "UChar" ) }
}

RtlGetVersion := RtlGetVersion()

MsgBox % "RtlGetVersion function`n"
       . "RTL_OSVERSIONINFOEXW structure`n`n"
       . "OSVersionInfoSize:`t`t"     RtlGetVersion[1]   "`n"
       . "MajorVersion:`t`t"          RtlGetVersion[2]   "`n"
       . "MinorVersion:`t`t"          RtlGetVersion[3]   "`n"
       . "BuildNumber:`t`t"           RtlGetVersion[4]   "`n"
       . "PlatformId:`t`t"            RtlGetVersion[5]   "`n"
       . "CSDVersion:`t`t"            RtlGetVersion[6]   "`n"
       . "ServicePackMajor:`t`t"      RtlGetVersion[7]   "`n"
       . "ServicePackMinor:`t`t"      RtlGetVersion[8]   "`n"
       . "SuiteMask:`t`t"             RtlGetVersion[9]   "`n"
       . "ProductType:`t`t"           RtlGetVersion[10]
GetVersionEx function

Code: Select all

GetVersionEx()
{
    static OSVEREX, init := VarSetCapacity(OSVEREX, 284, 0) && NumPut(284, OSVEREX, "UInt")
    if !(DllCall("kernel32.dll\GetVersionEx", "Ptr", &OSVEREX))
        return DllCall("kernel32.dll\GetLastError")
    return { 1 : NumGet(OSVEREX,   0, "UInt"  ),  2 : NumGet(OSVEREX,         4, "UInt"  )
           , 3 : NumGet(OSVEREX,   8, "UInt"  ),  4 : NumGet(OSVEREX,        12, "UInt"  )
           , 5 : NumGet(OSVEREX,  16, "UInt"  ),  6 : StrGet(&OSVEREX + 20, 128, "UTF-16")
           , 7 : NumGet(OSVEREX, 276, "UShort"),  8 : NumGet(OSVEREX,       278, "UShort")
           , 9 : NumGet(OSVEREX, 280, "UShort"), 10 : NumGet(OSVEREX,       282, "UChar" ) }
}

GetVersionEx := GetVersionEx()

MsgBox % "GetVersionEx function`n"
       . "OSVERSIONINFOEX structure`n`n"
       . "OSVersionInfoSize:`t`t"     GetVersionEx[1]   "`n"
       . "MajorVersion:`t`t"          GetVersionEx[2]   "`n"
       . "MinorVersion:`t`t"          GetVersionEx[3]   "`n"
       . "BuildNumber:`t`t"           GetVersionEx[4]   "`n"
       . "PlatformId:`t`t"            GetVersionEx[5]   "`n"
       . "CSDVersion:`t`t"            GetVersionEx[6]   "`n"
       . "ServicePackMajor:`t`t"      GetVersionEx[7]   "`n"
       . "ServicePackMinor:`t`t"      GetVersionEx[8]   "`n"
       . "SuiteMask:`t`t"             GetVersionEx[9]   "`n"
       . "ProductType:`t`t"           GetVersionEx[10]
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Change GetVersionEx to RtlGetVersion

22 Jan 2015, 04:23

Why is this in Bug Reports?
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Change GetVersionEx to RtlGetVersion

22 Jan 2015, 04:29

Where should I post this if the use of GetVersionEx is not correct?
Isn't it a suggestion for improvements? In Wish List?
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Change GetVersionEx to RtlGetVersion

26 Jan 2015, 09:47

Dear Lexikos, should we move this to Wish List or what?

Again, the GetVersionEx function gives not the correct returns for OS-Version!
So isnt it better to use the RtlGetVersion function for AutoHotkey?

Windows 8.1 Build 9600
Image

Windows 10 Build 9926
Image

Used Script:

Code: Select all

; GLOBAL SETTINGS ===============================================================================================================

#Warn
#NoEnv
#SingleInstance Force

#Include <Class_LV_Colors>

; SCRIPT ========================================================================================================================

RtlGetVersion := RtlGetVersion()
GetVersionEx  := GetVersionEx()

Gui, Margin, 4, 4
Gui, Font, s10, MS Shell Dlg 2
Gui, Add, ListView, xm ym w370 r5 +LV0x1 vLV1, Built-in Variables|Returns
LV_Add("", "A_AhkVersion", A_AhkVersion)
LV_Add("", "A_PtrSize",    A_PtrSize " (" A_PtrSize * 8 "-Bit)")
LV_Add("", "A_OSVersion",  A_OSVersion)
LV_Add("", "A_Is64bitOS",  A_Is64bitOS)
LV_Add("", "A_OSType",     A_OSType)
LV_ModifyCol(1, 140), LV_ModifyCol(2, 220)
Gui, Add, ListView, xm y+5 w370 r3 +LV0x1 vLV2, Extra Functions|Returns
LV_Add("", "ProcessorArchitecture", GetSystemInfo())
LV_Add("", "tba...", "tba...")
LV_ModifyCol(1, 140), LV_ModifyCol(2, 220)
Gui, Add, ListView, xm y+5 w370 r12 +LV0x1 vLV3 hwndHLV, Description|RtlGetVersion()|GetVersionEx()
LV_Add("", "OSVersionInfoSize", RtlGetVersion[1],  GetVersionEx[1])
LV_Add("", "MajorVersion",      RtlGetVersion[2],  GetVersionEx[2])
LV_Add("", "MinorVersion",      RtlGetVersion[3],  GetVersionEx[3])
LV_Add("", "BuildNumber",       RtlGetVersion[4],  GetVersionEx[4])
LV_Add("", "PlatformId",        RtlGetVersion[5],  GetVersionEx[5])
LV_Add("", "CSDVersion",        RtlGetVersion[6],  GetVersionEx[6])
LV_Add("", "ServicePackMajor",  RtlGetVersion[7],  GetVersionEx[7])
LV_Add("", "ServicePackMinor",  RtlGetVersion[8],  GetVersionEx[8])
LV_Add("", "SuiteMask",         RtlGetVersion[9],  GetVersionEx[9])
LV_Add("", "ProductType",       RtlGetVersion[10], GetVersionEx[10])
LV_Add("", "", "", "")
LV_Add("", "GetProductInfo()", GetProductInfo(RtlGetVersion[2], RtlGetVersion[3], RtlGetVersion[7], RtlGetVersion[8])
                             , GetProductInfo(GetVersionEx[2],  GetVersionEx[3],  GetVersionEx[7],  GetVersionEx[8]))
LV_ModifyCol(1, 140), LV_ModifyCol(2, 110), LV_ModifyCol(3, 110)

LV_Colors.Attach(HLV, 1, 0, 0)
loop % LV_GetCount()
{
    LV_GetText(RtlGV, A_Index, 2), LV_GetText(GVE, A_Index, 3)
    if (RtlGV != GVE)
        LV_Colors.Row(HLV, A_Index, 0xF79791, 0x000000)
}

Gui, Show, AutoSize
LV_Colors.OnMessage()
Gui, +LastFound
WinSet, Redraw
return

; FUNCTIONS =====================================================================================================================

GetSystemInfo()
{
    static PRC := "", PA := { 0: "x86", 6: "Intel Itanium-based", 9: "x64", 65535: "Unknown architecture"}
    static SYSINF, size := (A_PtrSize = 8 ? 48 : 36), init := VarSetCapacity(SYSINF, size, 0) && NumPut(size, SYSINF, "Ptr")
    if (A_PtrSize = 4) && (A_Is64bitOS)
        DllCall("kernel32.dll\GetNativeSystemInfo", "Ptr", &SYSINF, "Ptr")
    else
        DllCall("kernel32.dll\GetSystemInfo", "Ptr", &SYSINF, "Ptr")
    PRC := NumGet(SYSINF, 0, "UShort")
    return PRC " [" PA[PRC] "]"
}

RtlGetVersion()
{
    static RTL_OSVIEX, init := VarSetCapacity(RTL_OSVIEX, 284, 0) && NumPut(284, RTL_OSVIEX, "UInt")
    if (DllCall("ntdll.dll\RtlGetVersion", "Ptr", &RTL_OSVIEX) != 0)
        return "Error in RtlGetVersion"
    return { 1 : NumGet(RTL_OSVIEX,   0, "UInt"  ),  2 : NumGet(RTL_OSVIEX,         4, "UInt"  )
           , 3 : NumGet(RTL_OSVIEX,   8, "UInt"  ),  4 : NumGet(RTL_OSVIEX,        12, "UInt"  )
           , 5 : NumGet(RTL_OSVIEX,  16, "UInt"  ),  6 : StrGet(&RTL_OSVIEX + 20, 128, "UTF-16")
           , 7 : NumGet(RTL_OSVIEX, 276, "UShort"),  8 : NumGet(RTL_OSVIEX,       278, "UShort")
           , 9 : NumGet(RTL_OSVIEX, 280, "UShort"), 10 : NumGet(RTL_OSVIEX,       282, "UChar" ) }
}

GetVersionEx()
{
    static OSVEREX, init := VarSetCapacity(OSVEREX, 284, 0) && NumPut(284, OSVEREX, "UInt")
    if !(DllCall("kernel32.dll\GetVersionEx", "Ptr", &OSVEREX))
        return DllCall("kernel32.dll\GetLastError")
    return { 1 : NumGet(OSVEREX,   0, "UInt"  ),  2 : NumGet(OSVEREX,         4, "UInt"  )
           , 3 : NumGet(OSVEREX,   8, "UInt"  ),  4 : NumGet(OSVEREX,        12, "UInt"  )
           , 5 : NumGet(OSVEREX,  16, "UInt"  ),  6 : StrGet(&OSVEREX + 20, 128, "UTF-16")
           , 7 : NumGet(OSVEREX, 276, "UShort"),  8 : NumGet(OSVEREX,       278, "UShort")
           , 9 : NumGet(OSVEREX, 280, "UShort"), 10 : NumGet(OSVEREX,       282, "UChar" ) }
}

GetProductInfo(osmav, osmivs, spmav, spmiv)
{
    static ProductType := ""
    if !(DllCall("Kernel32.dll\GetProductInfo", "UInt", osmav, "UInt", osmivs, "UInt", spmav, "UInt", spmiv, "UInt*", ProductType))
        return DllCall("kernel32.dll\GetLastError")
    return ProductType
}

; EXIT ==========================================================================================================================

GuiClose:
ExitApp
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

Re: Change GetVersionEx to RtlGetVersion

26 Jan 2015, 16:20

What use of GetVersionEx? Your own? GetVersionEx behaves exactly as documented at MSDN. Even if it didn't, AutoHotkey is not responsible for its behaviour, only for the behaviour of A_OSVersion, which you did not mention anywhere in your post. Even if you did, A_OSVersion behaves as documented.
One of the following strings: WIN_7 [requires v1.1+ or AHK_L], WIN_8 [requires v1.1.08+], WIN_8.1 [requires v1.1.15+], WIN_VISTA, WIN_2003, WIN_XP, WIN_2000.
There is no string for Windows 10, except in the latest test build, in which I integrated your unspoken suggestion to use RtlGetVersion instead of GetVersionEx.
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Change GetVersionEx to RtlGetVersion

27 Jan 2015, 03:52

Yes it was for A_OSVersion. The request was for future use (WIN_10 or later)

Windows 10 Build 9926 (latest version)
RtlGetVersion: 10.0.9926 (old 6.4.xxxx)
GetVersionEx: 6.3.9600 => Win 8.1

It seems RtlGetVersion got always the right value for the latest builds.

... but thanks anyway.


More Info:
- Windows NT Releases
- Microsoft Confirms that Windows 10 will also be Version 10 Internally
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: [Done] Change GetVersionEx to RtlGetVersion

09 Mar 2015, 03:35

Thanks for your great work lexikos.
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: [Done] Change GetVersionEx to RtlGetVersion

27 Jul 2015, 09:18

Just for Information:
[GetVersionEx may be altered or unavailable for releases after Windows 8.1. Instead, use the Version Helper APIs]

With the release of Windows 8.1, the behavior of the GetVersionEx API has changed in the value it will return for the operating system version. The value returned by the GetVersionEx function now depends on how the application is manifested.
Applications not manifested for Windows 8.1 or Windows 10 Insider Preview will return the Windows 8 OS version value (6.2). Once an application is manifested for a given operating system version, GetVersionEx will always return the version that the application is manifested for in future releases. To manifest your applications for Windows 8.1 or Windows 10 Insider Preview, refer to Targeting your application for Windows.
ref: MSDN GetVersionEx function
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: Change GetVersionEx to RtlGetVersion

24 Mar 2020, 10:17

jNizM wrote:
26 Jan 2015, 09:47
Again, the GetVersionEx function gives not the correct returns for OS-Version!
So isnt it better to use the RtlGetVersion function for AutoHotkey?

lexikos wrote:
26 Jan 2015, 16:20
There is no string for Windows 10, except in the latest test build, in which I integrated your unspoken suggestion to use RtlGetVersion instead of GetVersionEx.
lexikos wrote: I've also removed the supportedOS entry for Windows 10 TP from the manifest. Instead, A_OSVersion uses RtlGetVersion(), which unlike GetVersionEx(), doesn't appear to be deprecated and doesn't lie on Windows 8.1 or Windows 10. (It may or may not lie on Windows 11 but that's too bad.)

However, both RtlGetVersion() and GetVersionEx() lie if AutoHotkey.exe is set to run in compatibility mode.


i ran into an issue where a user of mine was running my script in Compatibility Mode, and it was messing up my results. a quick google search suggested to use WMI instead which apparently isn't affected by the script running in compatibility mode. to test this, compile this script, and then right click the exe and turn on compatiblity mode for win7 for example, and then run it:

Code: Select all

for obj in ComObjGet("winmgmts:\\.\root\CIMV2").ExecQuery("SELECT * FROM Win32_OperatingSystem")
   WMIversion := obj.Version

msgbox % "A_OSversion = `t" A_OSversion
       . "`nRtlGetVersion = `t" RtlGetVersion()
       . "`nWMI version = `t" WMIversion
return 


RtlGetVersion()
{
    static RTL_OSVIEX
    VarSetCapacity(RTL_OSVIEX, 284, 0)
    NumPut(284, RTL_OSVIEX, "UInt")
    if (DllCall("ntdll.dll\RtlGetVersion", "uInt", &RTL_OSVIEX) != 0)
        return "Error in RtlGetVersion"
    return NumGet(RTL_OSVIEX, 4, "UInt") . "." . NumGet(RTL_OSVIEX, 8, "UInt") . "." . NumGet(RTL_OSVIEX, 12, "UInt")
}

User avatar
SKAN
Posts: 1551
Joined: 29 Sep 2013, 16:58

Re: [Done] Change GetVersionEx to RtlGetVersion

09 Jun 2020, 17:21

@guest3456

WMI call consumes above 100ms?!
I would use the following:

Code: Select all

FileGetVersion, OSV, user32.dll
OSV := Format("{1:}.{2:}.{3:}", StrSplit(OSV,".")*)

MsgBox % OSV
My Scripts and Functions: V1  V2
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: [Done] Change GetVersionEx to RtlGetVersion

09 Jun 2020, 21:53

SKAN wrote:
09 Jun 2020, 17:21
@guest3456

WMI call consumes above 100ms?!
I would use the following:

Code: Select all

FileGetVersion, OSV, user32.dll
OSV := Format("{1:}.{2:}.{3:}", StrSplit(OSV,".")*)

MsgBox % OSV
i dont care much about speed, since i'm only checking it once on script startup

your method is another good way, as long as user32dll version number is reliable

User avatar
SKAN
Posts: 1551
Joined: 29 Sep 2013, 16:58

Re: [Done] Change GetVersionEx to RtlGetVersion

10 Jun 2020, 03:25

guest3456 wrote: as long as user32dll version number is reliable
This MSDN page had originally suggested
To obtain the full version number for the operating system, call the GetFileVersionInfo function on one of the system DLLs, such as Kernel32.dll, then call VerQueryValue to obtain the \\StringFileInfo\\<lang><codepage>\\ProductVersion subblock of the file version information.
Now they have changed.. :(

Souce for the above quote


But... I tried your example in Win7/Win10 and seemingly FileGetVersion is consistent with WMI
My Scripts and Functions: V1  V2

Return to “Bug Reports”

Who is online

Users browsing this forum: No registered users and 32 guests