In an earlier post, I began having a conversation around how shims work. I wanted to supplement some of the discussion of internals with useful information on how specifically to use shims to address problems which you may discover in the software you are trying to get to work on Windows Vista.
In my experience, the most challenging aspect of mitigating application issues using shims is correctly mapping a particular shim to a particular problem. The documentation is a little light, and really reflects the fact that the primary design is for the Windows team to address compatibility issues with commercial software. We're actively working on that, and I delivered an instructor led lab at TechEd in Orlando, and I'll be delivering much of that same content at a breakout at TechEd IT Forum in Barcelona in November. We're also updating some of the documentation in the next revision of the Application Compatibility Toolkit.
Of course, it's really hard to map a particular problem to a particular solution in a way that is prescriptive enough to make it a no-brainer. So, instead, I have been taking the approach of trying to get as much knowledge as possible out there about the shims, because if you know what they do, even though you have to do the thinking, you still can arrive at the answer.
That being said, let's take a look at one of the shims we use the most frequently in the Windows Vista system shim database (sdb): VirtualRegistry. With VirtualRegistry, we can have registry APIs behave differently in a large number of ways. We can redirect keys. We can spoof the existence and/or value of a key. We can expand registry keys for applications that don't understand expandable registry keys.
What I want to go into today is spoofing result codes. Specifically, returning a different result when an application is checking a registry key to determine the version of Windows you are running (as opposed to using the GetVersion/Ex APIs, which you would use an xxxVersionLie shim for). To understand how to configure that, you first need to know how to apply a command line argument.
From within Compatibility Administrator, while creating a new fix, you first specify information about the application, on the next page you specify any operating system modes, and on the next page you specify any compatibility fixes. (Modes are just a collection of fixes - I typically just apply the fixes one by one.)
When you have a fix selected (in this example, VirtualRegistry), you can click on the parameters button, and a new dialog will accept a command line argument, as well as a list of modules to include or exclude. It's the Command line argument that we are interested in for configuring VirtualRegistry.
What are we fixing? Well, there are many available command lines, and we're just going to focus on version lies. Specifically, fixing applications that are reading HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion to determine the current version of Windows, and then reacting badly if they don't find the version they were looking for. The command lines that specify lying about this key are:
This command line pretends that CSDVersion = "Service Pack 5" and CurrentVersion = "4.0" for this key.
This command line pretends that CurrentVersion = "5.0" and ProductName = "Microsoft Windows 2000"
This command line pretends that CurrentVersion = "5.1" and ProductName = "Microsoft Windows XP"
These should get you past most checks for this key.
How would you know that this would be the fix that works? Well, typically when I find a version check issue, there will be a dialog that indicates that it's looking for a particular version. I'll then try with the appropriate xxxVersionLie shim. If that doesn't seem to work, I'll take a look with Process Monitor and see if it's hitting the CurrentVersion registry key. If so, then I know I need to use the VirtualRegistry shim to fix that up.
Note that a version lie shim not working doesn't necessarily mean that VirtualRegistry will. An application could be checking the version in any number of places. It could be pulling any Windows executable it wants and looking at the properties of the binary. Who knows? And it could also be that the version lie doesn't work for a reason (for example, we exclude managed code from the Windows XP version lie). That's why I always follow up with Process Monitor.