Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows 10 versions: use Windows Registry to obtain release Id/display name #12509

Closed
josephsl opened this issue Jun 3, 2021 · 1 comment · Fixed by #12544
Closed

Windows 10 versions: use Windows Registry to obtain release Id/display name #12509

josephsl opened this issue Jun 3, 2021 · 1 comment · Fixed by #12544
Milestone

Comments

@josephsl
Copy link
Collaborator

josephsl commented Jun 3, 2021

Hi,

I'd be happy to provide a pull request regarding this - after all, what I'm proposing was already implemented as part of an add-on.

Introduction

As part of Windows as a Service (WaaS) model, Microsoft releases new releases of Windows every six months or so. As of June 2021, the latest release is 21H1 (May 2021 Update).

Until Windows 10 RTM (Version 1507/build 10240), one way to determine Windows releases was build number (Windows 10 uses Windows NT version 10.0 internally). With Version 1511 (November Update released in 2015), Microsoft added "ReleaseId" (aka YYMM) to identify releases, with this info displayed as part of About Windows (WinVer) dialog. The release Id can be found under the Windows Registry path HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion.

Then in 2020, Microsoft made two related changes: the codename for a feature update became a public name for a semi-annual update, the best known being Version 20H2 (October 2020 Update). To reflect this change, a new key named "DisplayName" was added to the mentioned Registry path, which is used by WinVer instead of ReleaseId when displaying version information. If you recall, a few months ago we had a discussion about Windows 10 versions to be used (2009 versus 20H2) as part of #11795 (see that issue for details), and the new Registry key is the reason why.

The picture became complicated in 2021. As of June 2021, Microsoft is working on at least four code bases: Vibranium (2004/20H2/21H1), Iron Server 2022 and initial (and now canceled) version of Windows 10 X), Cobalt (a likely 21H2 build), and Nickel (next year and first bits may show up to dev channel Windows Insiders in a few weeks). Consequently, four build ranges were spotted by Windows Insiders: 1904x for Vibranium, 203xx for Iron, 21xxx for Cobalt, 22xxx for Nickel. As a result, it becomes harder to keep track of which release is which in the current Windows 10 version implementation, which is described below.

Is your feature request related to a problem? Please describe.

Currently winversion module includes a record of which Windows 10 release is tied to a specific build. This is used by winVersion.WinVersion class to display Windows 10 release information.

As described above, with multiple code bases being developed, it becomes harder to associate a feature update with a specific build number. This will become an issue when recognizing 21H2 later this year, as one needs to use a tuple or a similar structure to record multiple builds for a given release and look up the correct index based on product type.

Describe the solution you'd like

Retrieve Windows 10 version information (Release Id/display name) directly from Windows Registry, and to use an updated releases to builds map as a fallback if Registry access is denied. In short, the following solution (source: Resource Monitor add-on which I am currently maintaining) is proposed:

  1. For Windows 10 build 10240, return "1507".
  2. Look for "DisplayName" key from the Registry path noted above.
  3. If it fails, look up "ReleaseId" key.
  4. If Registry access is completely denied, use the refined Windows 10 releases to builds map as a fallback. I expect it won't be necessary unless Registry access is denied to user programs such as NVDA.

This solution is applicable to Windows Server releases as well i.e. Server 2019 will say "Windows 10 1809" when winVersion.GetWinVer() is called.

The biggest advantage is that there is no need to add entries to releases to builds map when making NVDA recognize new Windows 10/Server releases - all the developer needs to do is add a WIN10_* constant (for Server 2022, if it turns out the build number is different then client releases, I think it would be better to call it WIN10_VER_SERVER, or perhaps WINSERVER_2022) since the needed info comes from Windows Registry. Plus, for Insiders on dev channel, display name is "Dev", making it easier for developers to determine which Windows 10 release is in use by simply looking for "Windows 10 whatever".

The biggest issue is prerelease builds that are being tested by beta and release preview Insiders. Prior to general availability, Microsoft assigns a specific build as the feature update build, and this will be noticed by beta and release preview Insiders ahead of time by months to weeks, respectively. Therefore, to make sure people can add the correct Windows version information/constants, I propose that people should wait until a feature update is released to release preview Insiders before sending a pull request to update winVersion module (this was the route I took to add 21H1 information a few weeks ago).

