'How to link against msvcrt.dll instead of msvcr100.dll in VC++ 10.0?

Is it possible to link against VC6's MSVCRT.DLL in VC++10.0?

By default it seems to be linking with MSVCR100.DLL, but I don't want to redistribute yet another DLL (MSVCRT.DLL is already available in every OS that I support).

==EDIT==

To clarify: my application is a pure C application that makes WinAPI calls. I do understand that doing C++ will require the C++ runtime, which is not bundled in Windows by default (and most probably has to match the compiler anyway). My question is about pure C usage, and only the CRT functions that exist in the earliest version of Windows that I'm targeting.



Solution 1:[1]

It's not the VC6 runtime. It's a system copy of MSVCRT.DLL that's bundled with Windows rather than Visual Studio. Each new version of Windows gets a new version of MSVCRT.DLL, as you can see by checking the file sizes.

You can compile against the system copy of MSVCRT.DLL by using the Windows Driver Kit. Note that this DLL is for use "only by system-level components." What's a system-level component? Well, a driver. Or, for example, a text service:

http://blogs.msdn.com/b/tsfaware/archive/2008/01/17/visual-studio-2008-issues.aspx

If you're building a text service DLL ... I would recommend installing the Vista (or XP) DDK and use the DDKWizard instead. The DDK comes with its own C/C++ compiler that uses the C Runtime Library that ships with the OS (and won't cause problems with other applications) ...

More information:

http://kobyk.wordpress.com/2007/07/20/dynamically-linking-with-msvcrtdll-using-visual-c-2005/

A question arises, what does Microsoft do? They deploy their applications to a variety of Windows environments. A look at Windbg’s dependencies showed it’s using MSVCRT.DLL rather than one of the newer CRTs. Microsoft’s new Network Monitor 3.1 also uses MSVCRT.DLL. Windows Desktop Search is also using the old, trusty CRT.

How can all these new applications be using the vintage CRT? They’re not still using the antique, unsupported Visual C++ 6.0, are they? Well, no. The answer is more complicated and can be found in the Windows Driver Kit (WDK).

Update: The Windows 8 Driver Kit introduced a new MSBuild-based build system, which no longer links against the system copy of MSVCRT.DLL. However, binaries built with the Windows 7 Driver Kit still work on Windows 8 and Windows 10.

MSVCRT.DLL is still shipped with Windows 10 for backward compatibility, so it carries a File version of 7.0.#####. A component that is still being actively developed, such as user32.dll, carries a File version of 10.0.#####.

Solution 2:[2]

(you can find an executive summary, or TL;DR, at the bottom)

Important: This answer refers to official Microsoft toolchains only, not to something like the MinGW toolchain (GCC-based) which is also known to link against msvcrt.dll. But I doubt Microsoft would be inclined to support that toolchain anyway ;)

Short answer: no!

Don't even try using Visual C++ 2010 for the task.

There's an official and supported method: use a standalone WDK, if you need your application to link against msvcrt.dll!

You should never attempt to use a compiler toolchain that doesn't match the CRT headers and libs. Use the toolchains as Microsoft intended, not a patchwork you create. Don't mix and match. Use what's handed to you by Microsoft. But use that (and don't be afraid by the FUD).

The newest WDK which you can use to link against msvcrt.dll (7600.16385.1) uses cl.exe version 15.00.30729.207. This corresponds roughly to the compiler that comes with Visual C++ 2008! Later WDKs will link against the CRT of the Visual C++ version they require.

The msvcrt.dll you'll find on, say Windows XP or Windows 7 is not the original DLL which was included with Visual C++ 6.0 (even the most updated version of VC6).

This has also been correctly stated in other answers. No surprises there.

However, the msvcrt.dll which you will find on modern systems will, contrary to what other answers suggest, allow programs that linked against the original VC6 CRT to continue to work. Even today. It's a contract. And the promotion of msvcrt.dll to a system DLL further validated that contract.

A little historical background

The toolchains used by Microsoft internally were somewhat similar to what the WDKs prior to the Windows 8 WDK provided. I will exclusively write about these and use the term WDK (or standalone WDK) uniformly, even when prior to the Vista WDK they were called DDK.

The good folks from OSR, who seem to have access to the Windows source code or people who do, confirmed during one seminar I attended some years back that the WDK used to be a trimmed down version of the toolchain used internally to build Windows around the time (~2005). Similar hints can be found from MSFT's own Larry Osterman and early works of Alex Ionescu on tinykrnl, the co-author of recent editions of "Windows Internals". BCZ likely alludes to build -cZ, a commonly used invocation with the WDKs I am describing here.

