App modules: add additional app properties such as app path, immersive process, and app architecture (#8644)
* App modules: add appPath property, clarify that app module packages are also supported. Re #7894.
Add appModuleHandler.AppModule.appPath property used to obtain the full path for the executable (e.g. C:\Windows\explorer.exe).
Also, in app module docstring, clarify that app module packages (appmodname/__init__.py) are also supported.
* App modules: add isWindowsStoreApp property. Re #7894.
AppModule.isWindowsStoreApp will call user32.dll::IsImmersiveProcess to determine if the app is hosted inside a Windows RT container. This is useful for dealing with universla apps on Windows 10.
* App modules: add appArchitecture property. Re #7894.
appModule.appArchitecture will return the architecture for which the app is written. It can be x86 (32-bit app on 32-bit Windows), AMD64 (x64 app), or ARM64 (64-bit ARM app). This is accomplished by use of kernel32.dll's IsWow64Process2 (available on Windows 10 build 10586 and later).
* App module properties: address review comments. Re #7894.
appModule.isWindowsStoreApp: check if it is below Windows 8, also fixed tuple syntax.
appModule.appArchitecture: variable renames to make it clear.
* App modules/app architecture: use much improved is64bitProcess method. re #7894.
Thanks to work on ARM64 detection in appModule.is64BitProcess: use kernel32::isWow64Process2 directly and obtain either AMD64 or ARM64, falling back to AMD64 if that Windows API function isn't present (the function is present in Windows 10 Version 1511 (build 10586) and later).
* App architecture: rewrite the whole thing in order to support detection of 32-bit ARM apps. Re #7894.
Windows 10 Version 1903 includes foundatoins to support 32-bit ARM apps. Because this means two 32-bit architectures must be handled, rewrite app architecture method to:
1. Record architecture to arch names inside a map.
2. Call kernel32::IsWow64Process2 first and obtain arch name fromthe arch values map.
3. If IsWow64process2 fails for some reason (Windows 7 through 10 Version 1507), return appropriate architecture name based on 64-bit process status.
* App architecture: mention ARM32. re #7894.
* Lint fixes.
Fixes include inline comments and spaces around dictionary operator.
* App properties: use a dedicated (private) method for fetching package info for Microsoft Store apps. Re #7894.
User32.dll::IsImmersiveProcess won't quite cut it for Store apps:
* File Explorer is seen as an immersive app but it is not really a Store application.
* Converted desktop apps are seen as not immersive but they are Store apps.
The more accurate way to determine this information is looking for app package info, which can be done by calling kernel32.dll::GetPackageFullName. This returns a string representation of app name, version, architecture, language, and app ID (the first two are used in #4259). Every Store app comes with app model XML file that provides data for this structure (Store version of NVDA is no exception). Thus use this method, which is now part of a private function in the base app module so not only product name and version setter can use it, but also Store app property can call this method.
* Product name and version for Store apps: use the dedicated package info function. Re #7894.
Use the dedicated package info function for obtaining product name and version:
* If the package info is a string, info will be parsed.
* If it is None, executable file info will be fetched.
* Windows Store property: use package info method to determine if the underlying process is a Windows Store app. Re #7894.
User32.dll::IsImmersiveProcess won't work all the way, but package info fetching will (on Windows 8 and later). Therefore use the package info method to determine if a given process is a Windows Store app.
* Windows Store app property: use platform version tuple from sys.getwindowsversion(). Re #7894.
* App modules/immersive package info: use length instead of unused buffer to obtain actual package info length (addressing review action). Re #7894.