One of the changes introduced by Visual C++ 2005 is a change in how we deploy the Visual C++ Runtime Libraries (CRT, MFC, ATL). Deployment of the runtimes has been a complex and controversial question across many versions. What we’ve attempted to do in this version of the product is both simplify our plan and make it more robust in the face of potential security situations. Explaining this is going to take a while, so I’m going to try to spend a few blog posts on this theme.

Let me start with a little history. This story explains some of the earliest, and most powerful motivation for changing our deployment model.

Static Linking

Microsoft C and later Visual C++ has included libraries since the very first version of the product, as does every C and C++ product. These libraries were typically static-link binaries, consisting of compiled .objs (bound into .libs) that you link to your own application. The libraries do everything from the mundane (such as running initialization code) to the fundamental (implementing printf so that you can say “hello world”). Because the libraries were static-linked into your program by the linker, they became inescapably part of your program.

This static linking had very clear implications for what Microsoft call servicing – the process of shipping updates to existing products. A product like Microsoft Office has a clear Servicing model. Customers buy Microsoft Office from their local software store, and if they later need an update to Office, they contact Microsoft to get that update.

Servicing a development tool is more complex. A customer goes and buys LovellSoft Construction Toy Organizer 1.0 from my local store. They find a bug in the software, and contact LovellSoft. LovellSoft, in turn, determines that the bug was caused by a problem with a piece of Visual C++. They contact Microsoft. Microsoft ships LovellSoft an updated version of the Visual C++ Libraries with a fix for their problem. They then use this update to build an updated copy of Construction Toy Organizer, which they ship back to their customer.

You can see how Microsoft has no direct relationship with LovellSoft’s customer. If the Construction Toy Organizer 1.0 user contacted Microsoft directly, there is no way we could have helped, even if we had wanted to, because our code has been linked in with code supplied by LovellSoft.

As you can see, static linking can present a real servicing problem if a security problem is found in static linked code. This leads to a recommendation

            Avoid static-linking library code into your application wherever possible.

When security problems have been found in static linked code in the past (such as this one), the community has had to wait until many vendors who used the library rebuilt versions of their product. This can take a long time.

Dynamic Linking

For some time, we have also shipped our runtime libraries as a dynamic-link library (DLL). DLLs bring with them several benefits (small binaries, less disk space, reduced code duplication), but also creates some new problems (installation location, versioning) – collectively known as “DLL Hell” in some circles.

DLLs make our servicing obligations more ambiguous. When you ship a DLL that you got from Microsoft, it’s technically possible for LovellSoft’s customer to come directly to Microsoft and get a new version of the DLL with the fix they need. Note that I say “technically”, because in practice, we’ve kept the servicing relationship for our library DLLs the same as the relationship for our static linked code. We provide updated DLLs to software developers, who then deploy those DLLs to their customers.

Windows

Servicing of one version of our libraries (msvcrt.dll and mfc42.dll) is even more complex because the operating system took a hard dependency on the library, meaning that they ship and service the DLL. This means that if LovellSoft are using VC6 to build their application, and they find a bug that they need a fix for, they’d need to get a fix from Visual Studio (so that they could redistribute msvcrt.dll to Windows 95 and Windows NT4), and get operating system patches for whichever of Windows 2000, Windows XP and Windows Server 2003 that their application targets. Complicated.

Of course, this problem is now purely hypothetical, because Visual C++ 6 (from Visual Studio 98) has been unsupported since the end of last month.

Installation Location Policy

The nub of DLL hell problems is a versioning one. Does everyone on the system get the same version of a DLL? Can a rogue application installer ‘roll back’ to an older, broken DLL? If a new application installs a broken version of a DLL, can other applications opt-out?

Our traditional motivation around DLLs had been “sharing” disk and memory pages, so we focused on installing DLLs like msvcr40.dll and msvcr20.dll to System32. But this strategy created the DLL hell problem, as installation of these DLLs frequently broke other programs.

Up to VC6, our advice was – install your CRT DLL in system32 at setup time, assuming it is newer, and reference count the installation. A side effect of this policy is that, in an emergency, we do have a way to update msvcrt.dll. Since it’s required to be installed in a central location, and since the Windows loader prefers loading from that location over most others, we have the ability to deploy fixes directly into system32. This isn’t as robust a plan as you might think, but it was an avenue available to us.

During the time of VC6, Microsoft started to get serious about addressing DLL Hell, and as a result for VC7, our advice was the opposite – install your CRT DLL to your application’s EXE directory and NOT to system32.

This has the advantage that one installation won’t interfere with another. It also helps create software that can be installed by non-administrators, run from networks or ‘xcopy-deployed’ – three things that we were getting much more interested in.

However, it also has the disadvantage that with the VC7 libraries, we have no way of servicing these DLLs centrally.

The Need for Central Servicing

As described above, we normally leave servicing of library DLLs to software vendors. They have the best knowledge of their customers needs, and so have best judgment on when and how to deploy updates to their software.

But, some events transcend this kind of policy. When a time-critical security problem is found in a redistributable component [such as an active worm on the Internet], Microsoft can’t just inform software developers of the problem and wait for them to update their products. Customers and partners will expect us to provide central updates to resolve these kinds of critical issues via http://windowsupdate.com.

The event linked above happened just after I took over leadership of the C++ Libraries team, and made me fundamentally rethink my assumptions about how we should ship our binaries.

A Solution

Luckily, in 1999 a team in Windows started work on creating solutions for exactly these kinds of problems. Their efforts resulted in the addition of manifest support to Microsoft Windows XP, and provided the foundation for us to solve the servicing problem described above, as well as several others that faced us. The solution means that most Visual C++-build DLLs and EXEs have a manifest, but also means that, if an emergency happens, we’ll be much better prepared than we were in previous versions.

In a future entry I’ll describe how this solution works, and other benefits it has, and provide some tips and tricks for problems you might hit.

In the mean time, write and tell me what you think.

Martyn