The reason it is interesting in this context is: all standalone WDKs allow you to create executables that link against msvcrt.dll by default. For the standalone WDKs msvcrt.dll is the CRT, just like for Visual C++ 2010 that's msvcr100.dll.

One should also note that the toolchains were updated alongside the Visual Studio toolchains. For example in the 3790.1830 WDK cl.exe reports as roughly on par with Visual C++ 2003:

C:\WINDDK\3790.1830\bin\x86>cl /version
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.4035 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

And for the 6001.18002 WDK (latest to support Windows 2000!) as roughly on par with Visual C++ 2005:

C:\WINDDK\6001.18002\bin\x86\x86>cl/version
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.278 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

For the 7600.16385.1 WDK it's on par with Visual C++ 2008.

Standalone WDKs

The WDK versions starting with the one for XP and up until (and including) Windows 7 SP1 did not require Visual Studio. They came with their own toolchain.

Versions prior to Windows XP required Visual C++ to build anything. If I remember correctly VC6 for the Windows 2000 DDK.

Versions starting from the Windows 8 WDK require Visual C++ again and integrate more tightly than ever with it (including wizards and even extensions for debugging and some driver-specific tasks). That's also the reason why when you use the respective WDKs, they will link to the CRT of the respective toolchain.

During the time of the standalone WDKs it was not unheard of - and that's the very reason for DDKWizard and VisualDDK - that people tried using Visual Studio to wrap the WDK build process. Some even used the unsupported method that Microsoft recommended against and built their drivers with the Visual Studio toolchains. Those unsupported methods amount roughly to what you are trying. So don't.

Anyway, the build process using WDK's build.exe with sources and makefile and so on was cumbersome and limiting. For example to build from any source file outside the current directory or its parent directory, you'd have to write your own NMake rules. After all build.exe was a wrapper around an NMake-based build. Your local makefile.inc would get included by the global one provided by the WDK/DDK.

Why linking to msvcrt.dll is officially supported

As mentioned earlier, linking against msvcrt.dll is supported with the standalone WDKs.

This is perfectly fine to do as well. In fact the USE_MSVCRT=1 statement in the sources file has exactly that effect. See here. Quoting from the 7600.16385.1 WDK documentation:

USE_MSVCRT

Use the USE_MSVCRT macro to instruct the Build utility to use the multithreaded runtime libraries in a DLL for your build.

Syntax

USE_MSVCRT = 1

[...]

Note You should never list Msvcrt.lib or Msvcrtd.lib in TARGETLIBS. However, you can list Ntdll.lib in TARGETLIBS.

Why would Microsoft even offer this path if it were not supported by them? Correct, they wouldn't!

As a matter of fact said WDKs (XP..7 SP1) have been using the system DLL msvcrt.dll as their CRT.

Caveats

There's mainly one caveat. The way SEH is implemented has changed over time with newer Visual C++ versions. Since the toolchains from the standalone WDK correspond closely to specific Visual C++ version, they inherit the respective SEH handling.

For example when you use the Windows 7 SP1 WDK to target Windows 7 and with USE_MSVCRT=1, it statically imports _except_handler4_common. That function was not available on Windows Server 2003, for example. So trying to run such an application on versions of Windows prior to the targeted version may fail. So in such a case you are venturing into "unsupported territory" and all disclaimers apply. However, you have the option of using the method outlined here, i.e. linking to msvcrt_win2000.obj, msvcrt_winxp.obj and msvcrt_win2003.obj (available in the Vista and 7 WDKs) to achieve the level of (binary) backward compatibility you desire.

Well, on the other hand, if you decide to set WINVER=0x0601 you should also not be surprised to find that the resulting executable imports functions from kernel32.dll (or other system DLLs) which are not available on, say, Windows XP. So why expect different semantics with regard to msvcrt.dll?

As another side-note: even checked builds (commonly considered to correspond to debug builds) also link against msvcrt.dll, not its debug version counterpart! Because "checked" refers to the fact that assertions are left in; it does not refer to particular configurations of the CRT, such as "release" or "debug". The assumption that the unavailability of a debug build for msvcrt.dll in the standalone WDKs means it's somehow not the C runtime of those WDKs is plain and simple a misunderstanding of what checked build means.

There is another minor caveat. If you use, say, the Windows 7 WDK, to achieve linking against msvcrt.dll, you're using a toolchain unaware of developments since Windows 7. This includes import libraries, but also headers. So don't expect it to support features that were unavailable at the time it was released.

System DLL: msvcrt.dll

msvcrt.dll was promoted to the status of a system DLL some years ago, which means it comes included with the system (and can be relied on, literally) unlike other Visual C++ CRTs, for which you need to install the respective redistributable packages. Which is also the gist of the blog post by Raymond Chen quoted in another answer.