Perhaps an unlikely issue is Registry access denial. I doubt this will be the case, but just in case this happens, I think existing releases to builds map should be used as a fallback to some degree.

Describe alternatives you've considered

Leave it as is and refine releases to builds map to account for a given feature release using different build numbers based on product type. One approach (although folks will need to wait until 2022.1 cycle) is change releases to builds map so that it records builds:releases instead of releases:builds.

Additional context

For a practical implementation, see:
https://github.com/josephsl/resourceMonitor

Don't worry about Windows Server LTS bits as it is not applicable to this issue. Also, if anyone would like to base a PR on bits of resource Monitor, feel free to do so.

Thanks.

@josephsl
Copy link
Collaborator Author

Hi,

For now releases to builds map will be left as is. The upcoming PR will add Registry checks as part of Windows version announcement method unless there is a need to create a separate function just for Windows 10 releases.

Thanks.

josephsl added a commit to josephsl/nvda that referenced this issue Jun 12, 2021
…ccess#12509.

From Widows 10 Version 1511 (November Update/build 10586), WinVer (About Windows) dialog uses Windows Registry to obtain version information (build 10240 wsa retroactively named '1507' then). Initially 'ReleaseId' key was used, but since 20H2, 'DisplayVersion' is used (ReleaseId for 20H2 is 2009).
The Registry method is needed to support multiple Windows 10 builds with same display version. Currently release Id's to builds map contains one to one mapping between versions and builds, whereas in 21H2 development cycle, up to three builds may represent this release. Therefore use Registry method to detect all public Windows 10 releases.
josephsl added a commit to josephsl/nvda that referenced this issue Jun 14, 2021
…ager. re nvaccess#12509.

Advised by Leonard de Ruijter: use context manager (with) associated with Windows Registry HKEY handles (of the form 'with winreg.openKey(HKEY, path) as something').
josephsl added a commit to josephsl/nvda that referenced this issue Jun 15, 2021
… Re nvaccess#12509.

Windows 10 releases to builds map records feature update release names to builds (e.g. '1903': 18362). With the Windows Registry method in place, coupled with several build branches for Version 21H2, it makes sense to remove an unused dictionary.
josephsl added a commit to josephsl/nvda that referenced this issue Jun 22, 2021
…ess#12509.

Advice from Reef Turner (NV Access): define a 'release name' atribute to set the public facing name for a Windows release such as 'Windows 7' for 6.1.7600. This is useful for Widows 10 due to many major updates released since July 2015.
josephsl added a commit to josephsl/nvda that referenced this issue Jun 22, 2021
…#12509.

If release name is defined, return this as the version name e.g. if 'releaseName' is 'Windows 10 1511' for build 10586, return 'Windows 10 1511' instead of using release names to builds map and/or Windows Registry. Note that the implied 'else' block is not indented.
josephsl added a commit to josephsl/nvda that referenced this issue Jun 22, 2021
…ess#12509.

Although release name texts are useful for Windows 10, apply this change to all constants (Windows 7 and 8.x also).
josephsl added a commit to josephsl/nvda that referenced this issue Jun 22, 2021
Note that on server systems, unless otherwise noted, client relesae names are returned. The first such exception is likely the erver counterpart of Windows 10 21H2 (Server 2022) which may have a different build than client releases.
josephsl added a commit to josephsl/nvda that referenced this issue Jun 22, 2021
Review by Reef Turner (NV Access): in winVersion.getWinVer() function, instead of opening Windows Registry to obtain Windows 10 each time the function is called, have the version string handy from the beginning. Note that Release Id and display version are not found on Windows 10 1507 (build 1024) or earlier.
josephsl added a commit to josephsl/nvda that referenced this issue Jun 22, 2021
Advised by Reef Turner (NV Access): define a unit test to compare release names, specifically to simulate winVersion.getWinVer but with a constant. Because repr(winVersion.getWinVer()) includes release name, major.minor.build, and product type in one go, use asertIn to test the expected string (in this case, 'Windows 10 1607' for Server 2016).
josephsl added a commit to josephsl/nvda that referenced this issue Jun 23, 2021
…ccess#12509.

