Why does VC8 install libraries to WinSxS?


style='font-size:10.0pt;font-family:Arial'>One of the changes introduced by href="http://msdn.microsoft.com/visualc/whidbey/">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.

style='font-size:10.0pt;font-family:Arial'>Let me start with a little history. This
story explains some of the earliest, and most powerful motivation for changing
our deployment model.

style='font-size:10.0pt;font-family:Arial;font-weight:bold'>Static Linking

style='font-size:10.0pt;font-family:Arial'>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.

style='font-size:10.0pt;font-family:Arial'>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.

style='font-size:10.0pt;font-family:Arial'>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 style='font-style:italic'>Construction Toy Organizer, which they
ship back to their customer.

style='font-size:10.0pt;font-family:Arial'>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.

style='font-size:10.0pt;font-family:Arial'>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

style='font-size:10.0pt;font-family:Arial'>            style='font-style:italic'>Avoid static-linking library code into your
application wherever possible.

style='font-size:10.0pt;font-family:Arial'>When security problems have been
found in static linked code in the past (such as this href="http://www.cert.org/advisories/CA-2002-07.html">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.

style='font-size:10.0pt;font-family:Arial;font-weight:bold'>Dynamic Linking

style='font-size:10.0pt;font-family:Arial'>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.

style='font-size:10.0pt;font-family:Arial'>DLLs make our servicing obligations
more ambiguous. When you ship a DLL that you got from Microsoft, it’s style='font-weight:bold'>technically possible for style='font-style:italic'>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.

style='font-size:10.0pt;font-family:Arial;font-weight:bold'>Windows

style='font-size:10.0pt;font-family:Arial'>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.

style='font-size:10.0pt;font-family:Arial'>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.

style='font-size:10.0pt;font-family:Arial;font-weight:bold'>Installation
Location Policy

style='font-size:10.0pt;font-family:Arial'>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?

style='font-size:10.0pt;font-family:Arial'>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.

style='font-size:10.0pt;font-family:Arial'>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.

style='font-size:10.0pt;font-family:Arial'>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.

style='font-size:10.0pt;font-family:Arial'>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.

style='font-size:10.0pt;font-family:Arial'>However, it also has the disadvantage
that with the VC7 libraries, we have no way of servicing these DLLs centrally.

style='font-size:10.0pt;font-family:Arial;font-weight:bold'>The Need for Central
Servicing

style='font-size:10.0pt;font-family:Arial'>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.

style='font-size:10.0pt;font-family:Arial'>But, some events transcend this kind
of policy. When a time-critical security problem is found in a href="http://www.microsoft.com/technet/security/bulletin/ms02-039.mspx">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.

style='font-size:10.0pt;font-family:Arial'>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.

style='font-size:10.0pt;font-family:Arial;font-weight:bold'>A Solution

style='font-size:10.0pt;font-family:Arial'>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.

style='font-size:10.0pt;font-family:Arial'>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.

style='font-size:10.0pt;font-family:Arial'>In the mean time, write and tell me
what you think.

style='font-size:10.0pt;font-family:Arial'>Martyn

style='font-size:10.0pt;font-family:Arial'> 


Comments (25)

  1. Bob says:

    Are there plans to deploy the WinSxS Visual Studio 8.0 libraries as an optional Windows Update?

  2. martynl says:

    Nope, we don’t have plans to do that. Application authors should redistribute the VC8 libraries their application needs as part of their application. [This is the same policy we’ve had for several versions — only the VC6 msvcrt.dll was part of Windows].

    Martyn

  3. Mike says:

    Here’s what I worry about: downlevel DLL Hell. The recommended approach is to install 8.0 DLLs in system32 on Windows 2000. Now that those libs are not under file protection (unlike MFC42.DLL and MSVCRT.DLL which is protected in Win2K), any app can come around and overwrite, or worse, uninstall it, breaking your app.

    What is the recommended solution for this?

    Should we have two levels, i.e. an app copy of these DLLs and a system32 copy of these DLLs and have a fallback to the app copy?

  4. martynl says:

    Yep, we worry about DLL hell too. That was another of the key motivators behind our move to fusion.

    But, as you note, it doesn’t help our story on Windows 2000 or Windows 98.

    If you followed our recommendations in VC7 (and installed your DLLs local to your application), you were somewhat better protected. But we have no way to perform emergency servicing on those DLLs.

    So for these older platforms, we reverted back to the policy of installation in system32.

    On these older OSes, it definitely is possible for a rogue application to uninstall msvcr80.dll or to replace a newer version with an older version. But if the application uses our MSMs for central install (which is the only setup model we license and support), then the install will be performed correctly.

    I wouldn’t recommend having a ‘backup’ copy in your application directory, since this can’t even mitigate the problem of installation of an older verison in the central location. With various loading rules in effect, it could even cause two copies of the DLL to be loaded (in unusual cases).

    Your best mitigation against people whose setups break the rules is to support the MSI repair functionality and harden your application to be able to fix itself when others break it.

    Martyn

  5. Anonymous Coward says:

    The problem is, not everybody wants to use MSI. Merge modules don’t help if you use InnoSetup, NSIS, or simple XCOPY. There is no documented API for adding an assembly to WinSxS.

  6. Matt Godbolt says:

    I have to agree with the Anonymous Coward – I’m looking at moving our products to being built in VC8, and we use NSIS for our installations. Currently I can’t see any way of getting the CRT libraries redistributed short of reverse engineering the MSI way of installing – if I place the CRT DLLs in the app path various exceptions about ‘you must use the new way’ are thrown!

  7. Mike says:

    To Matt and AC: I understand the pain with MSI – we don’t even use it unless necessary. The best way to deal with this would be to use the merge modules to great a .MSI file which you can then launch silently from your non MSI based install. All supported platforms will have the necessary Windows Installer service to do this (I believe). A way to create this standalone MSI quickly and easily was found at this URL:

    http://blogs.msdn.com/nikolad/archive/2005/09/02/460368.aspx

  8. martynl says:

    There is no need to use MSI to use this solution. We provide two non-MSI solutions.

    First, the product includes an EXE installer that installs everything to WinSxS. So you can use that if you prefer. You can find that here on your install:

    X:Program FilesMicrosoft Visual Studio 8SDKv2.0BootStrapperPackagesvcredist_x86

    However, if you want to install-applocal, you should make sure that your application has a manifest, and then copy the whole of this folder into your EXE directory:

    X:Program FilesMicrosoft Visual Studio 8VCredistx86Microsoft.VC80.CRT

    and other folders if you use more than the CRT. Make sure you include the manifest.

    Martyn Lovell

    Development Lead

    Visual C++ Libraries

    http://blogs.msdn.com/martynl

  9. Mike says:

    Martyn,

    Thanks for that – I guess I should read the help. There is a great help topic here:

    [URL]ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.en/dv_vccore/html/8d1a994b-9986-4171-9c0b-56d24808fd1f.htm[/URL]

    and

  10. Graham Harwood says:

    Martyn,

    We’ve encountered a difference in the RTM msm’s from the Beta2 in that an extra custom action SxsInstallCA has appeared but is not in the binary table. This causes msi’s built with the release vc80_crt to fail on the missing custom action on Windows 2000 installs.

    Did I miss something? Installing the Dot Net framework fixes it but this can’t be a pre-requisite can it?

    Graham

  11. Graham Harwood says:

    re. SxsInstallCA above:

    I think I might have answered my question. The custom action is provided in MSI Version 3.1.

    Maybe someone can point me to where this change/requirement was documented as I didn’t see it.

    /Graham

  12. Yuhong Bao says:

    Why you kept the servicing relationship for DLLs the same as static libraries?

  13. Yuhong Bao says:

    The same thing would happen if the software was built using Visual C++ 5.0 or 4.2. What happens if the bug was specfic to the Windows 2000 or later version of the DLLs? And why does Windows XP still use msvcrt.dll in system components?

  14. Thomas Olsson says:

    We ran into two problems here:

    1) Windows Installer 3.x is needed (it seems like XP SP2 is enough and that is Windows Installer 3.0 and not 3.1?) Did anyone find where this new requirement is documented.

    2) This is a major problem: The new merge modules for CRT, ATL80 etc. prevents Per User installations. They require Per Machine installations. This is a major problem for us.

  15. Yuhong Bao says:

    You mentioned SQL Slammer.

    Microsoft Update didn’t exist at this time, but if it existed and supported MSDE then, the security update could have been published thru that.

  16. The Visual C++ 8 libraries (CRT, MFC, ATL, etc.) now support the Shared Side-by-Side Assemblies…

  17. When VS2005 SP1 has been released because of manifests it become more visible what version of VC++ DLLs