This is an archive copy of the original article, with the permission of the author, NN (thanks!). You can also read the original entry.
Dynamically linking with MSVCRT.DLL using Visual C++ 2005.
First, download VC++ 9.0 express (it is free and legal to use J). Download it here: https://www.microsoft.com/express/.
Second, download Windows Driver Kit (WDK). Download it here:
We are ready to go.
That’s all. Now your program is dependent only on msvcrt.dll!
It doesn’t say that you cannot compile debug, it just says that you must not use debug macros from CRT like ASSERT, assert and so on.
You can implement these macros by yourself and this works.
The only problem you may notice is compiling static build with RunTime Checks.
There is same function crt_debugger_hook in RunTmChk.lib from VC++ and libcmtd.lib from WDK.
The solution is simple, patch RuTmChk.lib (replace the name to e.g. crt_debugger_hoox) and move it to patched\RuTmChk.lib. Then add patched directory to additional library directories. Now RunTime Checks work with static build.
The implementation is very easy, you just need to implement CrtDbgReportW by yourself (You have the sources in Visual Studio 2008) and return this function.
Notice that ATL must not be compiled in debug.
Just undefine DEBUG macro before including atlbase.h:
You need also to define your own implementation of ATLASSERT, otherwise it uses ASSERTE which cannot be used in our case.
It is not ATL 8.0 nor ATL 9.0 but it is better than nothing J
You may use other Standard C++ Library implementation like STLPort. (https://stlport.org/download.html)
You need some special defines to make STLPort work correctly like:
And some more till you have your code compiled well. (Just read the readme files of STLPort)
You may compile STLPort if you want to use Standard C++ streams.
But what miserable Windows 9x users should do? Use old versions of VC++? No!!
This happens because of linker. Linker from VC++ 9.0 sets minimum Operating System to 5.0 and SubSystem version to 5.0. There /SUBSYSTEM flag does not allow to set the number below 5.0.
The simplest solution is just to patch the executable and change 5.0 to 4.0 J
After that the executable runs smoothly in Windows 98, but not Windows 95.
It can be solved very simple. You just “paste” the code of InterlockedCompareExchange instead of function call and change ImportAddressTable to not point to InterlockedCompareExchange.
Now if you disassemble your program you will see the following code:
This code is created by linker, so you cannot control it. Now we just have to replace call with direct call:
InterlockedCompareExchange implementation (in kernel32.dll):
Now the replacement:
It will be better to reduce the size:
The next thing is to remove InterlockedCompareExchange from Import Table. I just replace it with InterlockedIncrement: Find it using your favourite hex editor (I use HxD, it is free :) ) Replace InterlockedCompareExchange with InterlockedIncrement, fill zeroes to match the same size. Now look at the number of the function, it is BA 02 (02BAh). (It is before the name) InterlockedIncrement has other number: 02C0h. Just set the number.
And of course do not forget to update exe checksum even if no one checks it :)
Why Microsoft doesn’t want us to be able to compile for Windows 9x?
The answer is simple; it costs money to support old and buggy Operating Systems.
You may ask questions about the specific detail, if it is needed.
Thanx to KK