From Widows 10 Version 1511 (November Update/build 10586), WinVer (About Windows) dialog uses Windows Registry to obtain version information (build 10240 wsa retroactively named '1507' then). Initially 'ReleaseId' key was used, but since 20H2, 'DisplayVersion' is used (ReleaseId for 20H2 is 2009).
The Registry method is needed to support multiple Windows 10 builds with same display version. Currently release Id's to builds map contains one to one mapping between versions and builds, whereas in 21H2 development cycle, up to three builds may represent this release. Therefore use Registry method to detect all public Windows 10 releases.
josephsl added a commit to josephsl/nvda that referenced this issue Jun 23, 2021
…ager. re nvaccess#12509.

Advised by Leonard de Ruijter: use context manager (with) associated with Windows Registry HKEY handles (of the form 'with winreg.openKey(HKEY, path) as something').
josephsl added a commit to josephsl/nvda that referenced this issue Jun 23, 2021
… Re nvaccess#12509.

Windows 10 releases to builds map records feature update release names to builds (e.g. '1903': 18362). With the Windows Registry method in place, coupled with several build branches for Version 21H2, it makes sense to remove an unused dictionary.
josephsl added a commit to josephsl/nvda that referenced this issue Jun 23, 2021
…ess#12509.

Advice from Reef Turner (NV Access): define a 'release name' atribute to set the public facing name for a Windows release such as 'Windows 7' for 6.1.7600. This is useful for Widows 10 due to many major updates released since July 2015.
josephsl added a commit to josephsl/nvda that referenced this issue Jun 23, 2021
…#12509.

If release name is defined, return this as the version name e.g. if 'releaseName' is 'Windows 10 1511' for build 10586, return 'Windows 10 1511' instead of using release names to builds map and/or Windows Registry. Note that the implied 'else' block is not indented.
josephsl added a commit to josephsl/nvda that referenced this issue Jun 23, 2021
…ess#12509.

Although release name texts are useful for Windows 10, apply this change to all constants (Windows 7 and 8.x also).
josephsl added a commit to josephsl/nvda that referenced this issue Jun 23, 2021
Note that on server systems, unless otherwise noted, client relesae names are returned. The first such exception is likely the erver counterpart of Windows 10 21H2 (Server 2022) which may have a different build than client releases.
josephsl added a commit to josephsl/nvda that referenced this issue Jun 23, 2021
Review by Reef Turner (NV Access): in winVersion.getWinVer() function, instead of opening Windows Registry to obtain Windows 10 each time the function is called, have the version string handy from the beginning. Note that Release Id and display version are not found on Windows 10 1507 (build 1024) or earlier.
josephsl added a commit to josephsl/nvda that referenced this issue Jun 23, 2021
Advised by Reef Turner (NV Access): define a unit test to compare release names, specifically to simulate winVersion.getWinVer but with a constant. Because repr(winVersion.getWinVer()) includes release name, major.minor.build, and product type in one go, use asertIn to test the expected string (in this case, 'Windows 10 1607' for Server 2016).
josephsl added a commit to josephsl/nvda that referenced this issue Jun 23, 2021
josephsl added a commit to josephsl/nvda that referenced this issue Jun 23, 2021
…ved in 2022.1. Re nvaccess#12509.

Advised by NV Access: mark no longer used releases to builds map as deprecated and to be removed in 2022.1 as Windows 10 release names are obtained from Windows Registry.
josephsl added a commit to josephsl/nvda that referenced this issue Jun 23, 2021
… to release names' map. Re nvaccess#12509.

Note from Reef Turner (NV access): flip the now deprecated 'release names to builds' map by defining a new map that records builds to releases. This prepares NVDA to support Windows releases with multiple builds under the same release name, as well as defining the release name for build 10240 (Windows 10 1507) through this mapping instead of hard-coding it in functions.
josephsl added a commit to josephsl/nvda that referenced this issue Jun 23, 2021
…from WinVersion class to a new module-level function. Re nvaccess#12509.

Addressing a comment from NV Access: use a dedicated function to return Windows release names given its major, minor, and build components. Therefore transfer the bulk of WinVersion classes's Windows release name fetcher to the module and call it from both WinVersion class and getWinVer() function. The string returned will be used as 'releaseName' component of WinVersion class constructor.
josephsl added a commit to josephsl/nvda that referenced this issue Jun 23, 2021
…ethod to repr method. Re nvaccess#12509.

Transfer the private Windows release names method in WinVersion class to the repr method as a dedicated module-level function will return Windows release names. In case runtime error is raised, use the name 'Windows release unknown' to make it consistent with winVersion.getWinVer function.
josephsl added a commit to josephsl/nvda that referenced this issue Jun 23, 2021
…ieval functionality. re nvaccess#12509.

