A Trip Down Memory Lane with EmulateHeap
Enable this compatibility fix on a process to emulate the Windows 95 heap down to the very last detail.
- By Raymond Chen
One of the extremely simple--yet completely crazy--compatibility behaviors available in the Application Compatibility Toolkit is called EmulateHeap.
If you enable this compatibility fix on a process, then all the OS-level heap functions (from HeapCreate to LocalLock to GlobalReAlloc and everywhere in between) are redirected to replacement functions that emulate the Windows 95 heap down to the very last detail.
For example, you might have a program that allocates two blocks of memory, frees them both, then allocates a third block of memory and relies on the fact that the pointer returned by the third allocation is numerically identical to the pointer returned by the first allocation, because that's what happens on Windows 95.
You might have a program that overflows a heap buffer and suffers no serious consequences because the memory that comes after the heap buffer is not being used for anything, or at least that's what happens on Windows 95.
You may also be running a program that frees memory, then accesses the freed memory some time later, expecting that the memory will still contain the values that it did when it was freed and hasn't been reused for some other memory allocation, or at least it isn't reused on Windows 95. (Or even scarier, the program relies on the fact that the values change after the memory was freed in a very particular way!)
There are a whole bunch of tiny little weird dependencies like this in older applications. These applications weren't coded that way intentionally; these behaviors were just little mistakes scattered here and there, mistakes that programs managed to get away with because they happened not to cause problems when run in conjunction with the Windows 95 Heap Manager. And then when these programs are run on any other version of Windows, they crash because those other versions of Windows have a different Heap Manager.
Now, this doesn't make the Windows 95 Heap Manager "better" or "more robust" than the others. It's just different. There are probably just as many behaviors that manage to survive without crashing on Windows 7 that would have crashed on Windows 95. The effect you're seeing is just self-selection: If you wrote a program in 1995 that had a bug that crashed on Windows 95, you'd notice and fix it because Windows 95 was your target platform!
When the EmulateHeap compatibility fix is enabled on a process, the Heap Manager's behavior is altered so that it aligns all the stars to exactly the positions they were in 1995. All the coincidences that occurred on Windows 95--those coincidences that applications were unwittingly relying on--are once again forced to occur, so that the applications containing these types of errors would continue to run in exactly the same way they did before. Mind you, forcing all the coincidences to line up also means that new heap features such as low fragmentation must be turned off, because those features would shift the coincidences that applications were relying on.
That explains the simple part.
The reason this is also crazy: The way the application compatibility folks managed to emulate the Windows 95 Heap Manager so perfectly is that they simply took a copy of the Windows 95 Heap Manager source code, recompiled it, and added it to the compatibility infrastructure. In other words, there's a copy of a significant chunk of the Windows 95 kernel inside the Windows application compatibility framework. Not quite an entire copy of Microsoft Bob, but in this case, the chunk of code lifted intact from Windows 95 is more than ballast; if the EmulateHeap compatibility fix is enabled on a process, that ancient code gets loaded from the hard drive and begins doing actual work!
Windows 7 has a new Fault Tolerant Heap subsystem that attempts to detect many classes of simple application heap memory errors and apply mitigations automatically. For example, the Fault Tolerant Heap detects and corrects double-frees, heap buffer overruns (at least small overruns) and using memory after freeing it (at least if you use it only a short time after you free it). Hopefully, this more general solution means that the next version of Windows won't need to include a copy of the Windows 7 Heap Manager inside its compatibility infrastructure files.
[Editor's Note: This article originally appeared in TechNet Magazine.]
Raymond Chen's Web site, "The Old New Thing," and identically titled book (Addison-Wesley, 2007) deal with Windows history, Win32 programming, and Krashen's Comprehensible Input Hypothesis.