3

The latest release of Windows 10 (currently Insider Preview) is badged as:

Version 1511 (OS Build 10586.3)

when looking in "About Windows" ( Start > Run > winver )

Using an appropriately manifested console application, the Windows version returned from System.Environment.OSVersion.Version is 10.0.10586.0, which contains neither the "1511" or ".3" components of the version reported by winver.

There do appear to be strings in the registry under HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion such as ReleaseId which would provide this information, however this would be relying on an implementation detail rather than an API contract.

In short, is there a (documented) API that provides the Windows 10 version as shown by winver and/or Help > About in Windows components such as Notepad which is callable from a .net application?

Rob
  • 45,296
  • 24
  • 122
  • 150
  • "Using an appropriately manifested console application" Maybe this won't be the right manifest for 1511? There may be an additional supportedOS GUID coming up. – Sören Kuklau Nov 11 '15 at 19:41
  • In general you aren't supposed to care. It's "Windows 10" as far as end-users are concerned, and ``10.0.10586.0`` as far as telemetry/support data. – Chuck Walbourn Nov 11 '15 at 23:47

2 Answers2

8

Here is some circumstantial evidence that there is no API to get the "1511" string (other than reading it off the "ReleaseId" registry value). It's not an absolute proof, and it may not be the answer you sought, but that's what I have at this point.

Logging a "winver" run with sysinternals' ProcMon shows that the registry key is indeed queried, as @Sören Kuklau indicated already.

winver.exe RegQueryValue HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ReleaseID SUCCESS Type: REG_SZ, Length: 10, Data: 1511

The call stack at the point of that RegQueryValueExW for "ReleaseID" is the following, as reported by ProcMon.

 0 ntoskrnl.exe   NtQueryInformationFile + 0x3d50
 1 ntoskrnl.exe   NtOpenThreadTokenEx + 0x258c
 2 ntoskrnl.exe   setjmpex + 0x3963
 3 ntdll.dll      ZwQueryValueKey + 0x14
 4 KernelBase.dll MapPredefinedHandleInternal + 0x729
 5 KernelBase.dll RegQueryValueExW + 0xed
 6 SHCore.dll     SHQueryValueExW + 0xdd
 7 SHCore.dll     SHQueryValueExW + 0x32
 8 shell32.dll    Ordinal897 + 0x86f
 9 shell32.dll    Ordinal897 + 0xb8b
10 shell32.dll    Ordinal897 + 0x304
11 user32.dll     IsDialogMessageW + 0x76e
12 user32.dll     IsDialogMessageW + 0x941
13 user32.dll     IsDialogMessageW + 0x866
14 user32.dll     DispatchMessageW + 0x689
15 user32.dll     SendMessageW + 0x395
16 user32.dll     SetWindowLongPtrA + 0x979
17 user32.dll     DialogBoxIndirectParamAorW + 0x18c
18 user32.dll     DialogBoxIndirectParamAorW + 0x52
19 user32.dll     DialogBoxParamW + 0x85
20 shell32.dll    SHELL32_PifMgr_OpenProperties + 0x223d
21 shell32.dll    ShellAboutW + 0x72
22 winver.exe     winver.exe + 0x11d3
23 winver.exe     winver.exe + 0x1516
24 kernel32.dll   BaseThreadInitThunk + 0x22
25 ntdll.dll      RtlUserThreadStart + 0x34

So, winver.exe calls ShellAboutW from shell32.dll, which opens the dialog and fills-in the data. While doing this, it reads the "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ReleaseID" registry value, which returns "1511".

The value name "ReleaseID" is indeed found as a hardcoded string in shell32.dll. Moreover, the only other System32 DLLs that carry a "ReleaseId" string are SettingsHandlers_nt.dll and WSShared.dll - but neither is loaded by winver.exe, and both have different capitalizations for "ReleaseID" (lowercase "d" at the end, for one thing). This strongly hints that:
(a) the string passed into RegQueryValueExW is the one hardcoded in shell32.dll;
(b) other MS code has the similar string hardcoded, presumably because there is no API to get it.

This still leaves open the possiblity that the same "1511" information (or at least the "ReleaseID" value name) could conceivably be exposed by shell32.dll through some other API. It is possible, for example, that one of the "Ordinal897" calls at offsets 8, 9, 10 in the call stack may in fact be a function like "GetWin10RelID(LPTSTR lpRellD, int nMaxChars);" and it is also possible that it might get exported by name instead of ordinal and be documented in future SDKs. However, for the time being those are anonymous functions exported by ordinal, with no documentation, and no guarantee that they'll even keep the same ordinal next time shell32.dll is updated.

dxiv
  • 16,984
  • 2
  • 27
  • 49
  • 2
    releaseid no longer works for 21h1, instead displayversion is now used. which doesnt exist for older versions – az1d May 28 '21 at 07:21
  • @az1d Good to know, thanks. You could post that as an answer. – dxiv May 28 '21 at 07:31
6

FWIW, Process Monitor suggests that winver does simply query ReleaseId. So maybe that is indeed all there is to the "Version 1511" branding.

23:59:30,6022870    winver.exe  7004    RegQueryValue   HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ReleaseID SUCCESS Type: REG_SZ, Length: 10, Data: 1511

Changing the registry value to something random is immediately reflected when launching winver again. Removing the value makes winver show an empty string.

So, while not nicely wrapped in an API and possibly unsupported, this seems to do the trick for now:

using (var hklmKey = Microsoft.Win32.Registry.LocalMachine)
using (var subKey = hklmKey.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion"))
{
     if (subKey != null)
     {
         string release = subKey.GetValue("ReleaseId") as string;

         if (release != null)
             retVal += " Version " + release;
     }
}
Sören Kuklau
  • 19,454
  • 7
  • 52
  • 86
  • Thanks for taking the time to grok what's going on with Process Manager (and thus validating my theory about where the data may be coming from). I'm not going to accept this though as my question is specific in requesting an API for this, it is valuable information though =) Running sysinternals "strings" across winver.exe and it's MUI file find no references to "ReleaseId" so it looks like it may be calling an API after all... – Rob Nov 12 '15 at 08:13
  • 1
    releaseid no longer works for 21h1, instead displayversion is now used. which doesn't exist for older versions – az1d May 28 '21 at 07:22
  • 1
    Damn. Why do they keep changing that? (I don't have 21H1 yet. However, on 20H2, DisplayVersion does already exist. Unclear when that was introduced.) – Sören Kuklau May 28 '21 at 11:45