Add the following tests:
* Obtain Windows release name from known Windows release constants defined in winVersion module
* Make sure a runtime error is raised when the new Windows release name function defined in winVersion module receives unknown major.minor/build values
* Windows release name as defined in Windows Registry is returned on any Windows 10 releases not defined in releases to builds map, simulating Windows Insider Preview builds
Also, rename Windows release name test to reflect what it actually tests.
josephsl added a commit to josephsl/nvda that referenced this issue Jun 24, 2021
…ked for deprecation (will not be present in the module starting NVDA 2022.1). Re nvaccess#12509.

Advised by Reef Turner (Nv Access): do not add the deprecated Windows 10 releases to builds map in NVDA 2022.1 or later.
josephsl added a commit to josephsl/nvda that referenced this issue Jun 28, 2021
…dows Registry. Re nvaccess#12509.


Suggested by Reef Turner (NV aCcess): reduce LRU cache overhead by specifying that Registry value should be cached only once.

Co-authored-by: Reef Turner <feerrenrut@users.noreply.github.com>
josephsl added a commit to josephsl/nvda that referenced this issue Jun 28, 2021
…try when obtaining current build only. Re nvaccess#12509.

Suggested by Reef Turner (NV Access): ask Windows Registry when fetching current Windows version only.
josephsl added a commit to josephsl/nvda that referenced this issue Jun 28, 2021
…e determined. re nvaccess#12509.

On Windows 10 (and later), the following pths will be used to retrieve relase name (in this order):
1. Existing build: whatever the release name is.
2. Current version: Windows Registry. This also covers Windows Insider Preview builds that will eventually become stable (retail) builds.
If none of these work, just say 'Windows 10 unknown'. This also resolves Flake8 F821 (undefined variable name).
josephsl added a commit to josephsl/nvda that referenced this issue Jun 28, 2021
josephsl added a commit to josephsl/nvda that referenced this issue Jun 28, 2021
…ting on public uilds. Re nvaccess#12509.

Windows Insider Preview builds will say 'Windows 10 Dev', but as unit tests are tested in public builds (unless someone tests in sindier builds), test to see if 'unknown' is returned. Checkig this string is fine because build 21390 is an Insider Preview build that were succeeded by newer builds.
feerrenrut pushed a commit that referenced this issue Jul 8, 2021
…12544)

Closes #12509

# Summary of the issue:
Currently a static Windows 10 release names to builds map is used to record Windows 10 builds to feature updates (releases). Until 21H1 there was a one-to-one correspondence between releases and builds, but it appears Version 21H2 will be represented by multiple builds:

- Windows 10: 19044
- Server 2022: 20348
- Windows 11: build 22000

Therefore this breaks the existing static map of WIN10_RELEASE_NAME_TO_BUILDS.
"21H2" can not be the key for 19044, 20348, and 22000.

# Description of how this pull request fixes the issue:
- Replace WIN10_RELEASE_NAME_TO_BUILDS with the inverse mapping (_BUILDS_TO_RELEASE_NAMES), which is how it is used anyway.
- Allow class WinVersion to be constructed with an optional releaseName, if it is missing look up the name in static map.
- For the "currently running" version of Windows, try to look up the name via the registry if possible. Fall back to the static map.

Note:
- Since Version 1511, Windows Registry holds release name which corresponds to builds (e.g. 1511 = 10586, 20H2 = 19042), housed inside a "Release Id" key.
- Starting with Version 20H2, a separate "DisplayVersion" key is used to announce public release name.
- In Windows Insider Preview builds, dev channel has display version of "Dev", making it even easier to determine what kind of build a user is running.
- This tradition continues with Windows 11 and Server 2022, with Registry recording "21H2", which makes sense given their projected release period.
@nvaccessAuto nvaccessAuto modified the milestone: 2021.2 Jul 8, 2021
seanbudd pushed a commit that referenced this issue Jan 13, 2022
Removes deprecated code from #12509

Summary of the issue:
As of #12544, Windows 10 releases to builds map was deprecated, with what's new document declaring that this map will be gone in 2022.1. This pull request accomplishes exactly that.

Description of how this pull request fixes the issue:
Removes deprecated Windows 10 releases to builds as Windows Registry is used to obtain Windows 10/11 release information.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants