Currently, the enableTrueColors function in terminal does the following to
check for Windows 10:
ver.dwOSVersionInfoSize = sizeof(ver).DWORD
let res = getVersionExW(addr ver)
if res == 0:
term.trueColorIsSupported = false
else:
term.trueColorIsSupported = ver.dwMajorVersion > 10 or
(ver.dwMajorVersion == 10 and (ver.dwMinorVersion > 0 or
(ver.dwMinorVersion == 0 and ver.dwBuildNumber >= 10586)))
Run
This is wrong.
As of Windows 8, the GetVersionEx functions have been deprecated and this
function will return the wrong version information as it pulls from the
manifest which isn't updated (read: if upgrading from Windows 8 to 10, it
returns a major version of 6 instead of 10). And lest someone think that the
VerifyVersionInfo functions in the WINAPI will work, just know that they won't;
they are now subject to the same manifest "bug":
[https://msdn.microsoft.com/en-us/library/windows/desktop/dn424972.aspx](https://msdn.microsoft.com/en-us/library/windows/desktop/dn424972.aspx).
The best way to try and get the version of Windows is via the registry. Sadly,
Window 10 introduced new keys that hold the version, so getting it would look
something like this:
proc regOpenKey(root: HANDLE, subKey: WideCString, opts: DWORD, access:
DWORD, key: ptr HANDLE): LONG
{.stdcall, dynlib: "advapi32", importc: "RegOpenKeyExW".}
proc regCloseKey(key: HANDLE): LONG
{.stdcall, dynlib: "advapi32", importc: "RegCloseKey".}
proc regQueryValueEx(key: HANDLE, subKey: WideCString, res: pointer, kind:
pointer, data: pointer, dataSize: ptr DWORD): LONG
{.stdcall, dynlib: "advapi32", importc: "RegQueryValueExW".}
let HKEY_LOCAL_MACHINE = 0x80000002.HANDLE
let KEY_READ = 0x20019.DWORD
let KEY_WOW64_64KEY = 0x0100.DWORD
let VERSION_KEY = newWideCString(r"SOFTWARE\Microsoft\Windows
NT\CurrentVersion".cstring)
proc getWindowsVersion(): tuple[major, minor: Option[int]] =
var major, minor = none[int]()
var key: HANDLE
if regOpenKey(HKEY_LOCAL_MACHINE, VERSION_KEY, 0.DWORD, KEY_READ or
KEY_WOW64_64KEY, addr(key)) == 0:
let majorKey = newWideCString("CurrentMajorVersionNumber")
let minorKey = newWideCString("CurrentMinorVersionNumber")
# output from query values
var value: DWORD = 0
var size: DWORD = sizeof(value).DWORD
# get version key values
if regQueryValueEx(key, majorKey, nil.pointer, nil.pointer,
addr(value), addr(size)) == 0:
major = some(value.int)
if regQueryValueEx(key, minorKey, nil.pointer, nil.pointer,
addr(value), addr(size)) == 0:
minor = some(value.int)
discard regCloseKey(key)
(major, minor)
Run
But, again, this only works on Windows 10. On versions < 10, you need to get
the "CurrentVersion" key (a string), and parse it:
# ... similar to above, opening the key, but the sub key being read is
different
var value = newStringOfCap(100)
var size = 100.DWORD
# get version key values
if regQueryValueEx(key, versionKey, nil.pointer, nil.pointer,
value.cstring, addr(size)) == 0:
echo value
let ver = split(value.strip(), '.')
major = some(ver[0].parseInt())
minor = some(ver[1].parseInt())
Run
I haven't gotten this half to work (it segfaults attempting to read from nil).
I assume I'm loading the value wrong. My time with Nim so far has only been a
couple days, so hopefully it's a quick/easy fix for someone here.
Anyway, I don't know if there are other places in the standard library that are
testing against the Windows version (specifically looking for Windows 10 or
higher), but the check in terminal is wrong and should be changed. And there it
might be beneficial - in general - to just have an os.getVersion():
tuple[major, minor: int] method available that's cross-platform and can be used
for these sorts of things.
As the above relates specifically to the terminal module, there shouldn't
really be a need to test for Windows 10. It should be possible to just set the
ENABLE_VIRTUAL_TERMINAL_PROCESSING mode flag on STDOUT and it either works or
not. If not, it's not supported. If so, then great. Making this change would be
no different (to the end user) than the current behavior. Right now it silently
just doesn't even try to set it and the end result is the same: it's as if the
console didn't support it.