Since the standalone WDKs (XP..7 SP1) default to linking to msvcrt.dll as their CRT, there's no objective argument against it. Of course opinions vary.

A "reply"

Unfortunately this answer which has changed a lot since I first commented on it, perpetuates FUD and tries to pull quotes from purportedly authoritative sources out of context. It also links to original (MSFT) sources which - upon close inspection - do not support the statements for whose support they were linked.


Microsoft's Raymond Chen blogged on this a few years ago. From his blog Windows is not a Microsoft Visual C/C++ Run-Time delivery channel:

one DLL compatible with all versions of Visual C++ was a maintenance nightmare ... At some point, the decision was made to just give up and declare it an operating system DLL, to be used only by operating system components.

Emphasis mine. Think again, are you really writing something that ships with Windows? Is it THAT difficult to add a supported file to your setup program or link the static version of CRT, instead of depending on a system component that Microsoft gave up on compiler compatibility more than a decade ago?

Okay, so February 2010 is more than a decade ago (time this answer was written: March 2016)? Because that's the release date of the 7600.16385.1 WDK, which officially supports linking against msvcrt.dll.

And the rest of Raymond's statements may match what Microsoft initially intended, but he even admits that they gave up on that and promoted it to a system DLL.

Also, it's quite dishonest to mix truly ancient history (Windows 9x) with recommendations in favor of using standalone WDKs, which don't even support Windows 9x. The historical background Raymond describes is pre-W2K and non-NT. The background I describe above refers to the NT lineage of Windows and I only know the standalone DDKs/WDKs (and newer) from practice, so I cannot tell how it was or was supposed to be prior to that.

All that said: his blog is not to be confused with official documentation from Microsoft, although a lot of gems can be found on his blog and I've been an avid reader for years.

And although that is more than a decade ago, the msvcrt.dll version information in Windows 2000 (SP4) says:

Description:    Microsoft (R) C Runtime Library
Product:        Microsoft (R) Visual C++
Prod version:   6.10.9844.0
File version:   6.10.9844.0

... contrary to Raymond's introductory statement.

Only with Windows XP did that change to:

Description:    Windows NT CRT DLL
Product:        Microsoft« Windows« Operating System

It is amazing how many people are still in denial of this decision.

It's fair to assume after some previous comments that this is squarely aimed at me.

Well, I am not in denial of decisions made with the release of the Windows 8 WDK. But that doesn't "unrelease" the standalone WDKs which officially supported linking to msvcrt.dll nor does it "undocument" what can be found in their respective official documentation.

Hey, it's cool with me if you're in the luxurious position to only have to support Windows 7 or 8 and newer, or something along those lines. However, I have to support earlier Windows versions as well and so I'll make full use of the official tools provided by Microsoft for these Windows versions. Be that Visual C++ 2005 with the appropriate SDK integrated or be that a standalone WDK.


Those people caused "a lot of grief for the Visual C++ product team"

This statement refers to the aforementioned blog post by Raymond Chen, but pulls Raymond's statements out of context, specifically out of temporal context. The grief was caused by people trying approximately what the asker wants to do - and worse: reaching into the guts/internals of msvcrt.dll. And that was pre-W2K. It was not (and would not be) caused by using an official toolchain like the standalone WDKs from Microsoft.


The msvcrt version in modern versions of Windows has never been mentioned in the corresponding versions of Windows SDK.

While modern should be qualified, the use of "Windows SDK" suggests that it refers to all Windows SDKs after they were renamed from "Platform SDK". And I am inclined to readily believe that. But the poster is ignoring the standalone Windows WDKs (and prior to that DDKs) which not only mention it, but also use msvcrt.dll as their CRT. They are official toolchains from Microsoft aimed at both kernel and user mode development.


Microsoft update the CRT DLL (for example, when releasing a Windows Media Player patch) using a current toolchain that may or may not be made public.

That's correct. msvcrt.dll keeps getting updated because it has been promoted to a system DLL. And that is the contract one can rely on when using the WDKs. They're not going to break applications built with their own toolchains, just because they're patching msvcrt.dll.


You can count on them are not using the ancient WDK compiler and libs to build the msvcrt DLL in Windows

I'd not even be sure of that, but an official toolchain from 2010 isn't exactly something I'd call ancient. Besides, since Microsoft dropped support for XP and 2003 meanwhile, they only need to support Vista and onwards. That's bound to be easier with the latest Visual C++ version which directly provide the compiler and tools for the WDKs starting with the Windows 8 one.

(why ancient? Because the WDK team does not like people use their compiler to link against msvcrt either, and removed the loophole in version 8.0 to stop those "clever" people).

Oh really, does Doron actually say that at the linked forum post? Well, no:

