📜 ⬆️ ⬇️

Why a Win32 application manifest?

Recently, a question was asked on the board in the Programming section: “Why does a Win32 application need a manifest? What does it affect? ​​” The first thing that immediately occurs to most programmers is the themes. But in fact, in modern Windows, the manifesto is needed not only for this. I thought and wrote five key aspects that are affected by the manifesto or its absence. After that, several people immediately asked to arrange this post in the form of a more detailed article.

To begin with, I propose to recall how manifestos appeared in Windows and how they developed.

Manifest history

In ancient times, hell reigned in the world of Win95 / 98, more precisely the DLL hell . It originated from the fact that Windows was conceived as an ideal system. All applications in it should always have been written using the most recent versions of the system libraries. And the different versions of the libraries themselves were supposed to be interchangeable. Reality quickly proved to everyone that for a popular OSes it is an impossible dream, that is how hell appeared. Every second application during installation overwrites the system libraries with the versions it needs. As a result, after installing the application X, the previously installed application Y started to fail. And after reinstalling the application Y, the application X started to fail. In general, users had fun.

To solve this problem, Side-by-side Assembly (SxS) technology appeared in Windows XP. Its essence was that the application could clearly indicate with which version of the library it wants to work. This information could be specified either in a special .manifest file or in the application resources in the Manifest section. In the XP itself, on the basis of a new technology, one of the most noticeable new features of the system was implemented - themes.
')
Typical manifesto:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="CompanyName.ProductName.YourApplication" type="win32" /> <description>Your application description here.</description> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*" /> </dependentAssembly> </dependency> </assembly> 


SxS was all good except one - it was terribly inconvenient for a programmer. In 99% of cases, the manifesto was used only to include those very themes, and nothing more. The developers of Windows, it became clear that we need a new, easier to use way to specify the supported versions of the system libraries. Then they came up with a simple rule: within the same version of the system, the interface and the behavior of these libraries does not change. It was necessary only to somehow learn how to determine which version of them is required by a particular application. So in Windows 7, the Compatibility section appeared in the manifest, where you can specify with which OS versions the application was tested.
Also in the manifesto, starting with Windows Vista, a few more sections appeared, about all of them below.

Manifest functions

  1. Activating themes ( Visual Styles )
    This technology appeared in XP and is completely based on SxS. It works simply: you request the sixth version of ComCtl32.dll system, and - voila - all standard controls are drawn according to the theme activated in the system. If you do not mention ComCtl32.dll in the manifest, or the manifest will be completely absent from the application, then the system will by default load ComCtl32.dll fifth version, which draws controls in the style of Win95. In addition to supporting themes, the sixth version of ComCtl32.dll contains some functionality that is not present in the fifth version. Therefore, if you turn off the themes, some applications will work and look differently than their authors intended.

    On the right is the same application without the manifest:



  2. Interaction with UAC has several aspects :
    • The requestedExecutionLevel.level key allows you to specify the level of user rights required by the application. For example, if you specify requireAdministrator, then the application will be granted administrator rights (if the user allows).

      Request user permission:



    • If the entire section on interaction with UAC is missing in the manifest, file system and registry virtualization will be applied to the application. If such an application tries to write something to protected folders like “Program files”, it will be redirected to the folder “% userprofile% \ AppData \ Local \ VirtualStore \ Program files". Similarly, attempts to write to the registry key HKEY_LOCAL_MACHINE will be redirected to "HKEY_CURRENT_USER \ Software \ Classes \ VirtualStore \ MACHINE. ”Naturally, the changes made in this way will be visible only to applications running in virtualization mode.

      File system virtualization in practice:



    • The requestedExecutionLevel.uiAccess key allows applications running without administrator rights to interact with windows of applications running as administrator. This may be required on-screen keyboards, applications such as AutoIt, on-screen readers, test and debug tools. For this key to work, the application must be signed with a Microsoft Authenticode certificate .

  3. DPI scaling control
    Since ancient times, Windows has an interface scaling mechanism depending on the monitor's DPI (it says that everything started in XP, but it seems to me that before ). At that time, this setting was set only manually, probably due to the lack of EDID . It did not enjoy popularity, perhaps because it was hidden far away, and perhaps because there were very few very high-resolution monitors. In addition, much of the work needed to support scaling was left to the applications themselves and their authors. And programmers, as you know, people are very lazy, so a lot of software for Windows was written under the assumption that DPI is always equal to the standard value 96. It is often the case that the application used libraries supporting non-standard DPI, while the code of the application itself is not supported. This led to the appearance of terrible artifacts in the application interface, it cost the user to set the DPI, for example, to 120 (scaling 125%):



    The developers of Vista did not tolerate such a disgrace, and laid the ability in the DWM to perform scaling independently, and lie to applications that the DPI is still 96. Moreover, the system settings depending on it, the monitor resolution and even the mouse position are also recalculated. Unfortunately, the developers of Vista were not wizards, so DWM scaling using simple image stretching algorithms. And if the application interface needs to be increased, then the image is blurred. Imagine what it would be like if Photoshop developers couldn’t turn it off. Nobody wanted such riots on the ship, so the opportunity appeared to indicate in the manifest that your application still knows how to scale its interface properly, and it does not need the help of DWM. The dpiAware parameter is responsible for this . Here, however, it should be noted that, by default, DWM scaling is enabled with an increase of 150% and higher. Apparently, Microsoft considered that when scaling 125%, the artifacts as in the screenshot above are quite tolerable.

    On the left, DWM scaling, and on the right, the application itself:



    In Windows 8.1, it became possible to specify a different scale for different monitors, if several are connected at once. Accordingly, the dpiAware key has a new “True / PM” value. It means that the application can dynamically change the scale of its interface when transferring windows from one monitor to another.

  4. Compatibility declaring
    It works very simple: the programmer is testing his application in a certain version of Windows, and if everything works as it should, it adds the GUID of this version to the manifest.

    Example:

     <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> <application> <!--This Id value indicates the application supports Windows Vista functionality --> <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> <!--This Id value indicates the application supports Windows 7 functionality--> <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> <!--This Id value indicates the application supports Windows 8 functionality--> <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> <!--This Id value indicates the application supports Windows 8.1 functionality--> <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> </application> </compatibility> 


    The most interesting question is: “What do these GUIDs affect?” So far, the list of differences in the behavior of system libraries is small. Most interesting is the mention of RPC optimization. It turns out that applications declaring compatibility with the seven will work faster.
    In the future, this section of the manifesto will certainly play a greater role than it is now. Indeed, in Windows is full of different hacks designed to ensure compatibility. And now there is an opportunity to protect normal applications from them.

    If GUIDs are completely absent in the manifest, then the rules are applied to the application as compatible with Vista:



  5. Control of other functions
    Above, I described only those functions that I had to deal with personally. But this is not all that can be controlled from the manifest: msdn.microsoft.com/en-us/library/aa374191.aspx Unfortunately, the documentation for most of the other functions is not available. Perhaps it will be published later, as happened with Magnification API in due time.


Epilogue

On this, I think I’ll finish reviewing the possibilities of Win32 application manifests. If you have any corrections or additions, please state them in the comments.

Source: https://habr.com/ru/post/230505/


All Articles