Are You F**king Kidding Me !? (OR: Surprising error in ATL 8.0 Runtime Manifest)

Part of my company’s product involves using Windows PE, the bootable-from-a-CD Windows environment Microsoft licenses to companies for products like Symantec Ghost. It’s basically equivalent to the Bart PE project, but it’s officially supported by MS.

The environment you get when running under Windows PE is very limited, and changing that limited environment is tricky. In my case, I need to run some code I wrote in Visual C++ 2005, which is dependent upon the Visual C++ runtime DLLs, atl80.dll, msvcm80.dll, msvcp80.dll, and msvcr80.dll. For various reasons I won’t go into, I don’t have the option to statically link to the runtimes and thus avoid the DLL dependencies in the first place.

As an added complication, Microsoft did away with DLL Hell by replacing it with what could be characterized as Side-by-Side Hell, whereby Windows executables reference their dependent DLLs located in a new ‘Side by Side’ (or ‘SxS’) area, using a cryptographic hash not unlike the .NET’s Strong Naming.aspx), only much less documented and vastly more error-prone. So it’s no longer enough to put all the DLLs your app needs in the folder where your app runs and call it a day; now you have to worry about registering the dependent DLLs with Side by Side using an XML manifest, blah blah blah.

There’s an out, however; a vestige, if you will, of the good old days of DLL Hell. If you have a folder named with the name of your DLL (Microsoft.VC80.ATL, for example), and it contains your DLL and a manifest, the Side-by-Side cruft will look there to resolve DLL dependencies. Sweet.

So, I just copied the Microsoft.VC80.ATL and Microsoft.VC80.CRT folders from \Program Files\Microsoft Visual Studio 8\VC\redist\x86 into the folder on the WinPE file system where my app is, and all was well.

Then, I upgraded to Visual Studio 2005 Service Pack 1, which corrects approximately 1,000 of the 600 million bugs included in the initial Visual Studio 2005 release. In this release, the Microsoft.VC80.ATL.manifest file in Microsoft.VC80.ATL is wrong. That is to say, it refers to an older version of the atl80.dll runtime, which is no longer in use, so if you’ve linked against the newer version, and have only the Microsoft.VC80.ATL from the redist folder available to you, your app will act as though the ATL runtime DLL is missing (where, by ‘act’ I mean ‘fail with a meaningless error message’).

As of SP1, the version of the atl80.dll is 8.0.50727.762. And yet, here’s what I see in my Microsoft.VC80.ATL.manifest in \Program Files\Microsoft Visual Studio 8\VC\redist\x86\Microsoft.VC80.ATL:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Copyright © 1981-2001 Microsoft Corporation -->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <noInheritable/>
    <assemblyIdentity
        type="win32"
        name="Microsoft.VC80.ATL"
        version="8.0.50608.0"
        processorArchitecture="x86"
        publicKeyToken="1fc8b3b9a1e18e3b"
    />
    <file name="ATL80.dll"/>
</assembly>

Look at the version number. ‘8.0.50608.0′ WTF?! Want further proof this is wrong? Delve into \Windows\WinSxS\Manifests, and try to find a file called x86_Microsoft.VC80.ATL_1fc8b3b9a1e18e3b_8.0.50727.762_x-ww_cbb27474.manifest. If you can’t, that’s OK; here’s what it looks like (beautified to match the one above):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Copyright © 1981-2001 Microsoft Corporation -->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <noInheritable/>
    <assemblyIdentity type="win32"
        name="Microsoft.VC80.ATL"
        version="8.0.50727.762"
        processorArchitecture="x86"
        publicKeyToken="1fc8b3b9a1e18e3b"/>
    <file name="ATL80.dll" hash="6a91b897f1be0d40f032a8773630c4627cd18bf7" hashalg="SHA1"/>
</assembly>

This is why your ATL apps work if you’ve run vcredist or used a merge module to install the VC++ runtimes. But if, like me, you assume the stuff in the redist folder in Visual Studio’s install directory is actually correct, you’re screwed to the wall.

All I had to do was replace the broken Microsoft.VC80.ATL.manifest file’s contents with what I found in the WinSxS folder, and it worked. But it shouldn’t have come to that, dammit!

Tags: , , , , , ,

Leave a Reply