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 Store/immersive apps: obtain product name and version via package functions if possible #10108

Closed
josephsl opened this issue Aug 16, 2019 · 3 comments · Fixed by #10114
Closed
Milestone

Comments

@josephsl
Copy link
Collaborator

@josephsl josephsl commented Aug 16, 2019

Hi,

Based on #7894 work:

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

App module class's product name and version descriptors are used to obtain name and version of the app associated with the app module class. However, there are cases when this does not work, particularly in regards to Windows Store apps (sometimes called "immersive apps"). For these, a container process is used, which causes file utils to say "invalid file version info".

The best known case is Windows 10 Calculator. Although the executable is unique (not wwahost.exe), product name and version cannot be fetched. Another example is Office 365 apps from Microsoft Store that not only presents a high-level version information (because these are converted desktop apps), but also comes with internal versions as seen through Store app package information (for example, 16.0 for desktop apps versus 16051 for Store apps).

Describe the solution you'd like

Detect and retrieve product name and version for immersive apps via package info functions from kernel32.dll (see #7894 for mechanics of this). If the app is not a hosted (immersive) app (such as on Windows 7 and many apps on Windows 8.x and 10), fall back to version info lookup.

Describe alternatives you've considered

None - leave it as is.

Additional context

Mostly useful for app module writers as they can easily detect versions for hosted apps in order to write workarounds. A proof of concept implementation is under active testing via Windows 10 App Essentials add-on.

Thanks.

@josephsl
Copy link
Collaborator Author

@josephsl josephsl commented Aug 17, 2019

Hi,

Another case: Notepad in 20H1 build 18963 which is now a converted desktop app and will be updated via Microsoft Store.

Thanks.

@josephsl
Copy link
Collaborator Author

@josephsl josephsl commented Aug 18, 2019

Hi,

After thinking about it, I am going to attempt the following solution:

  1. Check which Windows release we're dealing with. Not only it makes the code run a bit faster on Windows 7 and avoid exceptions (see below), it allows us to drop support for Windows 7 easily once we progress to a point where this is unavoidable.
  2. Try locating package full name by calling kernel32.dll::GetPackageFullName. If it returns 0, we're dealing with an immersive app, otherwise (error 15700), fall back to file version info method.
  3. If this is an immersive app, parse the package full name structure.

Notes:

  1. In order to fully implement this, the current file version info routine will become an inner function that returns a 2-tuple: product name, product version.
  2. In terms of speed, although calling IsImmersiveProcess first may sound more intuitive, this will cause an exception to be thrown in Windows 7. This means both code paths (one with and one without this function) must be traversed in Windows 7. Therefore checking Windows release ensures NVDA will continue to call file version info routine as before without coming to package name parser.
  3. Continuing from above, the only speed penalty is when dealing with native apps on Windows 8.x and 10. For these, both full package name (immersive process) and file version info (converted desktop or native apps) must be checked. Compounding the issue is that some apps are flagged wrong - File Explorer reports itself as "immersive" when in fact it is a native app, and Office 365 executables from Microsoft Store have their own internal version numbers even though they are not true immersive apps.

Thanks.

josephsl added a commit to josephsl/nvda that referenced this issue Aug 18, 2019
…ve (hosted) apps via kernel32::GetPackageFullName function. Re nvaccess#10108.

On Windows 8 and later, some apps can run inside a container. This is the case for WinRT/UWP apps, some web apps, and converted desktop apps (such as Microsoft Office 365 downloaded from Microsoft Store). For these apps, kernel32.dll::GetPackageFullName returns the 'real' product info such as name and version. Because it'll be returned in a serialized string representation, parse the first two values (name and version).
To accomodate this change, the former method of obtaining product name and version via file version info has been moved to an internal function inside product info setter method. This function will be invoked if:
* This is Windows 7/Server 2008 R2 (no support for containers yet).
* An immersive app that is really a native pap (such as File Explorer).
* Converted desktop apps that will not expose version info via file version info structure (such as Notepad in 20H1 Preview build 18963 and later).
For consistency with immersive app info structure, the modified function will return a 2-tuple that records product name and version in that order.
josephsl added a commit to josephsl/nvda that referenced this issue Sep 8, 2019
…ve (hosted) apps via kernel32::GetPackageFullName function. Re nvaccess#10108.

On Windows 8 and later, some apps can run inside a container. This is the case for WinRT/UWP apps, some web apps, and converted desktop apps (such as Microsoft Office 365 downloaded from Microsoft Store). For these apps, kernel32.dll::GetPackageFullName returns the 'real' product info such as name and version. Because it'll be returned in a serialized string representation, parse the first two values (name and version).
To accomodate this change, the former method of obtaining product name and version via file version info has been moved to an internal function inside product info setter method. This function will be invoked if:
* This is Windows 7/Server 2008 R2 (no support for containers yet).
* An immersive app that is really a native pap (such as File Explorer).
* Converted desktop apps that will not expose version info via file version info structure (such as Notepad in 20H1 Preview build 18963 and later).
For consistency with immersive app info structure, the modified function will return a 2-tuple that records product name and version in that order.
@josephsl
Copy link
Collaborator Author

@josephsl josephsl commented Sep 8, 2019

Hi,

Update: #4259 falls under this category although it is specific to WWAHost - the same approach used in #10114 will also resolve that one too, and is under active testing via Windows 10 App Essentials.

Thanks.

josephsl added a commit to josephsl/nvda that referenced this issue Sep 8, 2019
…getExecutableFileInfo. Re nvaccess#10108.

Reviewed by Mick Curran (NV Access): because of what the internal function does, it is better to give it a more descriptive name than just 'executable file info'.
josephsl added a commit to josephsl/nvda that referenced this issue Sep 10, 2019
…ts own method in base pap module. Re nvaccess#10108.

Suggested by Leonard de Ruijter (Babbage): transform executable file info function from an internal one to a private method in base app module for ease of future maintenance.
michaelDCurran pushed a commit that referenced this issue Sep 10, 2019
…e to obtain product info for immersive (hosted) apps (#10114)

* App modules/product name and version: obtain product info for immersive (hosted) apps via kernel32::GetPackageFullName function. Re #10108.

On Windows 8 and later, some apps can run inside a container. This is the case for WinRT/UWP apps, some web apps, and converted desktop apps (such as Microsoft Office 365 downloaded from Microsoft Store). For these apps, kernel32.dll::GetPackageFullName returns the 'real' product info such as name and version. Because it'll be returned in a serialized string representation, parse the first two values (name and version).
To accomodate this change, the former method of obtaining product name and version via file version info has been moved to an internal function inside product info setter method. This function will be invoked if:
* This is Windows 7/Server 2008 R2 (no support for containers yet).
* An immersive app that is really a native pap (such as File Explorer).
* Converted desktop apps that will not expose version info via file version info structure (such as Notepad in 20H1 Preview build 18963 and later).
For consistency with immersive app info structure, the modified function will return a 2-tuple that records product name and version in that order.

* App module handler/product name and version: _executableFileInfo -> _getExecutableFileInfo. Re #10108.

Reviewed by Mick Curran (NV Access): because of what the internal function does, it is better to give it a more descriptive name than just 'executable file info'.

* App module handler/product name and version for immersive apps: typo fix.

* Product name and version: separate executable file info function to its own method in base pap module. Re #10108.

Suggested by Leonard de Ruijter (Babbage): transform executable file info function from an internal one to a private method in base app module for ease of future maintenance.
@nvaccessAuto nvaccessAuto added this to the 2019.3 milestone Sep 10, 2019
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