the win7 wdk build deployed successfully because you linked against the windows CRT (msvcrt.dll). we don't want 3rd parties doing that anymore, so we removed that capability in the win8 wdk. it still works for backwards compat. while it may deploy successfully, there may be whck logo checks that make sure you use the right CRT

(emphasis mine)

The statement is about a "political decision" (and an official one at that) by Microsoft to change their stance. The "anymore" in fact implies that this only changed with the Windows 8 WDK. The first modern WDK that integrates with Visual C++ again (since the Windows 2000 DDK). So since the WDK has been demoted from a standalone toolchain to an extension that integrates with a given Visual C++ version, the new requirements are no surprise at all.

It is, btw, also dishonest to argue based on the Windows 8 WDK and newer, when the suggestions regarding standalone WDKs, which use msvcrt.dll as their CRT, were prior to that policy change. It's also dishonest to mix the history that led to the promotion of msvcrt.dll to a system DLL with the era after it had been promoted.


Glossary

  • CRT == C/C++ runtime
  • 3790.1830 == Windows Server 2003 Service Pack 1 (SP1) Driver Development Kit (DDK)
  • 6001.18002 == Windows Driver Kit SP1 for Windows Server 2008/Vista
  • 7600.16385.1 == Windows Driver Kit version 7.1.0 (Supporting Windows 7, Windows Vista, Windows XP, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003)

TL;DR

Contrary to this answer it is perfectly fine to use Microsoft's own and unchanged toolchains, such as the standalone WDKs, which support linking against msvcrt.dll (XP..7 SP1) "natively". It's even documented in the documentation that comes with those toolchains (unless you decide to not install it or close your eyes :)).

You "only" have to make sure to target the correct Windows version when building (essentially the same as defining the correct WINVER). But the same can be said for other system DLLs (e.g. kernel32.dll, user32.dll ...).

However, using any Visual C++ since 2002 to link against msvcrt.dll is bound to create trouble. Don't mix and match. Simply use the CRT matching those particular Visual C++ versions.

Solution 3:[3]

An average "Petzold-style" Win32 program only needs a few functions out of msvcrt.dll. In my case, I often need the float-point formatting routines, like _sntprintf(). And it's unlikely that the functionality of such functions ever changes. For this reason, I created an msvcrt-light.lib import library (download) as a replacement for the standard library which I include in the MSVC project.

For full-fledged C++ programs, msvcrt-light.lib may not be suitable at all. Use the DDK as stated above.

Solution 4:[4]

This requires CRT compatibility across major compiler releases, which Microsoft tried to accommodate (e.g. added a VC5 heap to the VC6SP2 runtime) but eventually gave up on and introduced msvcrxx.dll that are in use today. If you look at the CRT source, you will find lots of #ifndef _SYSCRT, that's the difference between Microsoft's msvcrt.dll and the one used by your compiler when generating code.

Microsoft's Raymond Chen blogged on this a few years ago. From his blog Windows is not a Microsoft Visual C/C++ Run-Time delivery channel:

one DLL compatible with all versions of Visual C++ was a maintenance nightmare ... At some point, the decision was made to just give up and declare it an operating system DLL, to be used only by operating system components.

Emphasis mine. Think again is it THAT difficult to add a supported file to your setup program or link the static version of CRT, instead of depending on a system component that Microsoft gave up on compiler compatibility more than a decade ago?

It is amazing how many people are still in denial of this decision. Those people caused "a lot of grief for the Visual C++ product team", and if you keep pissing them off, I won't be surprised if they piss you off sometimes like what they did in Windows XP that crashed a lot of VC6 apps. A lot of people did not follow Windows 2000 application developer guidelines and put settings/game saves in the Program Files folder. We all know what a good ending it is when Windows Vista was released.

By the way the dll is not VC6's. Using an old dll in the system would fail the Microsoft’s Security Development Lifecycle automatically. (https://blogs.msdn.microsoft.com/oldnewthing/20100607-00/?p=13793/#10020962). You don't realistically expect Microsoft use VC6 to compile its modern product, do you?

The msvcrt version in modern versions of Windows has never been mentioned in the corresponding versions of Windows SDK. Whatever compiler version or CRT lib version you use, it most likely won't match the majority of DLL versions on your customer's machine. Microsoft update the CRT DLL (for example, when releasing a Windows Media Player patch) using a current toolchain that may or may not be made public. You can count on them are not using the ancient WDK compiler and libs to build the msvcrt DLL in Windows (why ancient? Because the WDK team does not like people use their compiler to link against msvcrt either, and removed the loophole in version 8.0 to stop those "clever" people).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Damian Yerrick
Solution 3 0xC0000022L
Solution 4 Yuhong Bao