]> git.lyx.org Git - features.git/commitdiff
visual leak detector: update add patch for msvc10
authorPeter Kümmel <syntheticpp@gmx.net>
Sun, 22 May 2011 11:26:44 +0000 (11:26 +0000)
committerPeter Kümmel <syntheticpp@gmx.net>
Sun, 22 May 2011 11:26:44 +0000 (11:26 +0000)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@38809 a592a061-630c-0410-9148-cb99ea01b6c8

23 files changed:
development/Win32/vld/CHANGES.txt
development/Win32/vld/README.html
development/Win32/vld/include/vld.h [deleted file]
development/Win32/vld/src/callstack.cpp
development/Win32/vld/src/callstack.h
development/Win32/vld/src/crtmfcpatch.h [new file with mode: 0644]
development/Win32/vld/src/map.h
development/Win32/vld/src/ntapi.cpp
development/Win32/vld/src/ntapi.h
development/Win32/vld/src/resource.h [new file with mode: 0644]
development/Win32/vld/src/set.h
development/Win32/vld/src/tree.h
development/Win32/vld/src/utility.cpp
development/Win32/vld/src/utility.h
development/Win32/vld/src/vld.cpp
development/Win32/vld/src/vld.h [new file with mode: 0644]
development/Win32/vld/src/vldapi.cpp
development/Win32/vld/src/vldheap.cpp
development/Win32/vld/src/vldheap.h
development/Win32/vld/src/vldint.h
development/Win32/vld/tools/cmake/CMakeLists.txt
development/Win32/vld/tools/cmake/vld.cmake
development/Win32/vld/vld.ini

index 1c6f100d6406f92631f2a2769f91fe46af956354..c6805efef961ca9a84aaf2c4f124900e32fdf292 100644 (file)
@@ -1,12 +1,36 @@
-Visual Leak Detector (VLD) Version 1.9f (beta)
+Visual Leak Detector (VLD) Version 1.9h (beta)
 
   Change Log / Release Notes
+
+    Enhancements:
+  + Added support to work with Visual Studio 2010.
   
+1.9h beta (24 February 2009)
+----------------------------
+  Enhancements:
+  + Added support to work with Visual Studio 2008.
+
+  Known Bugs/Restrictions:
+  + Same bugs/restrictions as version 1.9f.
+
+
+1.9g beta (16 April 2008)
+----------------------------
+  Bugs Fixed:
+  + Another deadlock condition may occur when loading DLLs into the process
+    being debugged. Special thanks to Eric Bissonnette and Kristian Paradis for
+    contributing this patch.
+
+  Known Bugs/Restrictions:
+  + Same bugs/restrictions as version 1.9f.
+
+
 1.9f beta (18 November 2006)
 ----------------------------
   Bugs Fixed:
   + Deadlocks or access violations may occur when loading DLLs into
     multithreaded processes.
+
   + In multithreaded programs, if the main thread terminates before other
     threads in the process, then Visual Leak Detector may cause an access
     violation while generating the memory leak report.
@@ -14,15 +38,19 @@ Visual Leak Detector (VLD) Version 1.9f (beta)
   Known Bugs/Restrictions:
   + Memory allocations made through calls to functions loaded from a DLL using
     delayed loading may not be detected.
+
   + Support for programs that use MFC 7.0 or MFC 7.1 is not complete yet. Some
     memory leaks from such MFC-based programs may not be detected.
+
   + Visual Leak Detector may report leaks internal to Visual Leak Detector
     if the main thread of the process terminates while other threads are still
     running.
+
   + If more than one copy of the same C Runtime DLL is loaded in the process at
     the same time, then some leaks may go undetected (note that loading more
     than one copy of the C Runtime DLL into a process at the same time is
     probably a bad idea to begin with).
+
   
 1.9e beta (16 November 2006)
 ----------------------------
@@ -34,12 +62,15 @@ Visual Leak Detector (VLD) Version 1.9f (beta)
   + Numerous deadlock situations. The multithread synchronization scheme has
     been completely re-written which should make deadlocks in VLD much less
     likey to happen.
+
   + An access violation will occur in VLD if GetProcAddress is called to obtain
     an export's address by ordinal, for certain libraries.
+
   + Problems may potentially occur when the program being debugged exits due to
     the Debug Help Library having been detached from the process too early.
     Symptoms might include access violation exceptions or other erratic behavior
     just as the program exits and while VLD is generating the leak report.
+
   + The copy of vld.ini installed in VLD's installation directory overrides any
     other copies of vld.ini that are created, even copies placed in the
     working directory of the program being debugged.
@@ -47,35 +78,46 @@ Visual Leak Detector (VLD) Version 1.9f (beta)
   Known Bugs/Restrictions:
   + Memory allocations made through calls to functions loaded from a DLL using
     delayed loading may not be detected.
+
   + Support for programs that use MFC 7.0 or MFC 7.1 is not complete yet. Some
     memory leaks from such MFC-based programs may not be detected.
+
   + If more than one copy of the same C Runtime DLL is loaded in the process at
     the same time, then some leaks may go undetected (note that loading more
     than one copy of the C Runtime DLL into a process at the same time is
     probably a bad idea to begin with).
+
   
 1.9d beta (12 November 2006)
 ----------------------------
   Bugs Fixed:
   + Failed assertion "freed == TRUE" pops up when running a program with VLD
     without the debugger attached.
+
   + Some, but not all, multithreaded programs that dynamically load and unload
     many DLLs have been known to experience problems, such as deadlocks or
     exceptions, when used with VLD.
+
   + Failed assertion "exportmodule != NULL" pops up when running some programs
     with VLD.
+
   + VLD fails to show file names or function names in the memory leak report for
     some programs that are linked with the dynamic CRT library.
+
   + Access violation exceptions are thrown, but caught by the operating system,
     when running some programs with VLD.
 
+
 1.9c beta (6 November 2006)
 ---------------------------
   New Features/Enhancments:
   + New NSIS installer makes setting up and using VLD much easier.
+
   + No need to manually copy dbghelp.dll to the right location, VLD will always
     find the right version.
+
   + MFC 8.0 is now fully supported.
+
   + The memory leak report is now written to the output window much faster.
     Support has been added, through a new configuration option, to slow down
     the report output for older versions of Visual Studio that have trouble
@@ -83,16 +125,22 @@ Visual Leak Detector (VLD) Version 1.9f (beta)
   
   Bugs Fixed:
   + All known compatibilities with Visual Studio 2005 have been eliminated.
+
   + Leaks from calloc may go undetected.
+
   + Leaks from vector new operator may go undetected.
+
   + VLDDisable and VLDEnable do not work as expected; some memory leaks that
     should be ignored by VLD due to a previous call to VLDDisable are still
     reported.
+
   + Unloading and reloading a previously loaded module may cause leaks that
     occur in the module after it was reloaded to go undetected.
+
   + If vld.h is included in a release build, then the compiler will generate
     errors if the VLDEnable or VLDDisable APIs have been used.
 
+
 1.9b beta (26 October 2006)
 ---------------------------
   Bugs Fixed:
@@ -114,6 +162,7 @@ Visual Leak Detector (VLD) Version 1.9f (beta)
     This restriction does not apply to programs that use MFC 4.2, which is fully
     supported.
 
+
 1.9a beta (9 March 2006)
 ------------------------
   New Features/Enhancments:
index e624126f395ed0bf50aa1b4a91d55bd19d8c8950..87b94694dd8017eb7beba309959825df94d9a437 100644 (file)
         blockquote {
             font-style: italic;
         }
+
+        form {
+            margin: 20px;
+        }
     </style>
 
     <title>Visual Leak Detector (Beta)</title>
 
 <div id="masthead">
 
-<h1>Visual&nbsp;Leak&nbsp;Detector&nbsp;1.9f (Beta)</h1>
+<h1>Visual&nbsp;Leak&nbsp;Detector&nbsp;1.9h (Beta)</h1>
 
 <p id="slogan">Enhanced Memory Leak Detection for Visual&nbsp;C++</p>
 
 
     <li><a href="#restrictions">Known Restrictions</a></li>
 
+    <li><a href="#contibuting">Contributing</a></li>
+
     <li><a href="#license">License</a></li>
 
     <li><a href="#contact">Contacting the Author</a></li>
+
+    <li><a href="#help-wanted">Additional Developers Wanted</a></li>
 </ul>
 
 </div> <!-- #toc -->
    Detector include and library directories to the Visual C++ include and library directory search paths:</p>
 
 <ul>
-    <li><strong>Visual&nbsp;C++ 8</strong>: Go to Tools -> Options -> Projects and Solutions -> VC++ Directories.
+    <li><strong>Visual&nbsp;C++ 8 and 9</strong>: Go to Tools -> Options -> Projects and Solutions -> VC++ Directories.
         Select "Include files" from the "Show Directories For" drop-down menu. Add the
         <span class="filename">include</span> subdirectory from the Visual Leak Detector installation directory. Move it
         to the bottom of the list. Then select "Library files" from the drop-down menu and add the
 <h2 id="build">Building Visual&nbsp;Leak&nbsp;Detector from Source</h2>
 
 <p>Because Visual&nbsp;Leak&nbsp;Detector is open source, it can be built from source if you want to tweak it to your
-   liking. The most difficult part about building VLD from source is getting your build environment correctly set up.
+   liking. As of Visual Studio 2008, the source can usually be built out-of-the-box without downloading or installing
+   any other tools. If you are using Visual Studio 2008 (or later), you can skip ahead to
+   <a href="#exec">Executing Your Built vld.dll</a>.
+
+<p>Users with older versions of Visual Studio should continue reading here and follow the instructions in the next
+   subsection.</p>
+
+<h3>For Older Versions of Visual Studio</h3>
+
+<p>The most difficult part about building VLD from source is getting your build environment correctly set up.
    But if you follow these instructions carefully, the  process should be fairly painless.</p>
 
 <ol>
     <li>VLD depends on the Debug Help Library. This library is part of
         <a href="http://www.microsoft.com/whdc/devtools/debugging/default.mspx">Debugging Tools for Windows</a> (DTfW).
         Download and install DTfW in order to install the required headers and libraries. I recommend installing version
-        6.5 of DTfW. Newer versions may also work, but older versions will probably not work. Be sure to manually select
-        to install the SDK files during the DTfW installation or the headers and libraries will not be installed (they
-        are not installed with a default installation).</li>
+        6.5 of DTfW, or later. Newer versions tend to  work fine, but older versions will probably not work. Be sure to
+        manually select to install the SDK files during the DTfW installation or the headers and libraries will not be
+        installed (they are not always installed with a default installation).</li>
 
     <li>Visual&nbsp;C++ will need to be made aware of where it can find the Debug Help Library header and library files.
         Add the <span class="filename">sdk\inc</span> and <span class="filename">sdk\lib</span> subdirectories from the
 <p>Once you have completed all of the above steps, your build environment should be ready. To build VLD, just open the
    <span class="filename">vld.sln</span> solution file and do a full build.</p>
 
+<h3 id="exec">Executing Your Built vld.dll</h3>
+
 <p>When actually running the built project, <span class="filename">vld.dll</span> will expect to find the Debug Help
    Library as a private assembly. The private assembly must be located in the same directory as
    <span class="filename">vld.dll</span> (either the <span class="filename">Release</span> or
 
 <h2 id="x64">Windows x64 Support</h2>
 
-<p>The VLD source code has been modified to add support for x64-based 64-bit Windows. However, the binary contained in
-   the distributed version of VLD is 32-bit only. To take advantage of the 64-bit support, you'll need to build a 64-bit
-   version of VLD from source. To build the 64-bit version, follow the instructions for <a href="#build">building VLD
-   from source</a>. So long as it is built using a x64-compatible compiler in 64-bit mode, the resulting DLL will be a
-   64-bit binary.</p>
-
-<p class="note"><strong>Note:</strong> I have not personally tested the 64-bit extensions so they are not absolutely
-   guaranteed to work out-of-the-box. There may be a few lingering 64-bit compiler errors that still need to be worked
-   out. If you need 64-bit support and run into problems trying to build the source in 64-bit mode, please
-   <a href="mailto:dmoulding@gmail.com">let me know</a>. I'll be glad to assist in getting the 64-bit code working
-   properly.</p>
+<p>Currently VLD will not build on x64 due to limitations of the x64 compiler. Some efforts have been undertaken to
+   get it working in a 64-bit environment, but have not yet been successful. If you need 64-bit support and run into
+   problems trying to build the source in 64-bit mode, please <a href="mailto:dmoulding@gmail.com">let me know</a>.
+   I'll be glad to assist in getting the 64-bit code working properly, if at all possible.</p>
 
 
 
        DLLs in memory leak detection, by setting the <span class="option">ForceIncludeModules</span> configuration
        option to: "mfc70d.dll mfc71d.dll" and explicitly adding <span class="filename">vld.lib</span> as an input file
        on the linker command line (can be added through project settings by adding it to the list of library modules in
-       the linker options). This restriction does not apply to programs that use MFC 4.2 or MFC 8.0 which are both fully
-       supported.</li>
+       the linker options). This restriction does not apply to programs that use MFC 4.2, MFC 8.0, or MFC 9.0, which are
+       all fully supported.</li>
        
    <li>Visual Leak Detector may report leaks internal to Visual Leak Detector if the main thread of the process
        terminates while other threads are still running.</li>
        
    <li>On Windows 2000 and earlier operating systems, you may need to manually add the
-       <span class="filename">bin\Microsoft.VC80.CRT</span> subdirectory from the Visual Leak Detector installation
-       directory to the system PATH environment variable. Also, <span class="filename">dbghelp.dll</span> will probably
-       need to be manually copied to the directory where the program being debugged resides. Otherwise the system may
-       not find the required DLLs when running VLD.</li>
+       <span class="filename">bin</span> subdirectory from the Visual Leak Detector installation directory to the system
+       PATH environment variable. Also, <span class="filename">dbghelp.dll</span> will probably need to be manually copied
+       to the directory where the program being debugged resides. Otherwise the system may not find the required DLLs when
+       running VLD.</li>
        
     <li>If more than one copy of the same C Runtime DLL is loaded in the process at the same time, then some leaks may
         go undetected (note that loading more than one copy of the C Runtime DLL at the same time is probably a bad idea
 
 
 
+<h2 id="contibuting">Contributing</h2>
+
+<p>I encourage developers who've added their own features, or fixed bugs they've found, to contribute to the project.
+   The full version-controlled source tree is available publicly via Git at the URL below. Feel free to clone from this
+   URL and submit patches for consideration for inclusion in future versions. You can also hop onto
+   <a href="http://github.com">GitHub</a> (accounts are free) and issue pull requests for changes that you've made and
+   would like to share.</p>
+
+<p>Git Repository URL: git://github.com/dmoulding/vld.git</p>
 
 <h2 id="license">License</h2>
 
@@ -733,12 +754,24 @@ BWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbG
     </div>
 </form>
 
+
+
+<h2 id="help-wanted">Additional Developers Wanted</h2>
+
+<p>This project is looking for additional developers who have the time, knowledge, and talent, to help make VLD continue
+   to be a useful utility for the Windows developer community. If you feel that you or someone you know would be
+   interested in becoming an active member of the Visual Leak Detector development team, please let me know.</p>
+
+
+
 <p id="compliance">
     <a href="http://validator.w3.org"><img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a>
     <a href="http://jigsaw.w3.org/css-validator"><img id="valid-css" src="http://jigsaw.w3.org/css-validator/images/vcss" alt="Valid CSS!" /></a>
 </p>
 
-<p id="copyright">Copyright &copy; 2005-2006 Dan Moulding</p>
+
+
+<p id="copyright">Copyright &copy; 2005-2009 Dan Moulding</p>
 
 </div> <!-- #content -->
 
diff --git a/development/Win32/vld/include/vld.h b/development/Win32/vld/include/vld.h
deleted file mode 100644 (file)
index c6213de..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-//
-//  Visual Leak Detector - Import Library Header
-//  Copyright (c) 2006 Dan Moulding
-//
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU Lesser General Public
-//  License as published by the Free Software Foundation; either
-//  version 2.1 of the License, or (at your option) any later version.
-//
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
-//
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-//
-//  See COPYING.txt for the full terms of the GNU Lesser General Public License.
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#pragma once
-
-#ifdef VLD_BUILD
-#define VLD_EXPORT __declspec(dllexport)
-#else
-
-#define VLD_EXPORT __declspec(dllimport)
-
-#pragma comment(lib, "vld.lib")
-
-// Force a symbolic reference to the global VisualLeakDetector class object from
-// the DLL. This enusres that the DLL is loaded and linked with the program,
-// even if no code otherwise imports any of the DLL's exports.
-#pragma comment(linker, "/include:__imp_?vld@@3VVisualLeakDetector@@A")
-
-#endif
-
-
-#ifdef _DEBUG
-
-////////////////////////////////////////////////////////////////////////////////
-//
-//  Visual Leak Detector APIs
-//
-
-#ifdef __cplusplus
-extern "C" {
-#endif // __cplusplus
-
-// VLDDisable - Disables Visual Leak Detector's memory leak detection at
-//   runtime. If memory leak detection is already disabled, then calling this
-//   function has no effect.
-//
-//  Note: In multithreaded programs, this function operates on a per-thread
-//    basis. In other words, if you call this function from one thread, then
-//    memory leak detection is only disabled for that thread. If memory leak
-//    detection is enabled for other threads, then it will remain enabled for
-//    those other threads. It was designed to work this way to insulate you,
-//    the programmer, from having to ensure thread synchronization when calling
-//    VLDEnable() and VLDDisable(). Without this, calling these two functions
-//    unsychronized could result in unpredictable and unintended behavior.
-//    But this also means that if you want to disable memory leak detection
-//    process-wide, then you need to call this function from every thread in
-//    the process.
-//
-//  Return Value:
-//
-//    None.
-//
-VLD_EXPORT void VLDDisable ();
-
-// VLDEnable - Enables Visual Leak Detector's memory leak detection at runtime.
-//   If memory leak detection is already enabled, which it is by default, then
-//   calling this function has no effect.
-//
-//  Note: In multithreaded programs, this function operates on a per-thread
-//    basis. In other words, if you call this function from one thread, then
-//    memory leak detection is only enabled for that thread. If memory leak
-//    detection is disabled for other threads, then it will remain disabled for
-//    those other threads. It was designed to work this way to insulate you,
-//    the programmer, from having to ensure thread synchronization when calling
-//    VLDEnable() and VLDDisable(). Without this, calling these two functions
-//    unsychronized could result in unpredictable and unintended behavior.
-//    But this also means that if you want to enable memory leak detection
-//    process-wide, then you need to call this function from every thread in
-//    the process.
-//
-//  Return Value:
-//
-//    None.
-//
-VLD_EXPORT void VLDEnable ();
-
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#else // !_DEBUG
-
-#define VLDEnable()
-#define VLDDisable()
-
-#endif // _DEBUG
index 70576941b779f936ddba175483df0d377919ba7a..7bcbe5829ff8d3183303ea805a26c9e687e30608 100644 (file)
@@ -1,8 +1,7 @@
 ////////////////////////////////////////////////////////////////////////////////
-//  $Id: callstack.cpp,v 1.20 2006/11/18 03:12:34 dmouldin Exp $
 //
 //  Visual Leak Detector - CallStack Class Implementations
-//  Copyright (c) 2005-2006 Dan Moulding
+//  Copyright (c) 2005-2009 Dan Moulding
 //
 //  This library is free software; you can redistribute it and/or
 //  modify it under the terms of the GNU Lesser General Public
@@ -24,7 +23,9 @@
 
 #include <cassert>
 #include <windows.h>
+#ifndef __out_xcount
 #define __out_xcount(x) // Workaround for the specstrings.h bug in the Platform SDK.
+#endif
 #define DBGHELP_TRANSLATE_TCHAR
 #include <dbghelp.h>    // Provides symbol handling services.
 #define VLDBUILD
index b4d3d669a13f4914547b136d892aef94eaa7e6c2..e17a530a89b39307e8d74cc95fcd31988ff0fb4b 100644 (file)
@@ -1,5 +1,4 @@
 ////////////////////////////////////////////////////////////////////////////////
-//  $Id: callstack.h,v 1.10 2006/11/18 03:12:34 dmouldin Exp $
 //
 //  Visual Leak Detector - CallStack Class Definitions
 //  Copyright (c) 2005-2006 Dan Moulding
@@ -114,4 +113,4 @@ class SafeCallStack : public CallStack
 {
 public:
     VOID getstacktrace (UINT32 maxdepth, SIZE_T *framepointer);
-};
\ No newline at end of file
+};
diff --git a/development/Win32/vld/src/crtmfcpatch.h b/development/Win32/vld/src/crtmfcpatch.h
new file mode 100644 (file)
index 0000000..addcacd
--- /dev/null
@@ -0,0 +1,965 @@
+////////////////////////////////////////////////////////////////////////////////\r
+//\r
+//  Visual Leak Detector - CRT and MFC IAT Patch Functions Header\r
+//  Copyright (c) 2009 Dan Moulding\r
+//\r
+//  This library is free software; you can redistribute it and/or\r
+//  modify it under the terms of the GNU Lesser General Public\r
+//  License as published by the Free Software Foundation; either\r
+//  version 2.1 of the License, or (at your option) any later version.\r
+//\r
+//  This library is distributed in the hope that it will be useful,\r
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+//  Lesser General Public License for more details.\r
+//\r
+//  You should have received a copy of the GNU Lesser General Public\r
+//  License along with this library; if not, write to the Free Software\r
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
+//\r
+//  See COPYING.txt for the full terms of the GNU Lesser General Public License.\r
+//\r
+////////////////////////////////////////////////////////////////////////////////\r
+\r
+#pragma once\r
+\r
+#ifndef VLDBUILD\r
+#error \\r
+"This header should only be included by Visual Leak Detector when building it from source. \\r
+Applications should never include this header."\r
+#endif\r
+\r
+#include "vldint.h"\r
+extern __declspec(dllexport) VisualLeakDetector vld;\r
+\r
+#define TEMPLATE_HEADER \\r
+template<wchar_t const *crtddll, wchar_t const *mfcddll, wchar_t const *mfcuddll,\\r
+    char const *crtd_vector_new_name, char const *crtd_vector_new_dbg_name,\\r
+    char const *crtd_scalar_new_name, char const *crtd_scalar_new_dbg_name,\\r
+    int mfcd_vector_new_ordinal, int mfcd_vector_new_dbg_4p_ordinal, int mfcd_vector_new_dbg_3p_ordinal,\\r
+    int mfcd_scalar_new_ordinal, int mfcd_scalar_new_dbg_4p_ordinal, int mfcd_scalar_new_dbg_3p_ordinal,\\r
+    int mfcud_vector_new_ordinal, int mfcud_vector_new_dbg_4p_ordinal, int mfcud_vector_new_dbg_3p_ordinal,\\r
+    int mfcud_scalar_new_ordinal, int mfcud_scalar_new_dbg_4p_ordinal, int mfcud_scalar_new_dbg_3p_ordinal>\r
+\r
+#define TEMPLATE_ARGS \\r
+    crtddll, mfcddll, mfcuddll,\\r
+    crtd_vector_new_name, crtd_vector_new_dbg_name,\\r
+    crtd_scalar_new_name, crtd_scalar_new_dbg_name,\\r
+    mfcd_vector_new_ordinal, mfcd_vector_new_dbg_4p_ordinal, mfcd_vector_new_dbg_3p_ordinal,\\r
+    mfcd_scalar_new_ordinal, mfcd_scalar_new_dbg_4p_ordinal, mfcd_scalar_new_dbg_3p_ordinal,\\r
+    mfcud_vector_new_ordinal, mfcud_vector_new_dbg_4p_ordinal, mfcud_vector_new_dbg_3p_ordinal,\\r
+    mfcud_scalar_new_ordinal, mfcud_scalar_new_dbg_4p_ordinal, mfcud_scalar_new_dbg_3p_ordinal\r
+\r
+TEMPLATE_HEADER\r
+class CrtMfcPatch\r
+{\r
+public:\r
+    static void* __cdecl crtd__calloc_dbg (size_t num, size_t size, int type, char const *file, int line);\r
+    static void* __cdecl crtd__malloc_dbg (size_t size, int type, const char *file, int line);\r
+    static void* __cdecl crtd__realloc_dbg (void *mem, size_t size, int type, char const *file, int line);\r
+    static void* __cdecl crtd__scalar_new_dbg (size_t size, int type, char const *file, int line);\r
+    static void* __cdecl crtd__vector_new_dbg (size_t size, int type, char const *file, int line);\r
+    static void* __cdecl crtd_calloc (size_t num, size_t size);\r
+    static void* __cdecl crtd_malloc (size_t size);\r
+    static void* __cdecl crtd_realloc (void *mem, size_t size);\r
+    static void* __cdecl crtd_scalar_new (size_t size);\r
+    static void* __cdecl crtd_vector_new (size_t size);\r
+\r
+    template<char const *procname>\r
+    static void* __cdecl crtd_new_dbg (SIZE_T fp, size_t size, int type, char const *file, int line);\r
+    template<char const *procname>\r
+    static void* __cdecl crtd_new (SIZE_T fp, size_t size);\r
+\r
+    static void* __cdecl mfcd_vector_new (size_t size);\r
+    static void* __cdecl mfcd__vector_new_dbg_4p (size_t size, int type, char const *file, int line);\r
+    static void* __cdecl mfcd__vector_new_dbg_3p (size_t size, char const *file, int line);\r
+    static void* __cdecl mfcd_scalar_new (size_t size);\r
+    static void* __cdecl mfcd__scalar_new_dbg_4p (size_t size, int type, char const *file, int line);\r
+    static void* __cdecl mfcd__scalar_new_dbg_3p (size_t size, char const *file, int line);\r
+    static void* __cdecl mfcud_vector_new (size_t size);\r
+    static void* __cdecl mfcud__vector_new_dbg_4p (size_t size, int type, char const *file, int line);\r
+    static void* __cdecl mfcud__vector_new_dbg_3p (size_t size, char const *file, int line);\r
+    static void* __cdecl mfcud_scalar_new (size_t size);\r
+    static void* __cdecl mfcud__scalar_new_dbg_4p (size_t size, int type, char const *file, int line);\r
+    static void* __cdecl mfcud__scalar_new_dbg_3p (size_t size, char const *file, int line);\r
+\r
+    template<wchar_t const *mfcdll, int ordinal>\r
+    static void* __cdecl mfcd_new_dbg (SIZE_T fp, size_t size, int type, char const *file, int line);\r
+    template<wchar_t const *mfcdll, int ordinal>\r
+    static void* __cdecl mfcd_new_dbg (SIZE_T fp, size_t size, char const *file, int line);\r
+    template<wchar_t const *mfcdll, int ordinal>\r
+    static void* __cdecl mfcd_new (SIZE_T fp, size_t size);\r
+};\r
+\r
+\r
+////////////////////////////////////////////////////////////////////////////////\r
+//\r
+// Visual Studio DLLs\r
+//\r
+////////////////////////////////////////////////////////////////////////////////\r
+\r
+// crtd__calloc_dbg - Calls to _calloc_dbg from msvcrXXd.dll are patched\r
+//   through to this function.\r
+//\r
+//  - mem (IN): Pointer to the memory block to be reallocated.\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  - type (IN): The CRT "use type" of the block to be allocated.\r
+//\r
+//  - file (IN): The name of the file from which this function is being called.\r
+//\r
+//  - line (IN): The line number, in the above file, at which this function is\r
+//      being called.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by _calloc_dbg.\r
+//\r
+TEMPLATE_HEADER\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::crtd__calloc_dbg (size_t      num,\r
+                                                    size_t      size,\r
+                                                    int         type,\r
+                                                    char const *file,\r
+                                                    int         line)\r
+{\r
+    static _calloc_dbg_t pcrtxxd__calloc_dbg = NULL;\r
+\r
+    SIZE_T  fp;\r
+    HMODULE msvcrxxd;\r
+\r
+    FRAMEPOINTER(fp);\r
+\r
+    if (pcrtxxd__calloc_dbg == NULL) {\r
+        // This is the first call to this function. Link to the real\r
+        // _calloc_dbg.\r
+        msvcrxxd = GetModuleHandle(crtddll);\r
+        pcrtxxd__calloc_dbg = (_calloc_dbg_t)GetProcAddress(msvcrxxd, "_calloc_dbg");\r
+    }\r
+\r
+    return vld.__calloc_dbg(pcrtxxd__calloc_dbg, fp, num, size, type, file, line);\r
+}\r
+\r
+// crtd__malloc_dbg - Calls to _malloc_dbg from msvcrXXd.dll are patched\r
+//   through to this function.\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  - type (IN): The CRT "use type" of the block to be allocated.\r
+//\r
+//  - file (IN): The name of the file from which this function is being called.\r
+//\r
+//  - line (IN): The line number, in the above file, at which this function is\r
+//      being called.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by _malloc_dbg.\r
+//\r
+TEMPLATE_HEADER\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::crtd__malloc_dbg (size_t      size,\r
+                                                    int         type,\r
+                                                    char const *file,\r
+                                                    int         line)\r
+{\r
+    static _malloc_dbg_t pcrtxxd__malloc_dbg = NULL;\r
+\r
+    SIZE_T  fp;\r
+    HMODULE msvcrxxd;\r
+\r
+    FRAMEPOINTER(fp);\r
+\r
+    if (pcrtxxd__malloc_dbg == NULL) {\r
+        // This is the first call to this function. Link to the real\r
+        // _malloc_dbg.\r
+        msvcrxxd = GetModuleHandle(crtddll);\r
+        pcrtxxd__malloc_dbg = (_malloc_dbg_t)GetProcAddress(msvcrxxd, "_malloc_dbg");\r
+    }\r
+\r
+    return vld.__malloc_dbg(pcrtxxd__malloc_dbg, fp, size, type, file, line);\r
+}\r
+\r
+// crtd__realloc_dbg - Calls to _realloc_dbg from msvcrXXd.dll are patched\r
+//   through to this function.\r
+//\r
+//  - mem (IN): Pointer to the memory block to be reallocated.\r
+//\r
+//  - size (IN): The size of the memory block to reallocate.\r
+//\r
+//  - type (IN): The CRT "use type" of the block to be reallocated.\r
+//\r
+//  - file (IN): The name of the file from which this function is being called.\r
+//\r
+//  - line (IN): The line number, in the above file, at which this function is\r
+//      being called.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by _realloc_dbg.\r
+//\r
+TEMPLATE_HEADER\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::crtd__realloc_dbg (void       *mem,\r
+                                                     size_t     size,\r
+                                                     int        type,\r
+                                                     char const *file,\r
+                                                     int        line)\r
+{\r
+    static _realloc_dbg_t pcrtxxd__realloc_dbg = NULL;\r
+\r
+    SIZE_T fp;\r
+    HMODULE msvcrxxd;\r
+\r
+    FRAMEPOINTER(fp);\r
+\r
+    if (pcrtxxd__realloc_dbg == NULL) {\r
+        // This is the first call to this function. Link to the real\r
+        // _realloc_dbg.\r
+        msvcrxxd = GetModuleHandle(crtddll);\r
+        pcrtxxd__realloc_dbg = (_realloc_dbg_t)GetProcAddress(msvcrxxd, "_realloc_dbg");\r
+    }\r
+\r
+    return vld.__realloc_dbg(pcrtxxd__realloc_dbg, fp, mem, size, type, file, line);\r
+}\r
+\r
+// crtd__scalar_new_dbg - Calls to the CRT's debug scalar new operator from\r
+//   msvcrXXd.dll are patched through to this function.\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  - type (IN): The CRT "use type" of the block to be allocated.\r
+//\r
+//  - file (IN): The name of the file from which this function is being called.\r
+//\r
+//  - line (IN): The line number, in the above file, at which this function is\r
+//      being called.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by the CRT debug scalar new operator.\r
+//\r
+TEMPLATE_HEADER\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::crtd__scalar_new_dbg (size_t      size,\r
+                                                        int         type,\r
+                                                        char const *file,\r
+                                                        int         line)\r
+{\r
+    SIZE_T  fp;\r
+    FRAMEPOINTER(fp);\r
+\r
+    return crtd_new_dbg<crtd_scalar_new_dbg_name>(fp, size, type, file, line);\r
+}\r
+\r
+// crtd__vector_new_dbg - Calls to the CRT's debug vector new operator from\r
+//   msvcrXXd.dll are patched through to this function.\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  - type (IN): The CRT "use type" of the block to be allocated.\r
+//\r
+//  - file (IN): The name of the file from which this function is being called.\r
+//\r
+//  - line (IN): The line number, in the above file, at which this function is\r
+//      being called.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by the CRT debug vector new operator.\r
+//\r
+TEMPLATE_HEADER\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::crtd__vector_new_dbg (size_t      size,\r
+                                                        int         type,\r
+                                                        char const *file,\r
+                                                        int         line)\r
+{\r
+    SIZE_T  fp;\r
+    FRAMEPOINTER(fp);\r
+\r
+    return crtd_new_dbg<crtd_vector_new_dbg_name>(fp, size, type, file, line);\r
+}\r
+\r
+// crtd_calloc - Calls to calloc from msvcrXXd.dll are patched through to\r
+//   this function.\r
+//\r
+//  - dll (IN): The name of the dll\r
+//\r
+//  - num (IN): The number of blocks, of size 'size', to be allocated.\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the valued returned from calloc.\r
+//\r
+TEMPLATE_HEADER\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::crtd_calloc (size_t num, size_t size)\r
+{\r
+    static calloc_t pcrtxxd_calloc = NULL;\r
+\r
+    SIZE_T  fp;\r
+    HMODULE msvcrxxd;\r
+\r
+    FRAMEPOINTER(fp);\r
+\r
+    if (pcrtxxd_calloc == NULL) {\r
+        // This is the first call to this function. Link to the real malloc.\r
+        msvcrxxd = GetModuleHandle(crtddll);\r
+        pcrtxxd_calloc = (calloc_t)GetProcAddress(msvcrxxd, "calloc");\r
+    }\r
+\r
+    return vld._calloc(pcrtxxd_calloc, fp, num, size);\r
+}\r
+\r
+// crtd_malloc - Calls to malloc from msvcrXXd.dll are patched through to\r
+//   this function.\r
+//\r
+//  - dll (IN): The name of the dll\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the valued returned from malloc.\r
+//\r
+TEMPLATE_HEADER\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::crtd_malloc (size_t size)\r
+{\r
+    static malloc_t pcrtxxd_malloc = NULL;\r
+\r
+    SIZE_T  fp;\r
+    HMODULE msvcrxxd;\r
+\r
+    FRAMEPOINTER(fp);\r
+\r
+    if (pcrtxxd_malloc == NULL) {\r
+        // This is the first call to this function. Link to the real malloc.\r
+        msvcrxxd = GetModuleHandle(crtddll);\r
+        pcrtxxd_malloc = (malloc_t)GetProcAddress(msvcrxxd, "malloc");\r
+    }\r
+\r
+    return vld._malloc(pcrtxxd_malloc, fp, size);\r
+}\r
+\r
+// crtd_realloc - Calls to realloc from msvcrXXd.dll are patched through to\r
+//   this function.\r
+//\r
+//  - dll (IN): The name of the dll\r
+//\r
+//  - mem (IN): Pointer to the memory block to reallocate.\r
+//\r
+//  - size (IN): Size of the memory block to reallocate.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned from realloc.\r
+//\r
+TEMPLATE_HEADER\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::crtd_realloc (void *mem, size_t size)\r
+{\r
+    static realloc_t pcrtxxd_realloc = NULL;\r
+\r
+    SIZE_T  fp;\r
+    HMODULE msvcrxxd;\r
+\r
+    FRAMEPOINTER(fp);\r
+\r
+    if (pcrtxxd_realloc == NULL) {\r
+        // This is the first call to this function. Link to the real realloc.\r
+        msvcrxxd = GetModuleHandle(crtddll);\r
+        pcrtxxd_realloc = (realloc_t)GetProcAddress(msvcrxxd, "realloc");\r
+    }\r
+\r
+    return vld._realloc(pcrtxxd_realloc, fp, mem, size);\r
+}\r
+\r
+// crtd_scalar_new - Calls to the CRT's scalar new operator from msvcrXXd.dll\r
+//   are patched through to this function.\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by the CRT scalar new operator.\r
+//\r
+TEMPLATE_HEADER\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::crtd_scalar_new (size_t size)\r
+{\r
+    SIZE_T  fp;\r
+    FRAMEPOINTER(fp);\r
+\r
+    return crtd_new<crtd_scalar_new_name>(fp, size);\r
+}\r
+\r
+// crtd_vector_new - Calls to the CRT's vector new operator from msvcrXXd.dll\r
+//   are patched through to this function.\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by the CRT vector new operator.\r
+//\r
+TEMPLATE_HEADER\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::crtd_vector_new (size_t size)\r
+{\r
+    SIZE_T  fp;\r
+    FRAMEPOINTER(fp);\r
+\r
+    return crtd_new<crtd_vector_new_name>(fp, size);\r
+}\r
+\r
+// crtd_new_dbg - A template function for implementation of patch functions to\r
+//   the CRT's debug new operator from msvcrXXd.dll\r
+//\r
+//  - procname (IN): The debug new operator's name\r
+//\r
+//  - fp (IN): Frame pointer from the call that initiated this allocation.\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  - type (IN): The CRT "use type" of the block to be allocated.\r
+//\r
+//  - file (IN): The name of the file from which this function is being called.\r
+//\r
+//  - line (IN): The line number, in the above file, at which this function is\r
+//      being called.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by the CRT debug new operator.\r
+//\r
+TEMPLATE_HEADER\r
+template<char const *procname>\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::crtd_new_dbg (SIZE_T      fp,\r
+                                                size_t      size,\r
+                                                int         type,\r
+                                                char const *file,\r
+                                                int         line)\r
+{\r
+    static new_dbg_crt_t pcrtxxd_new_dbg = NULL;\r
+\r
+    HMODULE msvcrxxd;\r
+\r
+    if (pcrtxxd_new_dbg == NULL) {\r
+        // This is the first call to this function. Link to the real CRT debug\r
+        // new operator.\r
+        msvcrxxd = GetModuleHandle(crtddll);\r
+        pcrtxxd_new_dbg = (new_dbg_crt_t)GetProcAddress(msvcrxxd, procname);\r
+    }\r
+\r
+    return vld.new_dbg_crt(pcrtxxd_new_dbg, fp, size, type, file, line);\r
+}\r
+\r
+// crt_new - A template function for implementing patch functions to the\r
+//   CRT's new operator from msvcrXXd.dll\r
+//\r
+//  - dll (IN): The name of the dll\r
+//\r
+//  - procname (IN): The debug new operator's name\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by the CRT new operator.\r
+//\r
+TEMPLATE_HEADER\r
+template<char const *procname>\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::crtd_new (SIZE_T fp, size_t size)\r
+{\r
+    static new_t pcrtxxd_scalar_new = NULL;\r
+\r
+    HMODULE msvcrxxd;\r
+\r
+    if (pcrtxxd_scalar_new == NULL) {\r
+        // This is the first call to this function. Link to the real CRT new\r
+        // operator.\r
+        msvcrxxd = GetModuleHandle(crtddll);\r
+        pcrtxxd_scalar_new = (new_t)GetProcAddress(msvcrxxd, procname);\r
+    }\r
+\r
+    return vld._new(pcrtxxd_scalar_new, fp, size);\r
+}\r
+\r
+////////////////////////////////////////////////////////////////////////////////\r
+//\r
+// MFC DLLs\r
+//\r
+////////////////////////////////////////////////////////////////////////////////\r
+\r
+// mfcd__scalar_new_dbg_3p - Calls to the MFC debug scalar new operator from\r
+//   mfcXXd.dll are patched through to this function.\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  - type (IN): The "use type" of the block to be allocated.\r
+//\r
+//  - file (IN): The name of the file from which this function is being called.\r
+//\r
+//  - line (IN): The line number, in the above file, at which this function is\r
+//      being called.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by the MFC debug scalar new operator.\r
+//\r
+TEMPLATE_HEADER\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::mfcd__scalar_new_dbg_4p (size_t       size,\r
+                                                           int          type,\r
+                                                           char const  *file,\r
+                                                           int          line)\r
+{\r
+    SIZE_T  fp;\r
+    FRAMEPOINTER(fp);\r
+\r
+    return mfcd_new_dbg<mfcddll, mfcd_scalar_new_dbg_4p_ordinal>\r
+                       (fp, size, type, file, line);\r
+}\r
+\r
+// mfcd__scalar_new_dbg_3p - Calls to the MFC debug scalar new operator from\r
+//   mfcXXd.dll are patched through to this function.\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  - file (IN): The name of the file from which this function is being called.\r
+//\r
+//  - line (IN): The line number, in the above file, at which this function is\r
+//      being called.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by the MFC debug scalar new operator.\r
+//\r
+TEMPLATE_HEADER\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::mfcd__scalar_new_dbg_3p (size_t       size,\r
+                                                           char const  *file,\r
+                                                           int          line)\r
+{\r
+    SIZE_T  fp;\r
+    FRAMEPOINTER(fp);\r
+\r
+    return mfcd_new_dbg<mfcddll, mfcd_scalar_new_dbg_3p_ordinal>\r
+                       (fp, size, file, line);\r
+}\r
+\r
+// mfcd__vector_new_dbg_4p - Calls to the MFC debug vector new operator from\r
+//   mfcXXd.dll are patched through to this function.\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  - type (IN): The "use type" of the block to be allocated.\r
+//\r
+//  - file (IN): The name of the file from which this function is being called.\r
+//\r
+//  - line (IN): The line number, in the above file, at which this function is\r
+//      being called.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by the MFC debug vector new operator.\r
+//\r
+TEMPLATE_HEADER\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::mfcd__vector_new_dbg_4p (size_t       size,\r
+                                                           int          type,\r
+                                                           char const  *file,\r
+                                                           int          line)\r
+{\r
+    SIZE_T  fp;\r
+    FRAMEPOINTER(fp);\r
+\r
+    return mfcd_new_dbg<mfcddll, mfcd_vector_new_dbg_4p_ordinal>\r
+                       (fp, size, type, file, line);\r
+}\r
+\r
+// mfcd__vector_new_dbg_3p - Calls to the MFC debug vector new operator from\r
+//   mfcXXd.dll are patched through to this function.\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  - file (IN): The name of the file from which this function is being called.\r
+//\r
+//  - line (IN): The line number, in the above file, at which this function is\r
+//      being called.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by the MFC debug vector new operator.\r
+//\r
+TEMPLATE_HEADER\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::mfcd__vector_new_dbg_3p (size_t       size,\r
+                                                           char const  *file,\r
+                                                           int          line)\r
+{\r
+    SIZE_T  fp;\r
+    FRAMEPOINTER(fp);\r
+\r
+    return mfcd_new_dbg<mfcddll, mfcd_vector_new_dbg_3p_ordinal>\r
+                       (fp, size, file, line);\r
+}\r
+\r
+// mfcd_scalar_new - Calls to the MFC scalar new operator from mfcXXd.dll are\r
+//   patched through to this function.\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by the MFC scalar new operator.\r
+//\r
+TEMPLATE_HEADER\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::mfcd_scalar_new (size_t size)\r
+{\r
+    SIZE_T  fp;\r
+    FRAMEPOINTER(fp);\r
+\r
+    return mfcd_new<mfcddll, mfcd_scalar_new_ordinal>(fp, size);\r
+}\r
+\r
+// mfcd_vector_new - Calls to the MFC vector new operator from mfcXXd.dll are\r
+//   patched through to this function.\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by the MFC vector new operator.\r
+//\r
+TEMPLATE_HEADER\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::mfcd_vector_new (size_t size)\r
+{\r
+    SIZE_T  fp;\r
+    FRAMEPOINTER(fp);\r
+\r
+    return mfcd_new<mfcddll, mfcd_vector_new_ordinal>(fp, size);\r
+}\r
+\r
+// mfcud__scalar_new_dbg_4p - Calls to the MFC debug scalar new operator from\r
+//   mfcXXud.dll are patched through to this function.\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  - type (IN): The "use type" of the block to be allocated.\r
+//\r
+//  - file (IN): The name of the file from which this function is being called.\r
+//\r
+//  - line (IN): The line number, in the above file, at which this function is\r
+//      being called.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by the MFC debug scalar new operator.\r
+//\r
+TEMPLATE_HEADER\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::mfcud__scalar_new_dbg_4p (size_t      size,\r
+                                                            int         type,\r
+                                                            char const *file,\r
+                                                            int         line)\r
+{\r
+    SIZE_T  fp;\r
+    FRAMEPOINTER(fp);\r
+\r
+    return mfcd_new_dbg<mfcuddll, mfcud_scalar_new_dbg_4p_ordinal>\r
+                       (fp, size, type, file, line);\r
+}\r
+\r
+// mfcud__scalar_new_dbg_3p - Calls to the MFC debug scalar new operator from\r
+//   mfcXXud.dll are patched through to this function.\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  - file (IN): The name of the file from which this function is being called.\r
+//\r
+//  - line (IN): The line number, in the above file, at which this function is\r
+//      being called.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by the MFC debug scalar new operator.\r
+//\r
+TEMPLATE_HEADER\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::mfcud__scalar_new_dbg_3p (size_t      size,\r
+                                                            char const *file,\r
+                                                            int         line)\r
+{\r
+    SIZE_T  fp;\r
+    FRAMEPOINTER(fp);\r
+\r
+    return mfcd_new_dbg<mfcuddll, mfcud_scalar_new_dbg_3p_ordinal>\r
+                       (fp, size, file, line);\r
+}\r
+\r
+// mfcud__vector_new_dbg_4p - Calls to the MFC debug vector new operator from\r
+//   mfcXXud.dll are patched through to this function.\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  - type (IN): The "use type" of the block to be allocated.\r
+//\r
+//  - file (IN): The name of the file from which this function is being called.\r
+//\r
+//  - line (IN): The line number, in the above file, at which this function is\r
+//      being called.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by the MFC debug vector new operator.\r
+//\r
+TEMPLATE_HEADER\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::mfcud__vector_new_dbg_4p (size_t      size,\r
+                                                            int         type,\r
+                                                            char const *file,\r
+                                                            int         line)\r
+{\r
+    SIZE_T  fp;\r
+    FRAMEPOINTER(fp);\r
+\r
+    return mfcd_new_dbg<mfcuddll, mfcud_vector_new_dbg_4p_ordinal>\r
+                       (fp, size, type, file, line);\r
+}\r
+\r
+// mfcud__vector_new_dbg_3p - Calls to the MFC debug vector new operator from\r
+//   mfcXXud.dll are patched through to this function.\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  - file (IN): The name of the file from which this function is being called.\r
+//\r
+//  - line (IN): The line number, in the above file, at which this function is\r
+//      being called.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by the MFC debug vector new operator.\r
+//\r
+TEMPLATE_HEADER\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::mfcud__vector_new_dbg_3p (size_t      size,\r
+                                                            char const *file,\r
+                                                            int         line)\r
+{\r
+    SIZE_T  fp;\r
+    FRAMEPOINTER(fp);\r
+\r
+    return mfcd_new_dbg<mfcuddll, mfcud_vector_new_dbg_3p_ordinal>\r
+                       (fp, size, file, line);\r
+}\r
+\r
+// mfcud_scalar_new - Calls to the MFC scalar new operator from mfcXXud.dll are\r
+//   patched through to this function.\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by the MFC scalar new operator.\r
+//\r
+TEMPLATE_HEADER\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::mfcud_scalar_new (size_t size)\r
+{\r
+    SIZE_T  fp;\r
+    FRAMEPOINTER(fp);\r
+\r
+    return mfcd_new<mfcuddll, mfcud_scalar_new_ordinal>(fp, size);\r
+}\r
+\r
+// mfcud_vector_new - Calls to the MFC vector new operator from mfcXXud.dll are\r
+//   patched through to this function.\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by the MFC vector new operator.\r
+//\r
+TEMPLATE_HEADER\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::mfcud_vector_new (size_t size)\r
+{\r
+    SIZE_T  fp;\r
+    FRAMEPOINTER(fp);\r
+\r
+    return mfcd_new<mfcuddll, mfcud_vector_new_ordinal>(fp, size);\r
+}\r
+\r
+// mfcd_new_dbg - A generic function for implementing patch functions to the MFC\r
+//   debug new operators:\r
+//   void* __cdecl operator new[](size_t size, int type, char const *file, int line)\r
+//   void* __cdecl operator new(size_t size, int type, char const *file, int line)\r
+//\r
+//  - mfcdll (IN): The name of the MFC DLL\r
+//\r
+//  - ordinal (IN): The debug new operator's ordinal value\r
+//\r
+//  - type (IN): The "use type" of the block to be allocated.\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  - file (IN): The name of the file from which this function is being called.\r
+//\r
+//  - line (IN): The line number, in the above file, at which this function is\r
+//      being called.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by the MFC debug new operator.\r
+//\r
+TEMPLATE_HEADER\r
+template<wchar_t const *mfcdll, int ordinal>\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::mfcd_new_dbg (SIZE_T      fp,\r
+                                                size_t      size,\r
+                                                int         type,\r
+                                                char const *file,\r
+                                                int         line)\r
+{\r
+    static new_dbg_crt_t pmfcxxd__new_dbg = NULL;\r
+\r
+    HMODULE mfcxxd;\r
+\r
+    if (pmfcxxd__new_dbg == NULL) {\r
+        // This is the first call to this function. Link to the real MFC debug\r
+        // new operator.\r
+        mfcxxd = GetModuleHandle(mfcdll);\r
+        pmfcxxd__new_dbg = (new_dbg_crt_t)GetProcAddress(mfcxxd, (LPCSTR)ordinal);\r
+    }\r
+\r
+    return vld.new_dbg_mfc(pmfcxxd__new_dbg, fp, size, type, file, line);\r
+}\r
+\r
+// mfcd_new_dbg - A generic function for implementing patch functions to the MFC\r
+//   debug new operators:\r
+//   void* __cdecl operator new[](size_t size, char const *file, int line)\r
+//   void* __cdecl operator new(size_t size, char const *file, int line)\r
+//\r
+//  - mfcdll (IN): The name of the MFC DLL\r
+//\r
+//  - ordinal (IN): The debug new operator's ordinal value\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  - file (IN): The name of the file from which this function is being called.\r
+//\r
+//  - line (IN): The line number, in the above file, at which this function is\r
+//      being called.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by the MFC debug new operator.\r
+//\r
+TEMPLATE_HEADER\r
+template<wchar_t const *mfcdll, int ordinal>\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::mfcd_new_dbg (SIZE_T      fp,\r
+                                                size_t      size,\r
+                                                char const *file,\r
+                                                int         line)\r
+{\r
+    static new_dbg_mfc_t pmfcxxd__new_dbg = NULL;\r
+\r
+    HMODULE mfcxxd;\r
+\r
+    if (pmfcxxd__new_dbg == NULL) {\r
+        // This is the first call to this function. Link to the real MFC debug\r
+        // new operator.\r
+        mfcxxd = GetModuleHandle(mfcdll);\r
+        pmfcxxd__new_dbg = (new_dbg_mfc_t)GetProcAddress(mfcxxd, (LPCSTR)ordinal);\r
+    }\r
+\r
+    return vld.new_dbg_mfc(pmfcxxd__new_dbg, fp, size, file, line);\r
+}\r
+\r
+// mfcd_new - A generic function for implementing patch functions to the MFC new\r
+//   operators.\r
+//\r
+//  - mfcdll (IN): The name of the MFC DLL\r
+//\r
+//  - ordinal (IN): The new operator's ordinal value\r
+//\r
+//  - size (IN): The size, in bytes, of the memory block to be allocated.\r
+//\r
+//  Return Value:\r
+//\r
+//    Returns the value returned by the MFC new operator.\r
+//\r
+TEMPLATE_HEADER\r
+template<wchar_t const *mfcdll, int ordinal>\r
+void* CrtMfcPatch<TEMPLATE_ARGS>::mfcd_new (SIZE_T fp, size_t size)\r
+{\r
+    static new_t pmfcxxd_new = NULL;\r
+\r
+    HMODULE mfcxxd;\r
+\r
+    if (pmfcxxd_new == NULL) {\r
+        // This is the first call to this function. Link to the real CRT new\r
+        // operator.\r
+        mfcxxd = GetModuleHandle(mfcdll);\r
+        pmfcxxd_new = (new_t)GetProcAddress(mfcxxd, (LPCSTR)ordinal);\r
+    }\r
+\r
+    return vld._new(pmfcxxd_new, fp, size);\r
+}\r
+\r
+#undef TEMPLATE_HEADER\r
+#undef TEMPLATE_ARGS\r
+\r
+const extern char    scalar_new_dbg_name[] = "??2@YAPAXIHPBDH@Z";\r
+const extern char    vector_new_dbg_name[] = "??_U@YAPAXIHPBDH@Z";\r
+const extern char    scalar_new_name[] = "??2@YAPAXI@Z";\r
+const extern char    vector_new_name[] = "??_U@YAPAXI@Z";\r
+const extern wchar_t msvcrtd_dll[]  = L"msvcrtd.dll";\r
+const extern wchar_t mfc42d_dll[]   = L"mfc42d.dll";\r
+const extern wchar_t mfc42ud_dll[]  = L"mfc42ud.dll";\r
+const extern wchar_t msvcr70d_dll[] = L"msvcr70d.dll";\r
+const extern wchar_t mfc70d_dll[]   = L"mfc70d.dll";\r
+const extern wchar_t mfc70ud_dll[]  = L"mfc70ud.dll";\r
+const extern wchar_t msvcr71d_dll[] = L"msvcr71d.dll";\r
+const extern wchar_t mfc71d_dll[]   = L"mfc71d.dll";\r
+const extern wchar_t mfc71ud_dll[]  = L"mfc71ud.dll";\r
+const extern wchar_t msvcr80d_dll[] = L"msvcr80d.dll";\r
+const extern wchar_t mfc80d_dll[]   = L"mfc80d.dll";\r
+const extern wchar_t mfc80ud_dll[]  = L"mfc80ud.dll";\r
+const extern wchar_t msvcr90d_dll[] = L"msvcr90d.dll";\r
+const extern wchar_t mfc90d_dll[]   = L"mfc90d.dll";\r
+const extern wchar_t mfc90ud_dll[]  = L"mfc90ud.dll";\r
+const extern wchar_t msvcr100d_dll[] = L"msvcr100d.dll";\r
+const extern wchar_t mfc100d_dll[]   = L"mfc100d.dll";\r
+const extern wchar_t mfc100ud_dll[]  = L"mfc100ud.dll";\r
+\r
+// Visual Studio 6.0\r
+typedef CrtMfcPatch<msvcrtd_dll, mfc42d_dll, mfc42ud_dll,\r
+                    vector_new_name, vector_new_dbg_name,\r
+                    scalar_new_name, scalar_new_dbg_name,\r
+                    0, 0, 0, 711, 712, 714,\r
+                    0, 0, 0, 711, 712, 714>\r
+        VS60;\r
+// Visual Studio .NET 2002\r
+typedef CrtMfcPatch<msvcr70d_dll, mfc70d_dll, mfc70ud_dll,\r
+                    vector_new_name, vector_new_dbg_name,\r
+                    scalar_new_name, scalar_new_dbg_name,\r
+                    257, 258, 259, 832, 833, 834,\r
+                    258, 259, 260, 833, 834, 835>\r
+        VS70;\r
+// Visual Studio .NET 2003\r
+typedef CrtMfcPatch<msvcr71d_dll, mfc71d_dll, mfc71ud_dll,\r
+                    vector_new_name, vector_new_dbg_name,\r
+                    scalar_new_name, scalar_new_dbg_name,\r
+                    267, 268, 269, 893, 894, 895,\r
+                    267, 268, 269, 893, 894, 895>\r
+        VS71;\r
+// Visual Studio 2005\r
+typedef CrtMfcPatch<msvcr80d_dll, mfc80d_dll, mfc80ud_dll,\r
+                    vector_new_name, vector_new_dbg_name,\r
+                    scalar_new_name, scalar_new_dbg_name,\r
+                    267, 268, 269, 893, 894, 895,\r
+                    267, 268, 269, 893, 894, 895>\r
+        VS80;\r
+// Visual Studio 2008\r
+typedef CrtMfcPatch<msvcr90d_dll, mfc90d_dll, mfc90ud_dll,\r
+                    vector_new_name, vector_new_dbg_name,\r
+                    scalar_new_name, scalar_new_dbg_name,\r
+                    267, 268, 269, 931, 932, 933,\r
+                    267, 268, 269, 935, 936, 937>\r
+        VS90;\r
+\r
+// Visual Studio 2010\r
+typedef CrtMfcPatch<msvcr100d_dll, mfc100d_dll, mfc100ud_dll,\r
+                    vector_new_name, vector_new_dbg_name,\r
+                                       scalar_new_name, scalar_new_dbg_name,\r
+                                       267, 268, 269, 1405, 1406, 1407,\r
+                                       267, 268, 269, 1412, 1413, 1414>\r
+        VS100;
\ No newline at end of file
index 8f065494bda41de18b8cb1c62425a5adc6359e46..c1c8b137f29e8ef0d67c0cfc6f129a80f68109ac 100644 (file)
@@ -1,5 +1,4 @@
 ////////////////////////////////////////////////////////////////////////////////
-//  $Id: map.h,v 1.10 2006/11/18 03:12:34 dmouldin Exp $
 //
 //  Visual Leak Detector - Lightweight STL-like Map Template
 //  Copyright (c) 2006 Dan Moulding
index 278d72278799989c9fdad661c2b11ed74dc85741..e07d1b4942acae936ad8cf2f37fce78463961229 100644 (file)
@@ -1,5 +1,4 @@
 ////////////////////////////////////////////////////////////////////////////////
-//  $Id: ntapi.cpp,v 1.7 2006/11/18 03:12:34 dmouldin Exp $
 //
 //  Visual Leak Detector - Global NT API Function Pointers
 //  Copyright (c) 2006 Dan Moulding
@@ -30,4 +29,4 @@
 LdrLoadDll_t        LdrLoadDll;
 RtlAllocateHeap_t   RtlAllocateHeap;
 RtlFreeHeap_t       RtlFreeHeap;
-RtlReAllocateHeap_t RtlReAllocateHeap;
\ No newline at end of file
+RtlReAllocateHeap_t RtlReAllocateHeap;
index 26add1e8da69786f7d9b4f0c14031c252bd9a198..6d7ad67e63e71842cc42fae50bfad2f096c55a3f 100644 (file)
@@ -1,8 +1,7 @@
 ////////////////////////////////////////////////////////////////////////////////
-//  $Id: ntapi.h,v 1.8 2006/11/18 03:12:35 dmouldin Exp $
 //
 //  Visual Leak Detector - NT API Definitions
-//  Copyright (c) 2006 Dan Moulding
+//  Copyright (c) 2006-2009 Dan Moulding
 //
 //  This library is free software; you can redistribute it and/or
 //  modify it under the terms of the GNU Lesser General Public
@@ -33,7 +32,7 @@ Applications should never include this header."
 #include <windows.h>
 
 // Return code type used by LdrLoadDll.
-typedef ULONG NTSTATUS;
+typedef LONG NTSTATUS;
 #define   STATUS_SUCCESS 0
 
 // Unicode string structure used by NT APIs.
diff --git a/development/Win32/vld/src/resource.h b/development/Win32/vld/src/resource.h
new file mode 100644 (file)
index 0000000..c6b72e6
--- /dev/null
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}\r
+// Microsoft Visual C++ generated include file.\r
+// Used by vld.rc\r
+\r
+// Next default values for new objects\r
+// \r
+#ifdef APSTUDIO_INVOKED\r
+#ifndef APSTUDIO_READONLY_SYMBOLS\r
+#define _APS_NEXT_RESOURCE_VALUE        101\r
+#define _APS_NEXT_COMMAND_VALUE         40001\r
+#define _APS_NEXT_CONTROL_VALUE         1001\r
+#define _APS_NEXT_SYMED_VALUE           101\r
+#endif\r
+#endif\r
index cfab1b163cc609c7cd7db413e9d7d6ce5d99c4cf..fdeba5c60468822f9a571b27827daad9c986faf9 100644 (file)
@@ -1,5 +1,4 @@
 ////////////////////////////////////////////////////////////////////////////////
-//  $Id: set.h,v 1.9 2006/11/18 03:12:35 dmouldin Exp $
 //
 //  Visual Leak Detector - Lightweight STL-like Set Template
 //  Copyright (c) 2006 Dan Moulding
index 766104ee8e77c05ef7e96ebb9bad0385a3d4c8ea..ca1680f998b113d551b0bbfdb9297284f3e0f63a 100644 (file)
@@ -1,5 +1,4 @@
 ////////////////////////////////////////////////////////////////////////////////
-//  $Id: tree.h,v 1.13 2006/11/18 03:12:35 dmouldin Exp $
 //
 //  Visual Leak Detector - Red-black Tree Template
 //  Copyright (c) 2005-2006 Dan Moulding
index e2fbddd6d7b4655eb363c170fe8d37589dc477c6..3048ba29326a95234d81f56409595b4b89e726fe 100644 (file)
@@ -1,8 +1,7 @@
 ////////////////////////////////////////////////////////////////////////////////
-//  $Id: utility.cpp,v 1.24 2006/11/18 03:12:35 dmouldin Exp $
 //
 //  Visual Leak Detector - Various Utility Functions
-//  Copyright (c) 2005-2006 Dan Moulding
+//  Copyright (c) 2005-2009 Dan Moulding
 //
 //  This library is free software; you can redistribute it and/or
 //  modify it under the terms of the GNU Lesser General Public
 #include <cassert>
 #include <cstdio>
 #include <windows.h>
+#if _WIN32_WINNT > 0x0600 // Windows XP or earlier, no GetProcessIdOfThread()
+#include <winternl.h>
+#endif
+#ifndef __out_xcount
 #define __out_xcount(x) // Workaround for the specstrings.h bug in the Platform SDK.
+#endif
 #define DBGHELP_TRANSLATE_TCHAR
 #include <dbghelp.h>    // Provides portable executable (PE) image access functions.
 #define VLDBUILD        // Declares that we are building Visual Leak Detector.
@@ -779,3 +783,58 @@ BOOL strtobool (LPCWSTR s) {
         return FALSE;
     }
 }
+
+// _GetProcessIdOfThread - Returns the ID of the process owns the thread.
+//
+//  - thread (IN): The handle to the thread.
+//
+//  Return Value:
+//
+//    Returns the ID of the process that owns the thread. Otherwise returns 0.
+//
+DWORD _GetProcessIdOfThread (HANDLE thread)
+{
+    typedef struct _CLIENT_ID {
+        HANDLE UniqueProcess;
+        HANDLE UniqueThread;
+    } CLIENT_ID, *PCLIENT_ID;
+
+    typedef LONG NTSTATUS;
+    typedef LONG KPRIORITY;
+
+    typedef struct _THREAD_BASIC_INFORMATION {
+        NTSTATUS  ExitStatus;
+        PVOID     TebBaseAddress;
+        CLIENT_ID ClientId;
+        KAFFINITY AffinityMask;
+        KPRIORITY Priority;
+        KPRIORITY BasePriority;
+    } THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;
+
+    const static THREADINFOCLASS ThreadBasicInformation = (THREADINFOCLASS)0;
+
+    typedef NTSTATUS (WINAPI *PNtQueryInformationThread) (HANDLE thread,
+                THREADINFOCLASS infoclass, PVOID buffer, ULONG buffersize,
+                PULONG used);
+
+    static PNtQueryInformationThread NtQueryInformationThread = NULL;
+
+    THREAD_BASIC_INFORMATION tbi;
+    NTSTATUS status;
+    HMODULE  ntdll;
+    if (NtQueryInformationThread == NULL) {
+        ntdll = GetModuleHandle(L"ntdll.dll");
+        NtQueryInformationThread = (PNtQueryInformationThread)GetProcAddress(ntdll, "NtQueryInformationThread");
+        if (NtQueryInformationThread == NULL) {
+            return 0;
+        }
+    }
+
+    status = NtQueryInformationThread(thread, ThreadBasicInformation, &tbi, sizeof(tbi), NULL);
+    if(status < 0) {
+        // Shall we go through all the trouble of setting last error?
+        return 0;
+    }
+
+    return (DWORD)tbi.ClientId.UniqueProcess;
+}
index 2c85b9255d8d7f9efcc2f890fd06dc012e3a0919..ac9f348a9174dd79c6ecd79bc54ec8245741fe82 100644 (file)
@@ -1,5 +1,4 @@
 ////////////////////////////////////////////////////////////////////////////////
-//  $Id: utility.h,v 1.19 2006/11/18 03:12:35 dmouldin Exp $
 //
 //  Visual Leak Detector - Various Utility Definitions
 //  Copyright (c) 2005-2006 Dan Moulding
@@ -59,7 +58,7 @@ Applications should never include this header."
 #endif // _M_IX86
 
 #if defined(_M_IX86) || defined (_M_X64)
-#define FRAMEPOINTER(fp) __asm mov fp, BPREG // Copies the current frame pointer to the supplied variable.
+#define FRAMEPOINTER(fp) __asm {mov fp, BPREG} // Copies the current frame pointer to the supplied variable.
 #else
 // If you want to retarget Visual Leak Detector to another processor
 // architecture then you'll need to provide an architecture-specific macro to
@@ -107,3 +106,7 @@ VOID setreportencoding (encoding_e encoding);
 VOID setreportfile (FILE *file, BOOL copydebugger);
 VOID strapp (LPWSTR *dest, LPCWSTR source);
 BOOL strtobool (LPCWSTR s);
+#if _WIN32_WINNT < 0x0600 // Windows XP or earlier, no GetProcessIdOfThread()
+DWORD _GetProcessIdOfThread (HANDLE thread);
+#define GetProcessIdOfThread _GetProcessIdOfThread
+#endif
\ No newline at end of file
index ffaa43ac71a9bfb316a9a8334fbd09101774bb44..797a89401f0638821e54a3e2a21a28ca746a0db7 100644 (file)
@@ -1,8 +1,7 @@
 ////////////////////////////////////////////////////////////////////////////////
-//  $Id: vld.cpp,v 1.69 2006/11/18 05:07:04 dmouldin Exp $
 //
 //  Visual Leak Detector - VisualLeakDetector Class Implementation
-//  Copyright (c) 2005-2006 Dan Moulding
+//  Copyright (c) 2005-2009 Dan Moulding
 //
 //  This library is free software; you can redistribute it and/or
 //  modify it under the terms of the GNU Lesser General Public
 #include <cstdio>
 #include <sys/stat.h>
 #include <windows.h>
+#ifndef __out_xcount
 #define __out_xcount(x) // Workaround for the specstrings.h bug in the Platform SDK.
+#endif
 #define DBGHELP_TRANSLATE_TCHAR
-#include <dbghelp.h>    // Provides symbol handling services.
-#define VLDBUILD        // Declares that we are building Visual Leak Detector.
-#include "callstack.h"  // Provides a class for handling call stacks.
-#include "map.h"        // Provides a lightweight STL-like map template.
-#include "ntapi.h"      // Provides access to NT APIs.
-#include "set.h"        // Provides a lightweight STL-like set template.
-#include "utility.h"    // Provides various utility functions.
-#include "vldheap.h"    // Provides internal new and delete operators.
-#include "vldint.h"     // Provides access to the Visual Leak Detector internals.
+#include <dbghelp.h>     // Provides symbol handling services.
+#define VLDBUILD         // Declares that we are building Visual Leak Detector.
+#include "callstack.h"   // Provides a class for handling call stacks.
+#include "crtmfcpatch.h" // Provides CRT and MFC patch functions.
+#include "map.h"         // Provides a lightweight STL-like map template.
+#include "ntapi.h"       // Provides access to NT APIs.
+#include "set.h"         // Provides a lightweight STL-like set template.
+#include "utility.h"     // Provides various utility functions.
+#include "vldheap.h"     // Provides internal new and delete operators.
+#include "vldint.h"      // Provides access to the Visual Leak Detector internals.
 
 #define BLOCKMAPRESERVE     64  // This should strike a balance between memory use and a desire to minimize heap hits.
 #define HEAPMAPRESERVE      2   // Usually there won't be more than a few heaps in the process, so this should be small.
@@ -57,57 +59,15 @@ HANDLE           currentthread;  // Pseudo-handle for the current thread.
 CRITICAL_SECTION imagelock;      // Serializes calls to the Debug Help Library PE image access APIs.
 HANDLE           processheap;    // Handle to the process's heap (COM allocations come from here).
 CRITICAL_SECTION stackwalklock;  // Serializes calls to StackWalk64 from the Debug Help Library.
-CRITICAL_SECTION symbollock;     // Serializes calls to the Debug Help Library symbold handling APIs.
-
-// Function pointer types for explicit dynamic linking with functions listed in
-// the import patch table.
-typedef void* (__cdecl *_calloc_dbg_t) (size_t, size_t, int, const char*, int);
-typedef void* (__cdecl *_malloc_dbg_t) (size_t, int, const char *, int);
-typedef void* (__cdecl *_realloc_dbg_t) (void *, size_t, int, const char *, int);
-typedef void* (__cdecl *calloc_t) (size_t, size_t);
-typedef HRESULT (__stdcall *CoGetMalloc_t) (DWORD, LPMALLOC *);
-typedef LPVOID (__stdcall *CoTaskMemAlloc_t) (ULONG);
-typedef LPVOID (__stdcall *CoTaskMemRealloc_t) (LPVOID, ULONG);
-typedef void* (__cdecl *crt_new_dbg_t) (unsigned int, int, const char *, int);
-typedef void* (__cdecl *malloc_t) (size_t);
-typedef void* (__cdecl *mfc_new_dbg_t) (unsigned int, const char *, int);
-typedef void* (__cdecl *new_t) (unsigned int);
-typedef void* (__cdecl *realloc_t) (void *, size_t);
+CRITICAL_SECTION symbollock;     // Serializes calls to the Debug Help Library symbols handling APIs.
+
+// The one and only VisualLeakDetector object instance.
+__declspec(dllexport) VisualLeakDetector vld;
 
 // Global function pointers for explicit dynamic linking with functions listed
 // in the import patch table. Using explicit dynamic linking minimizes VLD's
 // footprint by loading only modules that are actually used. These pointers will
 // be linked to the real functions the first time they are used.
-static CoGetMalloc_t      pCoGetMalloc            = NULL;
-static CoTaskMemAlloc_t   pCoTaskMemAlloc         = NULL;
-static CoTaskMemRealloc_t pCoTaskMemRealloc       = NULL;
-static _calloc_dbg_t      pcrt80d__calloc_dbg     = NULL;
-static _malloc_dbg_t      pcrt80d__malloc_dbg     = NULL;
-static _realloc_dbg_t     pcrt80d__realloc_dbg    = NULL;
-static crt_new_dbg_t      pcrt80d__scalar_new_dbg = NULL;
-static crt_new_dbg_t      pcrt80d__vector_new_dbg = NULL;
-static calloc_t           pcrt80d_calloc          = NULL;
-static malloc_t           pcrt80d_malloc          = NULL;
-static realloc_t          pcrt80d_realloc         = NULL;
-static new_t              pcrt80d_scalar_new      = NULL;
-static new_t              pcrt80d_vector_new      = NULL;
-static _calloc_dbg_t      pcrtd__calloc_dbg       = NULL;
-static _malloc_dbg_t      pcrtd__malloc_dbg       = NULL;
-static _realloc_dbg_t     pcrtd__realloc_dbg      = NULL;
-static crt_new_dbg_t      pcrtd__scalar_new_dbg   = NULL;
-static calloc_t           pcrtd_calloc            = NULL;
-static malloc_t           pcrtd_malloc            = NULL;
-static realloc_t          pcrtd_realloc           = NULL;
-static new_t              pcrtd_scalar_new        = NULL;
-static mfc_new_dbg_t      pmfc42d__scalar_new_dbg = NULL;
-static new_t              pmfc42d_scalar_new      = NULL;
-static mfc_new_dbg_t      pmfc80d__scalar_new_dbg = NULL;
-static mfc_new_dbg_t      pmfc80d__vector_new_dbg = NULL;
-static new_t              pmfc80d_scalar_new      = NULL;
-static new_t              pmfc80d_vector_new      = NULL;
-
-// The one and only VisualLeakDetector object instance.
-__declspec(dllexport) VisualLeakDetector vld;
 
 // The import patch table: lists the heap-related API imports that VLD patches
 // through to replacement functions provided by VLD. Having this table simply
@@ -122,34 +82,135 @@ patchentry_t VisualLeakDetector::m_patchtable [] = {
     "kernel32.dll", "HeapReAlloc",        0x0, _RtlReAllocateHeap,
 
     // MFC new operators (exported by ordinal).
-    "mfc42d.dll",   (LPCSTR)714,          0x0, _mfc42d__scalar_new_dbg,
-    "mfc42d.dll",   (LPCSTR)711,          0x0, _mfc42d_scalar_new,
-    // XXX MFC 7.x DLL new operators still need to be added to this
-    //   table, but I don't know their ordinals.
-    "mfc80d.dll",   (LPCSTR)895,          0x0, _mfc80d__scalar_new_dbg,
-    "mfc80d.dll",   (LPCSTR)269,          0x0, _mfc80d__vector_new_dbg,
-    "mfc80d.dll",   (LPCSTR)893,          0x0, _mfc80d_scalar_new,
-    "mfc80d.dll",   (LPCSTR)267,          0x0, _mfc80d_vector_new,
+    // XXX why are the vector new operators missing for mfc42d.dll?
+    "mfc42d.dll",   (LPCSTR)711,          0x0, VS60::mfcd_scalar_new,
+    "mfc42d.dll",   (LPCSTR)712,          0x0, VS60::mfcd__scalar_new_dbg_4p,
+    "mfc42d.dll",   (LPCSTR)714,          0x0, VS60::mfcd__scalar_new_dbg_3p,
+    "mfc42ud.dll",  (LPCSTR)711,          0x0, VS60::mfcud_scalar_new,
+    "mfc42ud.dll",  (LPCSTR)712,          0x0, VS60::mfcud__scalar_new_dbg_4p,
+    "mfc42ud.dll",  (LPCSTR)714,          0x0, VS60::mfcud__scalar_new_dbg_3p,
+    "mfc70d.dll",   (LPCSTR)257,          0x0, VS70::mfcd_vector_new,
+    "mfc70d.dll",   (LPCSTR)258,          0x0, VS70::mfcd__vector_new_dbg_4p,
+    "mfc70d.dll",   (LPCSTR)259,          0x0, VS70::mfcd__vector_new_dbg_3p,
+    "mfc70d.dll",   (LPCSTR)832,          0x0, VS70::mfcd_scalar_new,
+    "mfc70d.dll",   (LPCSTR)833,          0x0, VS70::mfcd__scalar_new_dbg_4p,
+    "mfc70d.dll",   (LPCSTR)834,          0x0, VS70::mfcd__scalar_new_dbg_3p,
+    "mfc70ud.dll",  (LPCSTR)258,          0x0, VS70::mfcud_vector_new,
+    "mfc70ud.dll",  (LPCSTR)259,          0x0, VS70::mfcud__vector_new_dbg_4p,
+    "mfc70ud.dll",  (LPCSTR)260,          0x0, VS70::mfcud__vector_new_dbg_3p,
+    "mfc70ud.dll",  (LPCSTR)833,          0x0, VS70::mfcud_scalar_new,
+    "mfc70ud.dll",  (LPCSTR)834,          0x0, VS70::mfcud__scalar_new_dbg_4p,
+    "mfc70ud.dll",  (LPCSTR)835,          0x0, VS70::mfcud__scalar_new_dbg_3p,
+    "mfc71d.dll",   (LPCSTR)267,          0x0, VS71::mfcd_vector_new,
+    "mfc71d.dll",   (LPCSTR)268,          0x0, VS71::mfcd__vector_new_dbg_4p,
+    "mfc71d.dll",   (LPCSTR)269,          0x0, VS71::mfcd__vector_new_dbg_3p,
+    "mfc71d.dll",   (LPCSTR)893,          0x0, VS71::mfcd_scalar_new,
+    "mfc71d.dll",   (LPCSTR)894,          0x0, VS71::mfcd__scalar_new_dbg_4p,
+    "mfc71d.dll",   (LPCSTR)895,          0x0, VS71::mfcd__scalar_new_dbg_3p,
+    "mfc71ud.dll",  (LPCSTR)267,          0x0, VS71::mfcud_vector_new,
+    "mfc71ud.dll",  (LPCSTR)268,          0x0, VS71::mfcud__vector_new_dbg_4p,
+    "mfc71ud.dll",  (LPCSTR)269,          0x0, VS71::mfcud__vector_new_dbg_3p,
+    "mfc71ud.dll",  (LPCSTR)893,          0x0, VS71::mfcud_scalar_new,
+    "mfc71ud.dll",  (LPCSTR)894,          0x0, VS71::mfcud__scalar_new_dbg_4p,
+    "mfc71ud.dll",  (LPCSTR)895,          0x0, VS71::mfcud__scalar_new_dbg_3p,
+    "mfc80d.dll",   (LPCSTR)267,          0x0, VS80::mfcd_vector_new,
+    "mfc80d.dll",   (LPCSTR)268,          0x0, VS80::mfcd__vector_new_dbg_4p,
+    "mfc80d.dll",   (LPCSTR)269,          0x0, VS80::mfcd__vector_new_dbg_3p,
+    "mfc80d.dll",   (LPCSTR)893,          0x0, VS80::mfcd_scalar_new,
+    "mfc80d.dll",   (LPCSTR)894,          0x0, VS80::mfcd__scalar_new_dbg_4p,
+    "mfc80d.dll",   (LPCSTR)895,          0x0, VS80::mfcd__scalar_new_dbg_3p,
+    "mfc80ud.dll",  (LPCSTR)267,          0x0, VS80::mfcud_vector_new,
+    "mfc80ud.dll",  (LPCSTR)268,          0x0, VS80::mfcud__vector_new_dbg_4p,
+    "mfc80ud.dll",  (LPCSTR)269,          0x0, VS80::mfcud__vector_new_dbg_3p,
+    "mfc80ud.dll",  (LPCSTR)893,          0x0, VS80::mfcud_scalar_new,
+    "mfc80ud.dll",  (LPCSTR)894,          0x0, VS80::mfcud__scalar_new_dbg_4p,
+    "mfc80ud.dll",  (LPCSTR)895,          0x0, VS80::mfcud__scalar_new_dbg_3p,
+    "mfc90d.dll",   (LPCSTR)267,          0x0, VS90::mfcd_vector_new,
+    "mfc90d.dll",   (LPCSTR)268,          0x0, VS90::mfcd__vector_new_dbg_4p,
+    "mfc90d.dll",   (LPCSTR)269,          0x0, VS90::mfcd__vector_new_dbg_3p,
+    "mfc90d.dll",   (LPCSTR)931,          0x0, VS90::mfcd_scalar_new,
+    "mfc90d.dll",   (LPCSTR)932,          0x0, VS90::mfcd__scalar_new_dbg_4p,
+    "mfc90d.dll",   (LPCSTR)933,          0x0, VS90::mfcd__scalar_new_dbg_3p,
+    "mfc90ud.dll",  (LPCSTR)267,          0x0, VS90::mfcud_vector_new,
+    "mfc90ud.dll",  (LPCSTR)268,          0x0, VS90::mfcud__vector_new_dbg_4p,
+    "mfc90ud.dll",  (LPCSTR)269,          0x0, VS90::mfcud__vector_new_dbg_3p,
+    "mfc90ud.dll",  (LPCSTR)935,          0x0, VS90::mfcud_scalar_new,
+    "mfc90ud.dll",  (LPCSTR)936,          0x0, VS90::mfcud__scalar_new_dbg_4p,
+    "mfc90ud.dll",  (LPCSTR)937,          0x0, VS90::mfcud__scalar_new_dbg_3p,
+    "mfc100d.dll",   (LPCSTR)267,          0x0, VS100::mfcd_vector_new,
+    "mfc100d.dll",   (LPCSTR)268,          0x0, VS100::mfcd__vector_new_dbg_4p,
+    "mfc100d.dll",   (LPCSTR)269,          0x0, VS100::mfcd__vector_new_dbg_3p,
+    "mfc100d.dll",   (LPCSTR)1427,         0x0, VS100::mfcd_scalar_new,
+    "mfc100d.dll",   (LPCSTR)1428,         0x0, VS100::mfcd__scalar_new_dbg_4p,
+    "mfc100d.dll",   (LPCSTR)1429,         0x0, VS100::mfcd__scalar_new_dbg_3p,
+    "mfc100ud.dll",  (LPCSTR)267,          0x0, VS100::mfcud_vector_new,
+    "mfc100ud.dll",  (LPCSTR)268,          0x0, VS100::mfcud__vector_new_dbg_4p,
+    "mfc100ud.dll",  (LPCSTR)269,          0x0, VS100::mfcud__vector_new_dbg_3p,
+    "mfc100ud.dll",  (LPCSTR)1434,         0x0, VS100::mfcud_scalar_new,
+    "mfc100ud.dll",  (LPCSTR)1435,         0x0, VS100::mfcud__scalar_new_dbg_4p,
+    "mfc100ud.dll",  (LPCSTR)1436,         0x0, VS100::mfcud__scalar_new_dbg_3p,
 
     // CRT new operators and heap APIs.
-    "msvcr80d.dll", "_calloc_dbg",        0x0, _crt80d__calloc_dbg,
-    "msvcr80d.dll", "_malloc_dbg",        0x0, _crt80d__malloc_dbg,
-    "msvcr80d.dll", "_realloc_dbg",       0x0, _crt80d__realloc_dbg,
-    "msvcr80d.dll", "??2@YAPAXIHPBDH@Z",  0x0, _crt80d__scalar_new_dbg,
-    "msvcr80d.dll", "??_U@YAPAXIHPBDH@Z", 0x0, _crt80d__vector_new_dbg,
-    "msvcr80d.dll", "calloc",             0x0, _crt80d_calloc,
-    "msvcr80d.dll", "malloc",             0x0, _crt80d_malloc,
-    "msvcr80d.dll", "realloc",            0x0, _crt80d_realloc,
-    "msvcr80d.dll", "??2@YAPAXI@Z",       0x0, _crt80d_scalar_new,
-    "msvcr80d.dll", "??_U@YAPAXI@Z",      0x0, _crt80d_vector_new,
-    "msvcrtd.dll",  "_calloc_dbg",        0x0, _crtd__calloc_dbg,
-    "msvcrtd.dll",  "_malloc_dbg",        0x0, _crtd__malloc_dbg,
-    "msvcrtd.dll",  "??2@YAPAXIHPBDH@Z",  0x0, _crtd__scalar_new_dbg,
-    "msvcrtd.dll",  "_realloc_dbg",       0x0, _crtd__realloc_dbg,
-    "msvcrtd.dll",  "calloc",             0x0, _crtd_calloc,
-    "msvcrtd.dll",  "malloc",             0x0, _crtd_malloc,
-    "msvcrtd.dll",  "realloc",            0x0, _crtd_realloc,
-    "msvcrtd.dll",  "??2@YAPAXI@Z",       0x0, _crtd_scalar_new,
+    "msvcrtd.dll",  "_calloc_dbg",        0x0, VS60::crtd__calloc_dbg,
+    "msvcrtd.dll",  "_malloc_dbg",        0x0, VS60::crtd__malloc_dbg,
+    "msvcrtd.dll",  "_realloc_dbg",       0x0, VS60::crtd__realloc_dbg,
+    "msvcrtd.dll",  "??2@YAPAXIHPBDH@Z",  0x0, VS60::crtd__scalar_new_dbg,
+//  "msvcrtd.dll",  "??_U@YAPAXIHPBDH@Z", 0x0, VS60::crtd__vector_new_dbg,
+    "msvcrtd.dll",  "calloc",             0x0, VS60::crtd_calloc,
+    "msvcrtd.dll",  "malloc",             0x0, VS60::crtd_malloc,
+    "msvcrtd.dll",  "realloc",            0x0, VS60::crtd_realloc,
+    "msvcrtd.dll",  "??2@YAPAXI@Z",       0x0, VS60::crtd_scalar_new,
+//  "msvcrtd.dll",  "??_U@YAPAXI@Z",      0x0, VS60::crtd_vector_new,
+    "msvcr70d.dll", "_calloc_dbg",        0x0, VS70::crtd__calloc_dbg,
+    "msvcr70d.dll", "_malloc_dbg",        0x0, VS70::crtd__malloc_dbg,
+    "msvcr70d.dll", "_realloc_dbg",       0x0, VS70::crtd__realloc_dbg,
+    "msvcr70d.dll", "??2@YAPAXIHPBDH@Z",  0x0, VS70::crtd__scalar_new_dbg,
+    "msvcr70d.dll", "??_U@YAPAXIHPBDH@Z", 0x0, VS70::crtd__vector_new_dbg,
+    "msvcr70d.dll", "calloc",             0x0, VS70::crtd_calloc,
+    "msvcr70d.dll", "malloc",             0x0, VS70::crtd_malloc,
+    "msvcr70d.dll", "realloc",            0x0, VS70::crtd_realloc,
+    "msvcr70d.dll", "??2@YAPAXI@Z",       0x0, VS70::crtd_scalar_new,
+    "msvcr70d.dll", "??_U@YAPAXI@Z",      0x0, VS70::crtd_vector_new,
+    "msvcr71d.dll", "_calloc_dbg",        0x0, VS71::crtd__calloc_dbg,
+    "msvcr71d.dll", "_malloc_dbg",        0x0, VS71::crtd__malloc_dbg,
+    "msvcr71d.dll", "_realloc_dbg",       0x0, VS71::crtd__realloc_dbg,
+    "msvcr71d.dll", "??2@YAPAXIHPBDH@Z",  0x0, VS71::crtd__scalar_new_dbg,
+    "msvcr71d.dll", "??_U@YAPAXIHPBDH@Z", 0x0, VS71::crtd__vector_new_dbg,
+    "msvcr71d.dll", "calloc",             0x0, VS71::crtd_calloc,
+    "msvcr71d.dll", "malloc",             0x0, VS71::crtd_malloc,
+    "msvcr71d.dll", "realloc",            0x0, VS71::crtd_realloc,
+    "msvcr71d.dll", "??2@YAPAXI@Z",       0x0, VS71::crtd_scalar_new,
+    "msvcr71d.dll", "??_U@YAPAXI@Z",      0x0, VS71::crtd_vector_new,
+    "msvcr80d.dll", "_calloc_dbg",        0x0, VS80::crtd__calloc_dbg,
+    "msvcr80d.dll", "_malloc_dbg",        0x0, VS80::crtd__malloc_dbg,
+    "msvcr80d.dll", "_realloc_dbg",       0x0, VS80::crtd__realloc_dbg,
+    "msvcr80d.dll", "??2@YAPAXIHPBDH@Z",  0x0, VS80::crtd__scalar_new_dbg,
+    "msvcr80d.dll", "??_U@YAPAXIHPBDH@Z", 0x0, VS80::crtd__vector_new_dbg,
+    "msvcr80d.dll", "calloc",             0x0, VS80::crtd_calloc,
+    "msvcr80d.dll", "malloc",             0x0, VS80::crtd_malloc,
+    "msvcr80d.dll", "realloc",            0x0, VS80::crtd_realloc,
+    "msvcr80d.dll", "??2@YAPAXI@Z",       0x0, VS80::crtd_scalar_new,
+    "msvcr80d.dll", "??_U@YAPAXI@Z",      0x0, VS80::crtd_vector_new,
+    "msvcr90d.dll", "_calloc_dbg",        0x0, VS90::crtd__calloc_dbg,
+    "msvcr90d.dll", "_malloc_dbg",        0x0, VS90::crtd__malloc_dbg,
+    "msvcr90d.dll", "_realloc_dbg",       0x0, VS90::crtd__realloc_dbg,
+    "msvcr90d.dll", "??2@YAPAXIHPBDH@Z",  0x0, VS90::crtd__scalar_new_dbg,
+    "msvcr90d.dll", "??_U@YAPAXIHPBDH@Z", 0x0, VS90::crtd__vector_new_dbg,
+    "msvcr90d.dll", "calloc",             0x0, VS90::crtd_calloc,
+    "msvcr90d.dll", "malloc",             0x0, VS90::crtd_malloc,
+    "msvcr90d.dll", "realloc",            0x0, VS90::crtd_realloc,
+    "msvcr90d.dll", "??2@YAPAXI@Z",       0x0, VS90::crtd_scalar_new,
+    "msvcr90d.dll", "??_U@YAPAXI@Z",      0x0, VS90::crtd_vector_new,
+    "msvcr100d.dll", "_calloc_dbg",        0x0, VS100::crtd__calloc_dbg,
+    "msvcr100d.dll", "_malloc_dbg",        0x0, VS100::crtd__malloc_dbg,
+    "msvcr100d.dll", "_realloc_dbg",       0x0, VS100::crtd__realloc_dbg,
+    "msvcr100d.dll", scalar_new_dbg_name,  0x0, VS100::crtd__scalar_new_dbg,
+    "msvcr100d.dll", vector_new_dbg_name,  0x0, VS100::crtd__vector_new_dbg,
+    "msvcr100d.dll", "calloc",             0x0, VS100::crtd_calloc,
+    "msvcr100d.dll", "malloc",             0x0, VS100::crtd_malloc,
+    "msvcr100d.dll", "realloc",            0x0, VS100::crtd_realloc,
+    "msvcr100d.dll", scalar_new_name,      0x0, VS100::crtd_scalar_new,
+    "msvcr100d.dll", vector_new_name,      0x0, VS100::crtd_vector_new,
 
     // NT APIs.
     "ntdll.dll",    "RtlAllocateHeap",    0x0, _RtlAllocateHeap,
@@ -330,7 +391,6 @@ VisualLeakDetector::~VisualLeakDetector ()
     BlockMap::Iterator   blockit;
     BlockMap            *blockmap;
     size_t               count;
-    DWORD                exitcode;
     vldblockheader_t    *header;
     HANDLE               heap;
     HeapMap::Iterator    heapit;
@@ -339,10 +399,10 @@ VisualLeakDetector::~VisualLeakDetector ()
     WCHAR                leakfilew [MAX_PATH];
     int                  leakline = 0;
     ModuleSet::Iterator  moduleit;
-    SIZE_T               sleepcount;
     HANDLE               thread;
     BOOL                 threadsactive= FALSE;
     TlsSet::Iterator     tlsit;
+    DWORD                dwCurProcessID;
 
     if (m_options & VLD_OPT_VLDOFF) {
         // VLD has been turned off.
@@ -353,6 +413,8 @@ VisualLeakDetector::~VisualLeakDetector ()
         // Detach Visual Leak Detector from all previously attached modules.
         EnumerateLoadedModulesW64(currentprocess, detachfrommodule, NULL);
 
+        dwCurProcessID = GetCurrentProcessId();
+
         // See if any threads that have ever entered VLD's code are still active.
         EnterCriticalSection(&m_tlslock);
         for (tlsit = m_tlsset->begin(); tlsit != m_tlsset->end(); ++tlsit) {
@@ -361,33 +423,29 @@ VisualLeakDetector::~VisualLeakDetector ()
                 continue;
             }
 
-            sleepcount = 0;
-            thread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, (*tlsit)->threadid);
+            thread = OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION, FALSE, (*tlsit)->threadid);
             if (thread == NULL) {
                 // Couldn't query this thread. We'll assume that it exited.
                 continue; // XXX should we check GetLastError()?
             }
-            while (GetExitCodeThread(thread, &exitcode) == TRUE) {
-                if (exitcode != STILL_ACTIVE) {
-                    // This thread exited.
-                    break;
-                }
-                else {
-                    // There is still at least one other thread running. The CRT
-                    // will stomp it dead when it cleans up, which is not a
-                    // graceful way for a thread to go down. Warn about this,
-                    // and wait until the thread has exited so that we know it
-                    // can't still be off running somewhere in VLD's code.
-                    threadsactive = TRUE;
-                    Sleep(100);
-                    sleepcount++;
-                    if ((sleepcount % 100) == 0) {
-                        // Just in case this takes a long time, let the human
-                        // know we are still here and alive.
-                        report(L"Visual Leak Detector: Waiting for threads to terminate...\n");
-                    }
-                }
+            if (GetProcessIdOfThread(thread) != dwCurProcessID) {
+                //The thread ID has been recycled.
+                CloseHandle(thread);
+                continue;
+            }
+            while (WaitForSingleObject(thread, 10000) == WAIT_TIMEOUT) { // 10 seconds
+                // There is still at least one other thread running. The CRT
+                // will stomp it dead when it cleans up, which is not a
+                // graceful way for a thread to go down. Warn about this,
+                // and wait until the thread has exited so that we know it
+                // can't still be off running somewhere in VLD's code.
+                // 
+                // Since we've been waiting a while, let the human know we are
+                // still here and alive.
+                threadsactive = TRUE;
+                report(L"Visual Leak Detector: Waiting for threads to terminate...\n");
             }
+            CloseHandle(thread);
         }
         LeaveCriticalSection(&m_tlslock);
 
@@ -508,768 +566,1057 @@ VisualLeakDetector::~VisualLeakDetector ()
     }
 }
 
-// _CoGetMalloc - Calls to CoGetMalloc are patched through to this function.
-//   This function returns a pointer to Visual Leak Detector's implementation
-//   of the IMalloc interface, instead of returning a pointer to the system
-//   implementation. This allows VLD's implementation of the IMalloc interface
-//   (which is basically a thin wrapper around the system implementation) to be
-//   invoked in place of the system implementation.
+
+////////////////////////////////////////////////////////////////////////////////
 //
-//  - context (IN): Reserved; value must be 1.
+// Private Leak Detection Functions
 //
-//  - imalloc (IN): Address of a pointer to receive the address of VLD's
-//      implementation of the IMalloc interface.
+////////////////////////////////////////////////////////////////////////////////
+
+// attachtoloadedmodules - Attaches VLD to all modules contained in the provided
+//   ModuleSet. Not all modules are in the ModuleSet will actually be included
+//   in leak detection. Only modules that import the global VisualLeakDetector
+//   class object, or those that are otherwise explicitly included in leak
+//   detection, will be checked for memory leaks.
+//
+//   When VLD attaches to a module, it means that any of the imports listed in
+//   the import patch table which are imported by the module, will be redirected
+//   to VLD's designated replacements.
+//
+//  - newmodules (IN): Pointer to a ModuleSet containing information about any
+//      loaded modules that need to be attached.
 //
 //  Return Value:
 //
-//    Always returns S_OK.
+//    None.
 //
-HRESULT VisualLeakDetector::_CoGetMalloc (DWORD context, LPMALLOC *imalloc)
+VOID VisualLeakDetector::attachtoloadedmodules (ModuleSet *newmodules)
 {
-    HMODULE ole32;
+    size_t                count;
+    DWORD64               modulebase;
+    UINT32                moduleflags;
+    IMAGEHLP_MODULE64     moduleimageinfo;
+    LPCSTR                modulename;
+#define MAXMODULENAME (_MAX_FNAME + _MAX_EXT)
+    WCHAR                 modulenamew [MAXMODULENAME];
+    LPCSTR                modulepath;
+    DWORD                 modulesize;
+    ModuleSet::Iterator   newit;
+    ModuleSet::Iterator   oldit;
+    ModuleSet            *oldmodules;
+    BOOL                  refresh;
+    UINT                  tablesize = sizeof(m_patchtable) / sizeof(patchentry_t);
+    ModuleSet::Muterator  updateit;
 
-    *imalloc = (LPMALLOC)&vld;
+    // Iterate through the supplied set, until all modules have been attached.
+    for (newit = newmodules->begin(); newit != newmodules->end(); ++newit) {
+        modulebase  = (DWORD64)(*newit).addrlow;
+        moduleflags = 0x0;
+        modulename  = (*newit).name;
+        modulepath  = (*newit).path;
+        modulesize  = (DWORD)((*newit).addrhigh - (*newit).addrlow) + 1;
 
-    if (pCoGetMalloc == NULL) {
-        // This is the first call to this function. Link to the real
-        // CoGetMalloc and get a pointer to the system implementation of the
-        // IMalloc interface.
-        ole32 = GetModuleHandle(L"ole32.dll");
-        pCoGetMalloc = (CoGetMalloc_t)GetProcAddress(ole32, "CoGetMalloc");
-        pCoGetMalloc(context, &vld.m_imalloc);
-    }
+        refresh = FALSE;
+        EnterCriticalSection(&m_moduleslock);
+        oldmodules = m_loadedmodules;
+        if (oldmodules != NULL) {
+            // This is not the first time we have been called to attach to the
+            // currently loaded modules.
+            oldit = oldmodules->find(*newit);
+            if (oldit != oldmodules->end()) {
+                // We've seen this "new" module loaded in the process before.
+                moduleflags = (*oldit).flags;
+                LeaveCriticalSection(&m_moduleslock);
+                if (moduleispatched((HMODULE)modulebase, m_patchtable, tablesize)) {
+                    // This module is already attached. Just update the module's
+                    // flags, nothing more.
+                    updateit = newit;
+                    (*updateit).flags = moduleflags;
+                    continue;
+                }
+                else {
+                    // This module may have been attached before and has been
+                    // detached. We'll need to try reattaching to it in case it
+                    // was unloaded and then subsequently reloaded.
+                    refresh = TRUE;
+                }
+            }
+            else {
+                LeaveCriticalSection(&m_moduleslock);
+            }
+        }
+        else {
+            LeaveCriticalSection(&m_moduleslock);
+        }
 
-    return S_OK;
-}
+        EnterCriticalSection(&symbollock);
+        if ((refresh == TRUE) && (moduleflags & VLD_MODULE_SYMBOLSLOADED)) {
+            // Discard the previously loaded symbols, so we can refresh them.
+            if (SymUnloadModule64(currentprocess, modulebase) == FALSE) {
+                report(L"WARNING: Visual Leak Detector: Failed to unload the symbols for %s. Function names and line"
+                       L" numbers shown in the memory leak report for %s may be inaccurate.", modulename, modulename);
+            }
+        }
 
-// _CoTaskMemAlloc - Calls to CoTaskMemAlloc are patched through to this
-//   function. This function is just a wrapper around the real CoTaskMemAlloc
-//   that sets appropriate flags to be consulted when the memory is actually
-//   allocated by RtlAllocateHeap.
-//
-//  - size (IN): Size of the memory block to allocate.
-//
-//  Return Value:
-//
-//    Returns the value returned from CoTaskMemAlloc.
-//
-LPVOID VisualLeakDetector::_CoTaskMemAlloc (ULONG size)
-{
-    LPVOID   block;
-    SIZE_T   fp;
-    HMODULE  ole32;
-    tls_t   *tls = vld.gettls();
+        // Try to load the module's symbols. This ensures that we have loaded
+        // the symbols for every module that has ever been loaded into the
+        // process, guaranteeing the symbols' availability when generating the
+        // leak report.
+        moduleimageinfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
+        if ((SymGetModuleInfoW64(currentprocess, (DWORD64)modulebase, &moduleimageinfo) == TRUE) ||
+            ((SymLoadModule64(currentprocess, NULL, modulepath, NULL, modulebase, modulesize) == modulebase) &&
+            (SymGetModuleInfoW64(currentprocess, modulebase, &moduleimageinfo) == TRUE))) {
+            moduleflags |= VLD_MODULE_SYMBOLSLOADED;
+        }
+        LeaveCriticalSection(&symbollock);
 
-    if (tls->addrfp == 0x0) {
-        // This is the first call to enter VLD for the current allocation.
-        // Record the current frame pointer.
-        FRAMEPOINTER(fp);
-        tls->addrfp = fp;
-    }
+        if (_stricmp("vld.dll", modulename) == 0) {
+            // What happens when a module goes through it's own portal? Bad things.
+            // Like infinite recursion. And ugly bald men wearing dresses. VLD
+            // should not, therefore, attach to itself.
+            continue;
+        }
 
-    if (pCoTaskMemAlloc == NULL) {
-        // This is the first call to this function. Link to the real
-        // CoTaskMemAlloc.
-        ole32 = GetModuleHandle(L"ole32.dll");
-        pCoTaskMemAlloc = (CoTaskMemAlloc_t)GetProcAddress(ole32, "CoTaskMemAlloc");
-    }
+        mbstowcs_s(&count, modulenamew, MAXMODULENAME, modulename, _TRUNCATE);
+        if ((findimport((HMODULE)modulebase, m_vldbase, "vld.dll", "?vld@@3VVisualLeakDetector@@A") == FALSE) &&
+            (wcsstr(vld.m_forcedmodulelist, modulenamew) == NULL)) {
+            // This module does not import VLD. This means that none of the module's
+            // sources #included vld.h. Exclude this module from leak detection.
+            moduleflags |= VLD_MODULE_EXCLUDED;
+        }
+        else if (!(moduleflags & VLD_MODULE_SYMBOLSLOADED) || (moduleimageinfo.SymType == SymExport)) {
+            // This module is going to be included in leak detection, but complete
+            // symbols for this module couldn't be loaded. This means that any stack
+            // traces through this module may lack information, like line numbers
+            // and function names.
+            report(L"WARNING: Visual Leak Detector: A module, %s, included in memory leak detection\n"
+                   L"  does not have any debugging symbols available, or they could not be located.\n"
+                   L"  Function names and/or line numbers for this module may not be available.\n", modulename);
+        }
 
-    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
-    block = pCoTaskMemAlloc(size);
+        // Update the module's flags in the "new modules" set.
+        updateit = newit;
+        (*updateit).flags = moduleflags;
 
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
-    
-    return block;
+        // Attach to the module.
+        patchmodule((HMODULE)modulebase, m_patchtable, tablesize);
+    }
 }
 
-// _CoTaskMemRealloc - Calls to CoTaskMemRealloc are patched through to this
-//   function. This function is just a wrapper around the real CoTaskMemRealloc
-//   that sets appropriate flags to be consulted when the memory is actually
-//   allocated by RtlAllocateHeap.
-//
-//  - mem (IN): Pointer to the memory block to reallocate.
-//
-//  - size (IN): Size, in bytes, of the block to reallocate.
+// buildsymbolsearchpath - Builds the symbol search path for the symbol handler.
+//   This helps the symbol handler find the symbols for the application being
+//   debugged.
 //
 //  Return Value:
 //
-//    Returns the value returned from CoTaskMemRealloc.
+//    Returns a string containing the search path. The caller is responsible for
+//    freeing the string.
 //
-LPVOID VisualLeakDetector::_CoTaskMemRealloc (LPVOID mem, ULONG size)
+LPWSTR VisualLeakDetector::buildsymbolsearchpath ()
 {
-    LPVOID   block;
-    SIZE_T   fp;
-    HMODULE  ole32;
-    tls_t   *tls = vld.gettls();
+    WCHAR   directory [_MAX_DIR];
+    WCHAR   drive [_MAX_DRIVE];
+    LPWSTR  env;
+    DWORD   envlen;
+    SIZE_T  index;
+    SIZE_T  length;
+    HMODULE module;
+    LPWSTR  path = new WCHAR [MAX_PATH];
+    SIZE_T  pos = 0;
+    WCHAR   system [MAX_PATH];
+    WCHAR   windows [MAX_PATH];
 
-    if (tls->addrfp == 0x0) {
-        // This is the first call to enter VLD for the current allocation.
-        // Record the current frame pointer.
-        FRAMEPOINTER(fp);
-        tls->addrfp = fp;
-    }
+    // Oddly, the symbol handler ignores the link to the PDB embedded in the
+    // executable image. So, we'll manually add the location of the executable
+    // to the search path since that is often where the PDB will be located.
+    path[0] = L'\0';
+    module = GetModuleHandle(NULL);
+    GetModuleFileName(module, path, MAX_PATH);
+    _wsplitpath_s(path, drive, _MAX_DRIVE, directory, _MAX_DIR, NULL, 0, NULL, 0);
+    wcsncpy_s(path, MAX_PATH, drive, _TRUNCATE);
+    strapp(&path, directory);
 
-    if (pCoTaskMemRealloc == NULL) {
-        // This is the first call to this function. Link to the real
-        // CoTaskMemRealloc.
-        ole32 = GetModuleHandle(L"ole32.dll");
-        pCoTaskMemRealloc = (CoTaskMemRealloc_t)GetProcAddress(ole32, "CoTaskMemRealloc");
-    }
+    // When the symbol handler is given a custom symbol search path, it will no
+    // longer search the default directories (working directory, system root,
+    // etc). But we'd like it to still search those directories, so we'll add
+    // them to our custom search path.
+    //
+    // Append the working directory.
+    strapp(&path, L";.\\");
 
-    // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
-    block = pCoTaskMemRealloc(mem, size);
+    // Append the Windows directory.
+    if (GetWindowsDirectory(windows, MAX_PATH) != 0) {
+        strapp(&path, L";");
+        strapp(&path, windows);
+    }
 
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
+    // Append the system directory.
+    if (GetSystemDirectory(system, MAX_PATH) != 0) {
+        strapp(&path, L";");
+        strapp(&path, system);
+    }
 
-    return block;
+    // Append %_NT_SYMBOL_PATH%.
+    envlen = GetEnvironmentVariable(L"_NT_SYMBOL_PATH", NULL, 0);
+    if (envlen != 0) {
+        env = new WCHAR [envlen];
+        if (GetEnvironmentVariable(L"_NT_SYMBOL_PATH", env, envlen) != 0) {
+            strapp(&path, L";");
+            strapp(&path, env);
+        }
+        delete [] env;
+    }
+
+    //  Append %_NT_ALT_SYMBOL_PATH%.
+    envlen = GetEnvironmentVariable(L"_NT_ALT_SYMBOL_PATH", NULL, 0);
+    if (envlen != 0) {
+        env = new WCHAR [envlen];
+        if (GetEnvironmentVariable(L"_NT_ALT_SYMBOL_PATH", env, envlen) != 0) {
+            strapp(&path, L";");
+            strapp(&path, env);
+        }
+        delete [] env;
+    }
+
+    // Remove any quotes from the path. The symbol handler doesn't like them.
+    pos = 0;
+    length = wcslen(path);
+    while (pos < length) {
+        if (path[pos] == L'\"') {
+            for (index = pos; index < length; index++) {
+                path[index] = path[index + 1];
+            }
+        }
+        pos++;
+    }
+
+    return path;
 }
 
-// _crt80d__calloc_dbg - Calls to _calloc_dbg from msvcr80d.dll are patched
-//   through to this function. This function is just a wrapper around the real
-//   _calloc_dbg that sets appropriate flags to be consulted when the memory is
-//   actually allocated by RtlAllocateHeap.
-//
-//  - size (IN): The size, in bytes, of the memory block to be allocated.
-//
-//  - type (IN): The CRT "use type" of the block to be allocated.
-//
-//  - file (IN): The name of the file from which this function is being called.
-//
-//  - line (IN): The line number, in the above file, at which this function is
-//      being called.
+// configure - Configures VLD using values read from the vld.ini file.
 //
 //  Return Value:
 //
-//    Returns the value returned by _calloc_dbg.
+//    None.
 //
-void* VisualLeakDetector::_crt80d__calloc_dbg (size_t num, size_t size, int type, const char *file, int line)
+VOID VisualLeakDetector::configure ()
 {
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  msvcr80d;
-    tls_t   *tls = vld.gettls();
-
-    // _malloc_dbg is a CRT function and allocates from the CRT heap.
-    tls->flags |= VLD_TLS_CRTALLOC;
+#define BSIZE 64
+    WCHAR        buffer [BSIZE];
+    WCHAR        filename [MAX_PATH];
+    WCHAR        inipath [MAX_PATH];
+    BOOL         keyopen = FALSE;
+    DWORD        length;
+    HKEY         productkey;
+    LONG         regstatus;
+    struct _stat s;
+    DWORD        valuetype;
 
-    if (tls->addrfp == 0x0) {
-        // This is the first call to enter VLD for the current allocation.
-        // Record the current frame pointer.
-        FRAMEPOINTER(fp);
-        tls->addrfp = fp;
+    if (_wstat(L".\\vld.ini", &s) == 0) {
+        // Found a copy of vld.ini in the working directory. Use it.
+        wcsncpy_s(inipath, MAX_PATH, L".\\vld.ini", _TRUNCATE);
     }
-
-    if (pcrt80d__calloc_dbg == NULL) {
-        // This is the first call to this function. Link to the real
-        // _malloc_dbg.
-        msvcr80d = GetModuleHandle(L"msvcr80d.dll");
-        pcrt80d__calloc_dbg = (_calloc_dbg_t)GetProcAddress(msvcr80d, "_calloc_dbg");
+    else {
+        // Get the location of the vld.ini file from the registry.
+        regstatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, VLDREGKEYPRODUCT, 0, KEY_QUERY_VALUE, &productkey);
+        if (regstatus == ERROR_SUCCESS) {
+            keyopen = TRUE;
+            regstatus = RegQueryValueEx(productkey, L"IniFile", NULL, &valuetype, (LPBYTE)&inipath, &length);
+        }
+        if (keyopen) {
+            RegCloseKey(productkey);
+        }
+        if ((regstatus != ERROR_SUCCESS) || (_wstat(inipath, &s) != 0)) {
+            // The location of vld.ini could not be read from the registry. As a
+            // last resort, look in the Windows directory.
+            wcsncpy_s(inipath, MAX_PATH, L"vld.ini", _TRUNCATE);
+        }
     }
 
-    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
-    block = pcrt80d__calloc_dbg(num, size, type, file, line);
+    // Read the boolean options.
+    GetPrivateProfileString(L"Options", L"VLD", L"on", buffer, BSIZE, inipath);
+    if (strtobool(buffer) == FALSE) {
+        m_options |= VLD_OPT_VLDOFF;
+        return;
+    }
 
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
+    GetPrivateProfileString(L"Options", L"AggregateDuplicates", L"", buffer, BSIZE, inipath);
+    if (strtobool(buffer) == TRUE) {
+        m_options |= VLD_OPT_AGGREGATE_DUPLICATES;
+    }
 
-    return block;
-}
+    GetPrivateProfileString(L"Options", L"SelfTest", L"", buffer, BSIZE, inipath);
+    if (strtobool(buffer) == TRUE) {
+        m_options |= VLD_OPT_SELF_TEST;
+    }
 
-// _crt80d__malloc_dbg - Calls to _malloc_dbg from msvcr80d.dll are patched
-//   through to this function. This function is just a wrapper around the real
-//   _malloc_dbg that sets appropriate flags to be consulted when the memory is
-//   actually allocated by RtlAllocateHeap.
-//
-//  - size (IN): The size, in bytes, of the memory block to be allocated.
-//
-//  - type (IN): The CRT "use type" of the block to be allocated.
-//
-//  - file (IN): The name of the file from which this function is being called.
-//
-//  - line (IN): The line number, in the above file, at which this function is
-//      being called.
-//
-//  Return Value:
-//
-//    Returns the value returned by _malloc_dbg.
-//
-void* VisualLeakDetector::_crt80d__malloc_dbg (size_t size, int type, const char *file, int line)
-{
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  msvcr80d;
-    tls_t   *tls = vld.gettls();
+    GetPrivateProfileString(L"Options", L"SlowDebuggerDump", L"", buffer, BSIZE, inipath);
+    if (strtobool(buffer) == TRUE) {
+        m_options |= VLD_OPT_SLOW_DEBUGGER_DUMP;
+    }
 
-    // _malloc_dbg is a CRT function and allocates from the CRT heap.
-    tls->flags |= VLD_TLS_CRTALLOC;
+    GetPrivateProfileString(L"Options", L"StartDisabled", L"", buffer, BSIZE, inipath);
+    if (strtobool(buffer) == TRUE) {
+        m_options |= VLD_OPT_START_DISABLED;
+    }
 
-    if (tls->addrfp == 0x0) {
-        // This is the first call to enter VLD for the current allocation.
-        // Record the current frame pointer.
-        FRAMEPOINTER(fp);
-        tls->addrfp = fp;
+    GetPrivateProfileString(L"Options", L"TraceInternalFrames", L"", buffer, BSIZE, inipath);
+    if (strtobool(buffer) == TRUE) {
+        m_options |= VLD_OPT_TRACE_INTERNAL_FRAMES;
     }
 
-    if (pcrt80d__malloc_dbg == NULL) {
-        // This is the first call to this function. Link to the real
-        // _malloc_dbg.
-        msvcr80d = GetModuleHandle(L"msvcr80d.dll");
-        pcrt80d__malloc_dbg = (_malloc_dbg_t)GetProcAddress(msvcr80d, "_malloc_dbg");
+    // Read the integer configuration options.
+    m_maxdatadump = GetPrivateProfileInt(L"Options", L"MaxDataDump", VLD_DEFAULT_MAX_DATA_DUMP, inipath);
+    m_maxtraceframes = GetPrivateProfileInt(L"Options", L"MaxTraceFrames", VLD_DEFAULT_MAX_TRACE_FRAMES, inipath);
+    if (m_maxtraceframes < 1) {
+        m_maxtraceframes = VLD_DEFAULT_MAX_TRACE_FRAMES;
     }
 
-    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
-    block = pcrt80d__malloc_dbg(size, type, file, line);
+    // Read the force-include module list.
+    GetPrivateProfileString(L"Options", L"ForceIncludeModules", L"", m_forcedmodulelist, MAXMODULELISTLENGTH, inipath);
+    _wcslwr_s(m_forcedmodulelist, MAXMODULELISTLENGTH);
 
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
+    // Read the report destination (debugger, file, or both).
+    GetPrivateProfileString(L"Options", L"ReportFile", L"", filename, MAX_PATH, inipath);
+    if (wcslen(filename) == 0) {
+        wcsncpy_s(filename, MAX_PATH, VLD_DEFAULT_REPORT_FILE_NAME, _TRUNCATE);
+    }
+    _wfullpath(m_reportfilepath, filename, MAX_PATH);
+    GetPrivateProfileString(L"Options", L"ReportTo", L"", buffer, BSIZE, inipath);
+    if (_wcsicmp(buffer, L"both") == 0) {
+        m_options |= (VLD_OPT_REPORT_TO_DEBUGGER | VLD_OPT_REPORT_TO_FILE);
+    }
+    else if (_wcsicmp(buffer, L"file") == 0) {
+        m_options |= VLD_OPT_REPORT_TO_FILE;
+    }
+    else {
+        m_options |= VLD_OPT_REPORT_TO_DEBUGGER;
+    }
 
-    return block;
+    // Read the report file encoding (ascii or unicode).
+    GetPrivateProfileString(L"Options", L"ReportEncoding", L"", buffer, BSIZE, inipath);
+    if (_wcsicmp(buffer, L"unicode") == 0) {
+        m_options |= VLD_OPT_UNICODE_REPORT;
+    }
+    if ((m_options & VLD_OPT_UNICODE_REPORT) && !(m_options & VLD_OPT_REPORT_TO_FILE)) {
+        // If Unicode report encoding is enabled, then the report needs to be
+        // sent to a file because the debugger will not display Unicode
+        // characters, it will display question marks in their place instead.
+        m_options |= VLD_OPT_REPORT_TO_FILE;
+        m_status |= VLD_STATUS_FORCE_REPORT_TO_FILE;
+    }
+
+    // Read the stack walking method.
+    GetPrivateProfileString(L"Options", L"StackWalkMethod", L"", buffer, BSIZE, inipath);
+    if (_wcsicmp(buffer, L"safe") == 0) {
+        m_options |= VLD_OPT_SAFE_STACK_WALK;
+    }
 }
 
-// _crt80d__realloc_dbg - Calls to _realloc_dbg from msvcr80d.dll are patched
-//   through to this function. This function is just a wrapper around the real
-//   _realloc_dbg that sets appropriate flags to be consulted when the memory is
-//   actually allocated by RtlAllocateHeap.
-//
-//  - mem (IN): Pointer to the memory block to be reallocated.
-//
-//  - size (IN): The size of the memory block to reallocate.
-//
-//  - type (IN): The CRT "use type" of the block to be reallocated.
-//
-//  - file (IN): The name of the file from which this function is being called.
-//
-//  - line (IN): The line number, in the above filel, at which this function is
-//      being called.
+// enabled - Determines if memory leak detection is enabled for the current
+//   thread.
 //
 //  Return Value:
 //
-//    Returns the value returned by _realloc_dbg.
+//    Returns true if Visual Leak Detector is enabled for the current thread.
+//    Otherwise, returns false.
 //
-void* VisualLeakDetector::_crt80d__realloc_dbg (void *mem, size_t size, int type, const char *file, int line)
+BOOL VisualLeakDetector::enabled ()
 {
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  msvcr80d;
-    tls_t   *tls = vld.gettls();
-
-    // _realloc_dbg is a CRT function and allocates from the CRT heap.
-    tls->flags |= VLD_TLS_CRTALLOC;
+    tls_t *tls = vld.gettls();
 
-    if (tls->addrfp == 0x0) {
-        // This is the first call to enter VLD for the current allocation.
-        // Record the current frame pointer.
-        FRAMEPOINTER(fp);
-        tls->addrfp = fp;
+    if (!(m_status & VLD_STATUS_INSTALLED)) {
+        // Memory leak detection is not yet enabled because VLD is still
+        // initializing.
+        return FALSE;
     }
 
-    if (pcrt80d__realloc_dbg == NULL) {
-        // This is the first call to this function. Link to the real
-        // _realloc_dbg.
-        msvcr80d = GetModuleHandle(L"msvcr80d.dll");
-        pcrt80d__realloc_dbg = (_realloc_dbg_t)GetProcAddress(msvcr80d, "_realloc_dbg");
+    if (!(tls->flags & VLD_TLS_DISABLED) && !(tls->flags & VLD_TLS_ENABLED)) {
+        // The enabled/disabled state for the current thread has not been 
+        // initialized yet. Use the default state.
+        if (m_options & VLD_OPT_START_DISABLED) {
+            tls->flags |= VLD_TLS_DISABLED;
+        }
+        else {
+            tls->flags |= VLD_TLS_ENABLED;
+        }
     }
 
-    // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
-    block = pcrt80d__realloc_dbg(mem, size, type, file, line);
-
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
-
-    return block;
+    return ((tls->flags & VLD_TLS_ENABLED) != 0);
 }
 
-// _crt80d__scalar_new_dbg - Calls to the CRT's debug scalar new operator from
-//   msvcr80d.dll are patched through to this function. This function is just a
-//   wrapper around the real CRT debug scalar new operator that sets appropriate
-//   flags to be consulted when the memory is actually allocated by
-//   RtlAllocateHeap.
+// eraseduplicates - Erases, from the block maps, blocks that appear to be
+//   duplicate leaks of an already identified leak.
 //
-//  - size (IN): The size, in bytes, of the memory block to be allocated.
-//
-//  - type (IN): The CRT "use type" of the block to be allocated.
-//
-//  - file (IN): The name of the file from which this function is being called.
-//
-//  - line (IN): The line number, in the above file, at which this function is
-//      being called.
+//  - element (IN): BlockMap Iterator referencing the block of which to search
+//      for duplicates.
 //
 //  Return Value:
 //
-//    Returns the value returned by the CRT debug scalar new operator.
+//    Returns the number of duplicate blocks erased from the block map.
 //
-void* VisualLeakDetector::_crt80d__scalar_new_dbg (unsigned int size, int type, const char *file, int line)
+SIZE_T VisualLeakDetector::eraseduplicates (const BlockMap::Iterator &element)
 {
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  msvcr80d;
-    tls_t   *tls = vld.gettls();
-
-    // The debug new operator is a CRT function and allocates from the CRT heap.
-    tls->flags |= VLD_TLS_CRTALLOC;
+    BlockMap::Iterator  blockit;
+    BlockMap           *blockmap;
+    blockinfo_t        *elementinfo;
+    SIZE_T              erased = 0;
+    HeapMap::Iterator   heapit;
+    blockinfo_t        *info;
+    BlockMap::Iterator  previt;
 
-    if (tls->addrfp == 0x0) {
-        // This is the first call to enter VLD for the current allocation.
-        // Record the current frame pointer.
-        FRAMEPOINTER(fp);
-        tls->addrfp = fp;
-    }
+    elementinfo = (*element).second;
 
-    if (pcrt80d__scalar_new_dbg == NULL) {
-        // This is the first call to this function. Link to the real CRT debug
-        // new operator.
-        msvcr80d = GetModuleHandle(L"msvcr80d.dll");
-        pcrt80d__scalar_new_dbg = (crt_new_dbg_t)GetProcAddress(msvcr80d, "??2@YAPAXIHPBDH@Z");
+    // Iteratate through all block maps, looking for blocks with the same size
+    // and callstack as the specified element.
+    for (heapit = m_heapmap->begin(); heapit != m_heapmap->end(); ++heapit) {
+        blockmap = &(*heapit).second->blockmap;
+        for (blockit = blockmap->begin(); blockit != blockmap->end(); ++blockit) {
+            if (blockit == element) {
+                // Don't delete the element of which we are searching for
+                // duplicates.
+                continue;
+            }
+            info = (*blockit).second;
+            if ((info->size == elementinfo->size) && (*(info->callstack) == *(elementinfo->callstack))) {
+                // Found a duplicate. Erase it.
+                delete info->callstack;
+                delete info;
+                previt = blockit - 1;
+                blockmap->erase(blockit);
+                blockit = previt;
+                erased++;
+            }
+        }
     }
 
-    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
-    block = pcrt80d__scalar_new_dbg(size, type, file, line);
-
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
-
-    return block;
+    return erased;
 }
 
-// _crt80d__vector_new_dbg - Calls to the CRT's debug vector new operator from
-//   msvcr80d.dll are patched through to this function. This function is just a
-//   wrapper around the real CRT debug vector new operator that sets appropriate
-//   flags to be consulted when the memory is actually allocated by
-//   RtlAllocateHeap.
-//
-//  - size (IN): The size, in bytes, of the memory block to be allocated.
-//
-//  - type (IN): The CRT "use type" of the block to be allocated.
-//
-//  - file (IN): The name of the file from which this function is being called.
-//
-//  - line (IN): The line number, in the above file, at which this function is
-//      being called.
+// gettls - Obtains the thread local storage structure for the calling thread.
 //
 //  Return Value:
 //
-//    Returns the value returned by the CRT debug vector new operator.
+//    Returns a pointer to the thread local storage structure. (This function
+//    always succeeds).
 //
-void* VisualLeakDetector::_crt80d__vector_new_dbg (unsigned int size, int type, const char *file, int line)
+tls_t* VisualLeakDetector::gettls ()
 {
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  msvcr80d;
-    tls_t   *tls = vld.gettls();
-
-    // The debug new operator is a CRT function and allocates from the CRT heap.
-    tls->flags |= VLD_TLS_CRTALLOC;
+    tls_t *tls;
+    
+    // Get the pointer to this thread's thread local storage structure.
+    tls = (tls_t*)TlsGetValue(m_tlsindex);
+    assert(GetLastError() == ERROR_SUCCESS);
 
-    if (tls->addrfp == 0x0) {
-        // This is the first call to enter VLD for the current allocation.
-        // Record the current frame pointer.
-        FRAMEPOINTER(fp);
-        tls->addrfp = fp;
-    }
+    if (tls == NULL) {
+        // This thread's thread local storage structure has not been allocated.
+        tls = new tls_t;
+        TlsSetValue(m_tlsindex, tls);
+        tls->addrfp = 0x0;
+        tls->flags = 0x0;
+        tls->threadid = GetCurrentThreadId();
 
-    if (pcrt80d__vector_new_dbg == NULL) {
-        // This is the first call to this function. Link to the real CRT debug
-        // new operator.
-        msvcr80d = GetModuleHandle(L"msvcr80d.dll");
-        pcrt80d__vector_new_dbg = (crt_new_dbg_t)GetProcAddress(msvcr80d, "??_U@YAPAXIHPBDH@Z");
+        // Add this thread's TLS to the TlsSet.
+        EnterCriticalSection(&m_tlslock);
+        m_tlsset->insert(tls);
+        LeaveCriticalSection(&m_tlslock);
     }
 
-    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
-    block = pcrt80d__vector_new_dbg(size, type, file, line);
-
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
-
-    return block;
+    return tls;
 }
 
-// _crt80d_calloc - Calls to calloc from msvcr80d.dll are patched through to
-//   this function. This function is just a wrapper around the real calloc that
-//   sets appropriate flags to be consulted when the memory is actually
-//   allocated by RtlAllocateHeap.
+// mapblock - Tracks memory allocations. Information about allocated blocks is
+//   collected and then the block is mapped to this information.
 //
-//  - num (IN): The number of blocks, of size 'size', to be allocated.
+//  - heap (IN): Handle to the heap from which the block has been allocated.
 //
-//  - size (IN): The size, in bytes, of the memory block to be allocated.
+//  - mem (IN): Pointer to the memory block being allocated.
+//
+//  - size (IN): Size, in bytes, of the memory block being allocated.
+//
+//  - framepointer (IN): Framepointer at the time this allocation first entered
+//      VLD's code. This is used from determining the starting point for the
+//      stack trace.
+//
+//  - crtalloc (IN): Should be set to TRUE if this allocation is a CRT memory
+//      block. Otherwise should be FALSE.
 //
 //  Return Value:
 //
-//    Returns the valued returned from calloc.
+//    None.
 //
-void* VisualLeakDetector::_crt80d_calloc (size_t num, size_t size)
+VOID VisualLeakDetector::mapblock (HANDLE heap, LPCVOID mem, SIZE_T size, SIZE_T framepointer, BOOL crtalloc)
 {
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  msvcr80d;
-    tls_t   *tls = vld.gettls();
-
-    // malloc is a CRT function and allocates from the CRT heap.
-    tls->flags |= VLD_TLS_CRTALLOC;
+    blockinfo_t        *blockinfo;
+    BlockMap::Iterator  blockit;
+    BlockMap           *blockmap;
+    HeapMap::Iterator   heapit;
+    static SIZE_T       serialnumber = 0;
 
-    if (tls->addrfp == 0x0) {
-        // This is the first call to enter VLD for the current allocation.
-        // Record the current frame pointer.
-        FRAMEPOINTER(fp);
-        tls->addrfp = fp;
+    // Record the block's information.
+    blockinfo = new blockinfo_t;
+    if (m_options & VLD_OPT_SAFE_STACK_WALK) {
+        blockinfo->callstack = new SafeCallStack;
     }
-
-    if (pcrt80d_calloc == NULL) {
-        // This is the first call to this function. Link to the real malloc.
-        msvcr80d = GetModuleHandle(L"msvcr80d.dll");
-        pcrt80d_calloc = (calloc_t)GetProcAddress(msvcr80d, "calloc");
+    else {
+        blockinfo->callstack = new FastCallStack;
     }
+    if (m_options & VLD_OPT_TRACE_INTERNAL_FRAMES) {
+        // Passing NULL for the frame pointer argument will force the stack
+        // trace to begin at the current frame.
+        blockinfo->callstack->getstacktrace(m_maxtraceframes, NULL);
+    }
+    else {
+        // Start the stack trace at the call that first entered VLD's code.
+        blockinfo->callstack->getstacktrace(m_maxtraceframes, (SIZE_T*)framepointer);
+    }
+    blockinfo->serialnumber = serialnumber++;
+    blockinfo->size = size;
 
-    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
-    block = pcrt80d_calloc(num, size);
-
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
-
-    return block;
+    // Insert the block's information into the block map.
+    EnterCriticalSection(&m_maplock);
+    heapit = m_heapmap->find(heap);
+    if (heapit == m_heapmap->end()) {
+        // We haven't mapped this heap to a block map yet. Do it now.
+        mapheap(heap);
+        heapit = m_heapmap->find(heap);
+        assert(heapit != m_heapmap->end());
+    }
+    if (crtalloc == TRUE) {
+        // The heap that this block was allocated from is a CRT heap.
+        (*heapit).second->flags |= VLD_HEAP_CRT;
+    }
+    blockmap = &(*heapit).second->blockmap;
+    blockit = blockmap->insert(mem, blockinfo);
+    if (blockit == blockmap->end()) {
+        // A block with this address has already been allocated. The
+        // previously allocated block must have been freed (probably by some
+        // mechanism unknown to VLD), or the heap wouldn't have allocated it
+        // again. Replace the previously allocated info with the new info.
+        blockit = blockmap->find(mem);
+        delete (*blockit).second->callstack;
+        delete (*blockit).second;
+        blockmap->erase(blockit);
+        blockmap->insert(mem, blockinfo);
+    }
+    LeaveCriticalSection(&m_maplock);
 }
 
-// _crt80d_malloc - Calls to malloc from msvcr80d.dll are patched through to
-//   this function. This function is just a wrapper around the real malloc that
-//   sets appropriate flags to be consulted when the memory is actually
-//   allocated by RtlAllocateHeap.
+// mapheap - Tracks heap creation. Creates a block map for tracking individual
+//   allocations from the newly created heap and then maps the heap to this
+//   block map.
 //
-//  - size (IN): The size, in bytes, of the memory block to be allocated.
+//  - heap (IN): Handle to the newly created heap.
 //
 //  Return Value:
 //
-//    Returns the valued returned from malloc.
+//    None.
 //
-void* VisualLeakDetector::_crt80d_malloc (size_t size)
+VOID VisualLeakDetector::mapheap (HANDLE heap)
 {
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  msvcr80d;
-    tls_t   *tls = vld.gettls();
-
-    // malloc is a CRT function and allocates from the CRT heap.
-    tls->flags |= VLD_TLS_CRTALLOC;
-
-    if (tls->addrfp == 0x0) {
-        // This is the first call to enter VLD for the current allocation.
-        // Record the current frame pointer.
-        FRAMEPOINTER(fp);
-        tls->addrfp = fp;
-    }
+    heapinfo_t        *heapinfo;
+    HeapMap::Iterator  heapit;
 
-    if (pcrt80d_malloc == NULL) {
-        // This is the first call to this function. Link to the real malloc.
-        msvcr80d = GetModuleHandle(L"msvcr80d.dll");
-        pcrt80d_malloc = (malloc_t)GetProcAddress(msvcr80d, "malloc");
+    // Create a new block map for this heap and insert it into the heap map.
+    heapinfo = new heapinfo_t;
+    heapinfo->blockmap.reserve(BLOCKMAPRESERVE);
+    heapinfo->flags = 0x0;
+    EnterCriticalSection(&m_maplock);
+    heapit = m_heapmap->insert(heap, heapinfo);
+    if (heapit == m_heapmap->end()) {
+        // Somehow this heap has been created twice without being destroyed,
+        // or at least it was destroyed without VLD's knowledge. Unmap the heap
+        // from the existing heapinfo, and remap it to the new one.
+        report(L"WARNING: Visual Leak Detector detected a duplicate heap (" ADDRESSFORMAT L").\n", heap);
+        heapit = m_heapmap->find(heap);
+        unmapheap((*heapit).first);
+        m_heapmap->insert(heap, heapinfo);
     }
-
-    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
-    block = pcrt80d_malloc(size);
-
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
-
-    return block;
+    LeaveCriticalSection(&m_maplock);
 }
 
-// _crt80d_realloc - Calls to realloc from msvcr80d.dll are patched through to
-//   this function. This function is just a wrapper around the real realloc that
-//   sets appropriate flags to be consulted when the memory is actually
-//   allocated by RtlAllocateHeap.
+// remapblock - Tracks reallocations. Unmaps a block from its previously
+//   collected information and remaps it to updated information.
 //
-//  - mem (IN): Pointer to the memory block to reallocate.
+//  Note: If the block itself remains at the same address, then the block's
+//   information can simply be updated rather than having to actually erase and
+//   reinsert the block.
 //
-//  - size (IN): Size of the memory block to reallocate.
+//  - heap (IN): Handle to the heap from which the memory is being reallocated.
 //
-//  Return Value:
+//  - mem (IN): Pointer to the memory block being reallocated.
 //
-//    Returns the value returned from realloc.
+//  - newmem (IN): Pointer to the memory block being returned to the caller
+//      that requested the reallocation. This pointer may or may not be the same
+//      as the original memory block (as pointed to by "mem").
 //
-void* VisualLeakDetector::_crt80d_realloc (void *mem, size_t size)
+//  - size (IN): Size, in bytes, of the new memory block.
+//
+//  - framepointer (IN): The frame pointer at which this reallocation entered
+//      VLD's code. Used for determining the starting point of the stack trace.
+//
+//  - crtalloc (IN): Should be set to TRUE if this reallocation is for a CRT
+//      memory block. Otherwise should be set to FALSE.
+//
+//  Return Value:
+//
+//    None.
+//
+VOID VisualLeakDetector::remapblock (HANDLE heap, LPCVOID mem, LPCVOID newmem, SIZE_T size, SIZE_T framepointer,
+                                     BOOL crtalloc)
 {
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  msvcr80d;
-    tls_t   *tls = vld.gettls();
-
-    // realloc is a CRT function and allocates from the CRT heap.
-    tls->flags |= VLD_TLS_CRTALLOC;
+    BlockMap::Iterator   blockit;
+    BlockMap            *blockmap;
+    HeapMap::Iterator    heapit;
+    blockinfo_t         *info;
 
-    if (tls->addrfp == 0x0) {
-        // This is the first call to enter VLD for the current allocation.
-        // Record the current frame pointer.
-        FRAMEPOINTER(fp);
-        tls->addrfp = fp;
+    if (newmem != mem) {
+        // The block was not reallocated in-place. Instead the old block was
+        // freed and a new block allocated to satisfy the new size.
+        unmapblock(heap, mem);
+        mapblock(heap, newmem, size, framepointer, crtalloc);
+        return;
     }
 
-    if (pcrt80d_realloc == NULL) {
-        // This is the first call to this function. Link to the real realloc.
-        msvcr80d = GetModuleHandle(L"msvcr80d.dll");
-        pcrt80d_realloc = (realloc_t)GetProcAddress(msvcr80d, "realloc");
+    // The block was reallocated in-place. Find the existing blockinfo_t
+    // entry in the block map and update it with the new callstack and size.
+    EnterCriticalSection(&m_maplock);
+    heapit = m_heapmap->find(heap);
+    if (heapit == m_heapmap->end()) {
+        // We haven't mapped this heap to a block map yet. Obviously the
+        // block has also not been mapped to a blockinfo_t entry yet either,
+        // so treat this reallocation as a brand-new allocation (this will
+        // also map the heap to a new block map).
+        mapblock(heap, newmem, size, framepointer, crtalloc);
+        LeaveCriticalSection(&m_maplock);
+        return;
     }
 
-    // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
-    block = pcrt80d_realloc(mem, size);
+    // Find the block's blockinfo_t structure so that we can update it.
+    blockmap = &(*heapit).second->blockmap;
+    blockit = blockmap->find(mem);
+    if (blockit == blockmap->end()) {
+        // The block hasn't been mapped to a blockinfo_t entry yet.
+        // Treat this reallocation as a new allocation.
+        mapblock(heap, newmem, size, framepointer, crtalloc);
+        LeaveCriticalSection(&m_maplock);
+        return;
+    }
 
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
+    // Found the blockinfo_t entry for this block. Update it with
+    // a new callstack and new size.
+    info = (*blockit).second;
+    info->callstack->clear();
+    if (crtalloc) {
+        // The heap that this block was allocated from is a CRT heap.
+        (*heapit).second->flags |= VLD_HEAP_CRT;
+    }
+    LeaveCriticalSection(&m_maplock);
 
-    return block;
+    // Update the block's callstack and size.
+    if (m_options & VLD_OPT_TRACE_INTERNAL_FRAMES) {
+        // Passing NULL for the frame pointer argument will force
+        // the stack trace to begin at the current frame.
+        info->callstack->getstacktrace(m_maxtraceframes, NULL);
+    }
+    else {
+        // Start the stack trace at the call that first entered
+        // VLD's code.
+        info->callstack->getstacktrace(m_maxtraceframes, (SIZE_T*)framepointer);
+    }
+    info->size = size;
 }
 
-// _crt80d_scalar_new - Calls to the CRT's scalar new operator from msvcr80d.dll
-//   are patched through to this function. This function is just a wrapper
-//   around the real CRT scalar new operator that sets appropriate flags to be
-//   consulted when the memory is actually allocated by RtlAllocateHeap.
-//
-//  - size (IN): The size, in bytes, of the memory block to be allocated.
+// reportconfig - Generates a brief report summarizing Visual Leak Detector's
+//   configuration, as loaded from the vld.ini file.
 //
 //  Return Value:
 //
-//    Returns the value returned by the CRT scalar new operator.
+//    None.
 //
-void* VisualLeakDetector::_crt80d_scalar_new (unsigned int size)
+VOID VisualLeakDetector::reportconfig ()
 {
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  msvcr80d;
-    tls_t   *tls = vld.gettls();
-
-    // The new operator is a CRT function and allocates from the CRT heap.
-    tls->flags |= VLD_TLS_CRTALLOC;
-
-    if (tls->addrfp == 0x0) {
-        // This is the first call to enter VLD for the current allocation.
-        // Record the current frame pointer.
-        FRAMEPOINTER(fp);
-        tls->addrfp = fp;
+    if (m_options & VLD_OPT_AGGREGATE_DUPLICATES) {
+        report(L"    Aggregating duplicate leaks.\n");
     }
-
-    if (pcrt80d_scalar_new == NULL) {
-        // This is the first call to this function. Link to the real CRT new
-        // operator.
-        msvcr80d = GetModuleHandle(L"msvcr80d.dll");
-        pcrt80d_scalar_new = (new_t)GetProcAddress(msvcr80d, "??2@YAPAXI@Z");
+    if (wcslen(m_forcedmodulelist) != 0) {
+        report(L"    Forcing inclusion of these modules in leak detection: %s\n", m_forcedmodulelist);
+    }
+    if (m_maxdatadump != VLD_DEFAULT_MAX_DATA_DUMP) {
+        if (m_maxdatadump == 0) {
+            report(L"    Suppressing data dumps.\n");
+        }
+        else {
+            report(L"    Limiting data dumps to %lu bytes.\n", m_maxdatadump);
+        }
+    }
+    if (m_maxtraceframes != VLD_DEFAULT_MAX_TRACE_FRAMES) {
+        report(L"    Limiting stack traces to %u frames.\n", m_maxtraceframes);
+    }
+    if (m_options & VLD_OPT_UNICODE_REPORT) {
+        report(L"    Generating a Unicode (UTF-16) encoded report.\n");
+    }
+    if (m_options & VLD_OPT_REPORT_TO_FILE) {
+        if (m_options & VLD_OPT_REPORT_TO_DEBUGGER) {
+            report(L"    Outputting the report to the debugger and to %s\n", m_reportfilepath);
+        }
+        else {
+            report(L"    Outputting the report to %s\n", m_reportfilepath);
+        }
+    }
+    if (m_options & VLD_OPT_SLOW_DEBUGGER_DUMP) {
+        report(L"    Outputting the report to the debugger at a slower rate.\n");
+    }
+    if (m_options & VLD_OPT_SAFE_STACK_WALK) {
+        report(L"    Using the \"safe\" (but slow) stack walking method.\n");
+    }
+    if (m_options & VLD_OPT_SELF_TEST) {
+        report(L"    Perfoming a memory leak self-test.\n");
+    }
+    if (m_options & VLD_OPT_START_DISABLED) {
+        report(L"    Starting with memory leak detection disabled.\n");
+    }
+    if (m_options & VLD_OPT_TRACE_INTERNAL_FRAMES) {
+        report(L"    Including heap and VLD internal frames in stack traces.\n");
     }
-
-    // Do tha allocation. The block will be mapped by _RtlAllocateHeap.
-    block = pcrt80d_scalar_new(size);
-
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
-
-    return block;
 }
 
-// _crt80d_vector_new - Calls to the CRT's vector new operator from msvcr80d.dll
-//   are patched through to this function. This function is just a wrapper
-//   around the real CRT vector new operator that sets appropriate flags to be
-//   consulted when the memory is actually allocated by RtlAllocateHeap.
+// reportleaks - Generates a memory leak report for the specified heap.
 //
-//  - size (IN): The size, in bytes, of the memory block to be allocated.
+//  - heap (IN): Handle to the heap for which to generate a memory leak
+//      report.
 //
 //  Return Value:
 //
-//    Returns the value returned by the CRT vector new operator.
+//    None.
 //
-void* VisualLeakDetector::_crt80d_vector_new (unsigned int size)
+VOID VisualLeakDetector::reportleaks (HANDLE heap)
 {
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  msvcr80d;
-    tls_t   *tls = vld.gettls();
-
-    // The new operator is a CRT function and allocates from the CRT heap.
-    tls->flags |= VLD_TLS_CRTALLOC;
+    LPCVOID              address;
+    LPCVOID              block;
+    BlockMap::Iterator   blockit;
+    BlockMap            *blockmap;
+    crtdbgblockheader_t *crtheader;
+    SIZE_T               duplicates;
+    heapinfo_t          *heapinfo;
+    HeapMap::Iterator    heapit;
+    blockinfo_t         *info;
+    SIZE_T               size;
 
-    if (tls->addrfp == 0x0) {
-        // This is the first call to enter VLD for the current allocation.
-        // Record the current frame pointer.
-        FRAMEPOINTER(fp);
-        tls->addrfp = fp;
+    // Find the heap's information (blockmap, etc).
+    EnterCriticalSection(&m_maplock);
+    heapit = m_heapmap->find(heap);
+    if (heapit == m_heapmap->end()) {
+        // Nothing is allocated from this heap. No leaks.
+        LeaveCriticalSection(&m_maplock);
+        return;
     }
 
-    if (pcrt80d_vector_new == NULL) {
-        // This is the first call to this function. Link to the real CRT new
-        // operator.
-        msvcr80d = GetModuleHandle(L"msvcr80d.dll");
-        pcrt80d_vector_new = (new_t)GetProcAddress(msvcr80d, "??_U@YAPAXI@Z");
+    heapinfo = (*heapit).second;
+    blockmap = &heapinfo->blockmap;
+    for (blockit = blockmap->begin(); blockit != blockmap->end(); ++blockit) {
+        // Found a block which is still in the BlockMap. We've identified a
+        // potential memory leak.
+        block = (*blockit).first;
+        info = (*blockit).second;
+        address = block;
+        size = info->size;
+        if (heapinfo->flags & VLD_HEAP_CRT) {
+            // This block is allocated to a CRT heap, so the block has a CRT
+            // memory block header prepended to it.
+            crtheader = (crtdbgblockheader_t*)block;
+            if (CRT_USE_TYPE(crtheader->use) == CRT_USE_INTERNAL) {
+                // This block is marked as being used internally by the CRT.
+                // The CRT will free the block after VLD is destroyed.
+                continue;
+            }
+            // The CRT header is more or less transparent to the user, so
+            // the information about the contained block will probably be
+            // more useful to the user. Accordingly, that's the information
+            // we'll include in the report.
+            address = CRTDBGBLOCKDATA(block);
+            size = crtheader->size;
+        }
+        // It looks like a real memory leak.
+        if (m_leaksfound == 0) {
+            report(L"WARNING: Visual Leak Detector detected memory leaks!\n");
+        }
+        m_leaksfound++;
+        report(L"---------- Block %ld at " ADDRESSFORMAT L": %u bytes ----------\n", info->serialnumber, address, size);
+        if (m_options & VLD_OPT_AGGREGATE_DUPLICATES) {
+            // Aggregate all other leaks which are duplicates of this one
+            // under this same heading, to cut down on clutter.
+            duplicates = eraseduplicates(blockit);
+            if (duplicates) {
+                report(L"A total of %lu leaks match this size and call stack. Showing only the first one.\n",
+                       duplicates + 1);
+                m_leaksfound += duplicates;
+            }
+        }
+        // Dump the call stack.
+        report(L"  Call Stack:\n");
+        info->callstack->dump(m_options & VLD_OPT_TRACE_INTERNAL_FRAMES);
+        // Dump the data in the user data section of the memory block.
+        if (m_maxdatadump != 0) {
+            report(L"  Data:\n");
+            if (m_options & VLD_OPT_UNICODE_REPORT) {
+                dumpmemoryw(address, (m_maxdatadump < size) ? m_maxdatadump : size);
+            }
+            else {
+                dumpmemorya(address, (m_maxdatadump < size) ? m_maxdatadump : size);
+            }
+        }
+        report(L"\n");
     }
 
-    // Do tha allocation. The block will be mapped by _RtlAllocateHeap.
-    block = pcrt80d_vector_new(size);
-
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
-
-    return block;
+    LeaveCriticalSection(&m_maplock);
 }
 
-// _crtd__calloc_dbg - Calls to _calloc_dbg from msvcrtd.dll are patched through
-//   to this function. This function is just a wrapper around the real
-//   _calloc_dbg that sets appropriate flags to be consulted when the memory is
-//   actually allocated by RtlAllocateHeap.
+// unmapblock - Tracks memory blocks that are freed. Unmaps the specified block
+//   from the block's information, relinquishing internally allocated resources.
 //
-//  - num (IN): The number of blocks, of size 'size', to be allocated.
+//  - heap (IN): Handle to the heap to which this block is being freed.
 //
-//  - size (IN): The size, in bytes, of the memory block to be allocated.
+//  - mem (IN): Pointer to the memory block being freed.
 //
-//  - type (IN): The CRT "use type" of the block to be allocated.
+//  Return Value:
 //
-//  - file (IN): The name of the file from which this function is being called.
+//    None.
 //
-//  - line (IN): The line number, in the above file, at which this function is
-//      being called.
+VOID VisualLeakDetector::unmapblock (HANDLE heap, LPCVOID mem)
+{
+    BlockMap::Iterator  blockit;
+    BlockMap           *blockmap;
+    HeapMap::Iterator   heapit;
+    blockinfo_t        *info;
+
+    // Find this heap's block map.
+    EnterCriticalSection(&m_maplock);
+    heapit = m_heapmap->find(heap);
+    if (heapit == m_heapmap->end()) {
+        // We don't have a block map for this heap. We must not have monitored
+        // this allocation (probably happened before VLD was initialized).
+        LeaveCriticalSection(&m_maplock);
+        return;
+    }
+
+    // Find this block in the block map.
+    blockmap = &(*heapit).second->blockmap;
+    blockit = blockmap->find(mem);
+    if (blockit == blockmap->end()) {
+        // This block is not in the block map. We must not have monitored this
+        // allocation (probably happened before VLD was initialized).
+        LeaveCriticalSection(&m_maplock);
+        return;
+    }
+
+    // Free the blockinfo_t structure and erase it from the block map.
+    info = (*blockit).second;
+    delete info->callstack;
+    delete info;
+    blockmap->erase(blockit);
+    LeaveCriticalSection(&m_maplock);
+}
+
+// unmapheap - Tracks heap destruction. Unmaps the specified heap from its block
+//   map. The block map is cleared and deleted, relinquishing internally
+//   allocated resources.
+//
+//  - heap (IN): Handle to the heap which is being destroyed.
 //
 //  Return Value:
 //
-//    Returns the value returned by _calloc_dbg.
+//    None.
 //
-void* VisualLeakDetector::_crtd__calloc_dbg (size_t num, size_t size, int type, const char *file, int line)
+VOID VisualLeakDetector::unmapheap (HANDLE heap)
 {
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  msvcrtd;
-    tls_t   *tls = vld.gettls();
-
-    // _malloc_dbg is a CRT function and allocates from the CRT heap.
-    tls->flags |= VLD_TLS_CRTALLOC;
+    BlockMap::Iterator  blockit;
+    BlockMap           *blockmap;
+    heapinfo_t         *heapinfo;
+    HeapMap::Iterator   heapit;
 
-    if (tls->addrfp == 0x0) {
-        // This is the first call to enter VLD for the current allocation.
-        // Record the current frame pointer.
-        FRAMEPOINTER(fp);
-        tls->addrfp = fp;
+    // Find this heap's block map.
+    EnterCriticalSection(&m_maplock);
+    heapit = m_heapmap->find(heap);
+    if (heapit == m_heapmap->end()) {
+        // This heap hasn't been mapped. We must not have monitored this heap's
+        // creation (probably happened before VLD was initialized).
+        LeaveCriticalSection(&m_maplock);
+        return;
     }
 
-    if (pcrtd__calloc_dbg == NULL) {
-        // This is the first call to this function. Link to the real
-        // _malloc_dbg.
-        msvcrtd = GetModuleHandle(L"msvcrtd.dll");
-        pcrtd__calloc_dbg = (_calloc_dbg_t)GetProcAddress(msvcrtd, "_calloc_dbg");
+    // Free all of the blockinfo_t structures stored in the block map.
+    heapinfo = (*heapit).second;
+    blockmap = &heapinfo->blockmap;
+    for (blockit = blockmap->begin(); blockit != blockmap->end(); ++blockit) {
+        delete (*blockit).second->callstack;
+        delete (*blockit).second;
     }
+    delete heapinfo;
 
-    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
-    block = pcrtd__calloc_dbg(num, size, type, file, line);
+    // Remove this heap's block map from the heap map.
+    m_heapmap->erase(heapit);
+    LeaveCriticalSection(&m_maplock);
+}
 
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
 
-    return block;
-}
+////////////////////////////////////////////////////////////////////////////////
+//
+// Static Leak Detection Functions (Callbacks)
+//
+////////////////////////////////////////////////////////////////////////////////
 
-// _crtd__malloc_dbg - Calls to _malloc_dbg from msvcrtd.dll are patched through
-//   to this function. This function is just a wrapper around the real
-//   _malloc_dbg that sets appropriate flags to be consulted when the memory is
-//   actually allocated by RtlAllocateHeap.
+// addloadedmodule - Callback function for EnumerateLoadedModules64. This
+//   function records information about every module loaded in the process,
+//   each time adding the module's information to the provided ModuleSet (the
+//   "context" parameter).
 //
-//  - size (IN): The size, in bytes, of the memory block to be allocated.
+//   When EnumerateLoadedModules64 has finished calling this function for each
+//   loaded module, then the resulting ModuleSet can be used at any time to get
+//   information about any modules loaded into the process.
 //
-//  - type (IN): The CRT "use type" of the block to be allocated.
+//   - modulepath (IN): The fully qualified path from where the module was
+//       loaded.
 //
-//  - file (IN): The name of the file from which this function is being called.
+//   - modulebase (IN): The base address at which the module has been loaded.
 //
-//  - line (IN): The line number, in the above file, at which this function is
-//      being called.
+//   - modulesize (IN): The size, in bytes, of the loaded module.
+//
+//   - context (IN): Pointer to the ModuleSet to which information about each
+//       module is to be added.
 //
 //  Return Value:
 //
-//    Returns the value returned by _malloc_dbg.
+//    Always returns TRUE, which tells EnumerateLoadedModules64 to continue
+//    enumerating.
 //
-void* VisualLeakDetector::_crtd__malloc_dbg (size_t size, int type, const char *file, int line)
+BOOL VisualLeakDetector::addloadedmodule (PCWSTR modulepath, DWORD64 modulebase, ULONG modulesize, PVOID context)
 {
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  msvcrtd;
-    tls_t   *tls = vld.gettls();
+    size_t        count;
+    patchentry_t *entry;
+    CHAR          extension [_MAX_EXT];
+    CHAR          filename [_MAX_FNAME];
+    UINT          index;
+    moduleinfo_t  moduleinfo;
+    LPSTR         modulenamea;
+    LPSTR         modulepatha;
+    ModuleSet*    newmodules = (ModuleSet*)context;
+    SIZE_T        size;
+    UINT          tablesize = sizeof(m_patchtable) / sizeof(patchentry_t);
 
-    // _malloc_dbg is a CRT function and allocates from the CRT heap.
-    tls->flags |= VLD_TLS_CRTALLOC;
+    // Convert the module path to ASCII.
+    size = wcslen(modulepath) + 1;
+    modulepatha = new CHAR [size];
+    wcstombs_s(&count, modulepatha, size, modulepath, _TRUNCATE);
 
-    if (tls->addrfp == 0x0) {
-        // This is the first call to enter VLD for the current allocation.
-        // Record the current frame pointer.
-        FRAMEPOINTER(fp);
-        tls->addrfp = fp;
-    }
+    // Extract just the filename and extension from the module path.
+    _splitpath_s(modulepatha, NULL, 0, NULL, 0, filename, _MAX_FNAME, extension, _MAX_EXT);
+    size = strlen(filename) + strlen(extension) + 1;
+    modulenamea = new CHAR [size];
+    strncpy_s(modulenamea, size, filename, _TRUNCATE);
+    strncat_s(modulenamea, size, extension, _TRUNCATE);
+    _strlwr_s(modulenamea, size);
 
-    if (pcrtd__malloc_dbg == NULL) {
-        // This is the first call to this function. Link to the real
-        // _malloc_dbg.
-        msvcrtd = GetModuleHandle(L"msvcrtd.dll");
-        pcrtd__malloc_dbg = (_malloc_dbg_t)GetProcAddress(msvcrtd, "_malloc_dbg");
+    if (_stricmp(modulenamea, "vld.dll") == 0) {
+        // Record Visual Leak Detector's own base address.
+        vld.m_vldbase = (HMODULE)modulebase;
+    }
+    else {
+        // See if this is a module listed in the patch table. If it is, update
+        // the corresponding patch table entries' module base address.
+        for (index = 0; index < tablesize; index++) {
+            entry = &m_patchtable[index];
+            if (_stricmp(entry->exportmodulename, modulenamea) == 0) {
+                entry->modulebase = (SIZE_T)modulebase;
+            }
+        }
     }
 
-    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
-    block = pcrtd__malloc_dbg(size, type, file, line);
+    // Record the module's information and store it in the set.
+    moduleinfo.addrlow  = (SIZE_T)modulebase;
+    moduleinfo.addrhigh = (SIZE_T)(modulebase + modulesize) - 1;
+    moduleinfo.flags    = 0x0;
+    moduleinfo.name     = modulenamea;
+    moduleinfo.path     = modulepatha;
+    newmodules->insert(moduleinfo);
 
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
+    return TRUE;
+}
 
-    return block;
+// detachfrommodule - Callback function for EnumerateLoadedModules64 that
+//   detaches Visual Leak Detector from the specified module. If the specified
+//   module has not previously been attached to, then calling this function will
+//   not actually result in any changes.
+//
+//  - modulepath (IN): String containing the name, which may include a path, of
+//      the module to detach from (ignored).
+//
+//  - modulebase (IN): Base address of the module.
+//
+//  - modulesize (IN): Total size of the module (ignored).
+//
+//  - context (IN): User-supplied context (ignored).
+//
+//  Return Value:
+//
+//    Always returns TRUE.
+//
+BOOL VisualLeakDetector::detachfrommodule (PCWSTR /*modulepath*/, DWORD64 modulebase, ULONG /*modulesize*/,
+                                           PVOID /*context*/)
+{
+    UINT tablesize = sizeof(m_patchtable) / sizeof(patchentry_t);
+
+    restoremodule((HMODULE)modulebase, m_patchtable, tablesize);
+
+    return TRUE;
 }
 
-// _crtd__realloc_dbg - Calls to _realloc_dbg from msvcrtd.dll are patched
-//   through to this function. This function is just a wrapper around the real
-//   _realloc_dbg that sets appropriate flags to be consulted when the memory is
-//   actually allocated by RtlAllocateHeap.
+
+////////////////////////////////////////////////////////////////////////////////
 //
-//  - mem (IN): Pointer to the memory block to be reallocated.
+// Standard CRT and MFC IAT Replacement Functions
 //
-//  - size (IN): The size of the memory block to reallocate.
+// The addresses of these functions are not actually directly patched into the
+// import address tables, but these functions do get indirectly called by the
+// patch functions that are placed in the import address tables.
 //
-//  - type (IN): The CRT "use type" of the block to be reallocated.
+////////////////////////////////////////////////////////////////////////////////
+
+// _calloc - This function is just a wrapper around the real calloc that sets
+//   appropriate flags to be consulted when the memory is actually allocated by
+//   RtlAllocateHeap.
 //
-//  - file (IN): The name of the file from which this function is being called.
+//  - pcalloc (IN): Pointer to the particular calloc implementation to call.
 //
-//  - line (IN): The line number, in the above filel, at which this function is
-//      being called.
+//  - fp (IN): Frame pointer from the call that initiated this allocation.
+//
+//  - num (IN): The number of blocks, of size 'size', to be allocated.
+//
+//  - size (IN): The size, in bytes, of the memory block to be allocated.
 //
 //  Return Value:
 //
-//    Returns the value returned by _realloc_dbg.
+//    Returns the value returned from the specified calloc.
 //
-void* VisualLeakDetector::_crtd__realloc_dbg (void *mem, size_t size, int type, const char *file, int line)
+void* VisualLeakDetector::_calloc (calloc_t pcalloc,
+                                   SIZE_T   fp,
+                                   size_t   num,
+                                   size_t   size)
 {
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  msvcrtd;
-    tls_t   *tls = vld.gettls();
+    void  *block;
+    tls_t *tls = vld.gettls();
 
-    // _realloc_dbg is a CRT function and allocates from the CRT heap.
+    // malloc is a CRT function and allocates from the CRT heap.
     tls->flags |= VLD_TLS_CRTALLOC;
 
     if (tls->addrfp == 0x0) {
         // This is the first call to enter VLD for the current allocation.
         // Record the current frame pointer.
-        FRAMEPOINTER(fp);
         tls->addrfp = fp;
     }
 
-    if (pcrtd__realloc_dbg == NULL) {
-        // This is the first call to this function. Link to the real
-        // _realloc_dbg.
-        msvcrtd = GetModuleHandle(L"msvcrtd.dll");
-        pcrtd__realloc_dbg = (_realloc_dbg_t)GetProcAddress(msvcrtd, "_realloc_dbg");
-    }
-
-    // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
-    block = pcrtd__realloc_dbg(mem, size, type, file, line);
+    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
+    block = pcalloc(num, size);
 
     // Reset thread local flags and variables for the next allocation.
     tls->addrfp = 0x0;
@@ -1278,51 +1625,36 @@ void* VisualLeakDetector::_crtd__realloc_dbg (void *mem, size_t size, int type,
     return block;
 }
 
-// _crtd__scalar_new_dbg - Calls to the CRT's debug scalar new operator from
-//   msvcrtd.dll are patched through to this function. This function is just a
-//   wrapper around the real CRT debug scalar new operator that sets appropriate
-//   flags to be consulted when the memory is actually allocated by
+// _malloc - This function is just a wrapper around the real malloc that sets
+//   appropriate flags to be consulted when the memory is actually allocated by
 //   RtlAllocateHeap.
 //
-//  - size (IN): The size, in bytes, of the memory block to be allocated.
-//
-//  - type (IN): The CRT "use type" of the block to be allocated.
+//  - pmalloc (IN): Pointer to the particular malloc implementation to call.
 //
-//  - file (IN): The name of the file from which this function is being called.
+//  - fp (IN): Frame pointer from the call that initiated this allocation.
 //
-//  - line (IN): The line number, in the above file, at which this function is
-//      being called.
+//  - size (IN): The size, in bytes, of the memory block to be allocated.
 //
 //  Return Value:
 //
-//    Returns the value returned by the CRT debug scalar new operator.
+//    Returns the value returned from the specified malloc.
 //
-void* VisualLeakDetector::_crtd__scalar_new_dbg (unsigned int size, int type, const char *file, int line)
+void *VisualLeakDetector::_malloc (malloc_t pmalloc, SIZE_T fp, size_t size)
 {
     void    *block;
-    SIZE_T   fp;
-    HMODULE  msvcrtd;
     tls_t   *tls = vld.gettls();
 
-    // The debug new operator is a CRT function and allocates from the CRT heap.
+    // malloc is a CRT function and allocates from the CRT heap.
     tls->flags |= VLD_TLS_CRTALLOC;
 
     if (tls->addrfp == 0x0) {
         // This is the first call to enter VLD for the current allocation.
         // Record the current frame pointer.
-        FRAMEPOINTER(fp);
         tls->addrfp = fp;
     }
 
-    if (pcrtd__scalar_new_dbg == NULL) {
-        // This is the first call to this function. Link to the real CRT debug
-        // new operator.
-        msvcrtd = GetModuleHandle(L"msvcrtd.dll");
-        pcrtd__scalar_new_dbg = (crt_new_dbg_t)GetProcAddress(msvcrtd, "??2@YAPAXIHPBDH@Z");
-    }
-
     // Do the allocation. The block will be mapped by _RtlAllocateHeap.
-    block = pcrtd__scalar_new_dbg(size, type, file, line);
+    block = pmalloc(size);
 
     // Reset thread local flags and variables for the next allocation.
     tls->addrfp = 0x0;
@@ -1331,44 +1663,36 @@ void* VisualLeakDetector::_crtd__scalar_new_dbg (unsigned int size, int type, co
     return block;
 }
 
-// _crtd_calloc - Calls to calloc from msvcrtd.dll are patched through to this
-//   function. This function is just a wrapper around the real calloc that sets
-//   appropriate flags to be consulted when the memory is actually allocated by
-//   RtlAllocateHeap.
+// _new - This function is just a wrapper around the real CRT and MFC new
+//   operators that sets appropriate flags to be consulted when the memory is
+//   actually allocated by RtlAllocateHeap.
 //
-//  - num (IN): The number of blocks, of size 'size', to be allocated.
+//  - pnew (IN): Pointer to the particular new implementation to call.
+//
+//  - fp (IN): Frame pointer from the call that initiated this allocation.
 //
 //  - size (IN): The size, in bytes, of the memory block to be allocated.
 //
 //  Return Value:
 //
-//    Returns the valued returned from calloc.
+//    Returns the value returned by the specified CRT new operator.
 //
-void* VisualLeakDetector::_crtd_calloc (size_t num, size_t size)
+void* VisualLeakDetector::_new (new_t pnew, SIZE_T fp, size_t size)
 {
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  msvcrtd;
-    tls_t   *tls = vld.gettls();
+    void  *block;
+    tls_t *tls = vld.gettls();
 
-    // malloc is a CRT function and allocates from the CRT heap.
+    // The new operator is a CRT function and allocates from the CRT heap.
     tls->flags |= VLD_TLS_CRTALLOC;
 
     if (tls->addrfp == 0x0) {
         // This is the first call to enter VLD for the current allocation.
         // Record the current frame pointer.
-        FRAMEPOINTER(fp);
         tls->addrfp = fp;
     }
 
-    if (pcrtd_calloc == NULL) {
-        // This is the first call to this function. Link to the real malloc.
-        msvcrtd = GetModuleHandle(L"msvcrtd.dll");
-        pcrtd_calloc = (calloc_t)GetProcAddress(msvcrtd, "calloc");
-    }
-
     // Do the allocation. The block will be mapped by _RtlAllocateHeap.
-    block = pcrtd_calloc(num, size);
+    block = pnew(size);
 
     // Reset thread local flags and variables for the next allocation.
     tls->addrfp = 0x0;
@@ -1377,42 +1701,103 @@ void* VisualLeakDetector::_crtd_calloc (size_t num, size_t size)
     return block;
 }
 
-// _crtd_malloc - Calls to malloc from msvcrtd.dll are patched through to this
-//   function. This function is just a wrapper around the real malloc that sets
+// _realloc - This function is just a wrapper around the real realloc that sets
 //   appropriate flags to be consulted when the memory is actually allocated by
 //   RtlAllocateHeap.
 //
-//  - size (IN): The size, in bytes, of the memory block to be allocated.
+//  - prealloc (IN): Pointer to the particular realloc implementation to call.
+//
+//  - fp (IN): Frame pointer from the call that initiated this allocation.
+//
+//  - mem (IN): Pointer to the memory block to reallocate.
+//
+//  - size (IN): Size of the memory block to reallocate.
 //
 //  Return Value:
 //
-//    Returns the valued returned from malloc.
+//    Returns the value returned from the specified realloc.
 //
-void* VisualLeakDetector::_crtd_malloc (size_t size)
+void* VisualLeakDetector::_realloc (realloc_t  prealloc,
+                                    SIZE_T     fp,
+                                    void      *mem,
+                                    size_t     size)
 {
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  msvcrtd;
-    tls_t   *tls = vld.gettls();
+    void  *block;
+    tls_t *tls = vld.gettls();
 
-    // malloc is a CRT function and allocates from the CRT heap.
+    // realloc is a CRT function and allocates from the CRT heap.
     tls->flags |= VLD_TLS_CRTALLOC;
 
     if (tls->addrfp == 0x0) {
         // This is the first call to enter VLD for the current allocation.
         // Record the current frame pointer.
-        FRAMEPOINTER(fp);
         tls->addrfp = fp;
     }
 
-    if (pcrtd_malloc == NULL) {
-        // This is the first call to this function. Link to the real malloc.
-        msvcrtd = GetModuleHandle(L"msvcrtd.dll");
-        pcrtd_malloc = (malloc_t)GetProcAddress(msvcrtd, "malloc");
+    // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
+    block = prealloc(mem, size);
+
+    // Reset thread local flags and variables for the next allocation.
+    tls->addrfp = 0x0;
+    tls->flags &= ~VLD_TLS_CRTALLOC;
+
+    return block;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Debug CRT and MFC IAT Replacement Functions
+//
+// The addresses of these functions are not actually directly patched into the
+// import address tables, but these functions do get indirectly called by the
+// patch functions that are placed in the import address tables.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// __calloc_dbg - This function is just a wrapper around the real _calloc_dbg
+//   that sets appropriate flags to be consulted when the memory is actually
+//   allocated by RtlAllocateHeap.
+//
+//  - p_calloc_dbg: Pointer to the particular _calloc_dbg implementation to
+//      call.
+//
+//  - fp (IN): Frame pointer from the call that initiated this allocation.
+//
+//  - size (IN): The size, in bytes, of the memory block to be allocated.
+//
+//  - type (IN): The CRT "use type" of the block to be allocated.
+//
+//  - file (IN): The name of the file from which this function is being called.
+//
+//  - line (IN): The line number, in the above file, at which this function is
+//      being called.
+//
+//  Return Value:
+//
+//    Returns the value returned by the specified _calloc_dbg.
+//
+void* VisualLeakDetector::__calloc_dbg (_calloc_dbg_t  p_calloc_dbg,
+                                        SIZE_T         fp,
+                                        size_t         num,
+                                        size_t         size,
+                                        int            type,
+                                        char const    *file,
+                                        int            line)
+{
+    void  *block;
+    tls_t *tls = vld.gettls();
+
+    // _malloc_dbg is a CRT function and allocates from the CRT heap.
+    tls->flags |= VLD_TLS_CRTALLOC;
+
+    if (tls->addrfp == 0x0) {
+        // This is the first call to enter VLD for the current allocation.
+        // Record the current frame pointer.
+        tls->addrfp = fp;
     }
 
     // Do the allocation. The block will be mapped by _RtlAllocateHeap.
-    block = pcrtd_malloc(size);
+    block = p_calloc_dbg(num, size, type, file, line);
 
     // Reset thread local flags and variables for the next allocation.
     tls->addrfp = 0x0;
@@ -1421,44 +1806,100 @@ void* VisualLeakDetector::_crtd_malloc (size_t size)
     return block;
 }
 
-// _crtd_realloc - Calls to realloc from msvcrtd.dll are patched through to this
-//   function. This function is just a wrapper around the real realloc that sets
-//   appropriate flags to be consulted when the memory is actually allocated by
-//   RtlAllocateHeap.
+// __malloc_dbg - This function is just a wrapper around the real _malloc_dbg
+//   that sets appropriate flags to be consulted when the memory is actually
+//   allocated by RtlAllocateHeap.
 //
-//  - mem (IN): Pointer to the memory block to reallocate.
+//  - p_malloc_dbg (IN): Pointer to the particular _malloc_dbg implementation to
+//      call.
 //
-//  - size (IN): Size of the memory block to reallocate.
+//  - fp (IN): Frame pointer from the call that initiated this allocation.
+//
+//  - size (IN): The size, in bytes, of the memory block to be allocated.
+//
+//  - type (IN): The CRT "use type" of the block to be allocated.
+//
+//  - file (IN): The name of the file from which this function is being called.
+//
+//  - line (IN): The line number, in the above file, at which this function is
+//      being called.
 //
 //  Return Value:
 //
-//    Returns the value returned from realloc.
+//    Returns the value returned by the specified _malloc_dbg.
 //
-void* VisualLeakDetector::_crtd_realloc (void *mem, size_t size)
+void* VisualLeakDetector::__malloc_dbg (_malloc_dbg_t  p_malloc_dbg,
+                                        SIZE_T         fp,
+                                        size_t         size,
+                                        int            type,
+                                        char const    *file,
+                                        int            line)
 {
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  msvcrtd;
-    tls_t   *tls = vld.gettls();
+    void  *block;
+    tls_t *tls = vld.gettls();
 
-    // realloc is a CRT function and allocates from the CRT heap.
+    // _malloc_dbg is a CRT function and allocates from the CRT heap.
     tls->flags |= VLD_TLS_CRTALLOC;
 
     if (tls->addrfp == 0x0) {
         // This is the first call to enter VLD for the current allocation.
         // Record the current frame pointer.
-        FRAMEPOINTER(fp);
         tls->addrfp = fp;
     }
 
-    if (pcrtd_realloc == NULL) {
-        // This is the first call to this function. Link to the real realloc.
-        msvcrtd = GetModuleHandle(L"msvcrtd.dll");
-        pcrtd_realloc = (realloc_t)GetProcAddress(msvcrtd, "realloc");
+    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
+    block = p_malloc_dbg(size, type, file, line);
+
+    // Reset thread local flags and variables for the next allocation.
+    tls->addrfp = 0x0;
+    tls->flags &= ~VLD_TLS_CRTALLOC;
+
+    return block;
+}
+
+// new_dbg_crt - This function is just a wrapper around the real CRT debug new
+//   operators that sets appropriate flags to be consulted when the memory is
+//   actually allocated by RtlAllocateHeap.
+//
+//  - pnew_dbg_crt (IN): Pointer to the particular CRT new operator
+//      implementation to call.
+//
+//  - fp (IN): Frame pointer from the call that initiated this allocation.
+//
+//  - size (IN): The size, in bytes, of the memory block to be allocated.
+//
+//  - type (IN): The CRT "use type" of the block to be allocated.
+//
+//  - file (IN): The name of the file from which this function is being called.
+//
+//  - line (IN): The line number, in the above file, at which this function is
+//      being called.
+//
+//  Return Value:
+//
+//    Returns the value returned by the specified CRT debug new operator.
+//
+void* VisualLeakDetector::new_dbg_crt (new_dbg_crt_t  pnew_dbg_crt,
+                                       SIZE_T         fp,
+                                       size_t         size,
+                                       int            type,
+                                       char const    *file,
+                                       int            line)
+{
+    void  *block;
+    tls_t *tls = vld.gettls();
+
+    // The debug new operator is a CRT function and allocates from the CRT heap.
+    tls->flags |= VLD_TLS_CRTALLOC;
+
+    if (tls->addrfp == 0x0) {
+        // This is the first call to enter VLD for the current allocation.
+        // Record the current frame pointer.
+        tls->addrfp = fp;
     }
 
-    // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
-    block = pcrtd_realloc(mem, size);
+    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
+    block = pnew_dbg_crt(size, type, file, line);
 
     // Reset thread local flags and variables for the next allocation.
     tls->addrfp = 0x0;
@@ -1467,43 +1908,145 @@ void* VisualLeakDetector::_crtd_realloc (void *mem, size_t size)
     return block;
 }
 
-// _crtd_scalar_new - Calls to the CRT's scalar new operator from msvcrtd.dll
-//   are patched through to this function. This function is just a wrapper
-//   around the real CRT scalar new operator that sets appropriate flags to be
-//   consulted when the memory is actually allocated by RtlAllocateHeap.
+// new_dbg_mfc - This function is just a wrapper around the real MFC debug new
+//   operators that sets appropriate flags to be consulted when the memory is
+//   actually allocated by RtlAllocateHeap.
+//
+//  - pnew_dbg (IN): Pointer to the particular CRT new operator
+//      implementation to call.
+//
+//  - fp (IN): Frame pointer from the call that initiated this allocation.
 //
 //  - size (IN): The size, in bytes, of the memory block to be allocated.
 //
+//  - type (IN): The CRT "use type" of the block to be allocated.
+//
+//  - file (IN): The name of the file from which this function is being called.
+//
+//  - line (IN): The line number, in the above file, at which this function is
+//      being called.
+//
 //  Return Value:
 //
-//    Returns the value returned by the CRT scalar new operator.
+//    Returns the value returned by the specified CRT debug new operator.
 //
-void* VisualLeakDetector::_crtd_scalar_new (unsigned int size)
+void* VisualLeakDetector::new_dbg_mfc (new_dbg_crt_t  pnew_dbg,
+                                       SIZE_T         fp,
+                                       size_t         size,
+                                       int            type,
+                                       char const    *file,
+                                       int            line)
 {
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  msvcrtd;
-    tls_t   *tls = vld.gettls();
+    void  *block;
+    tls_t *tls = vld.gettls();
 
-    // The new operator is a CRT function and allocates from the CRT heap.
-    tls->flags |= VLD_TLS_CRTALLOC;
+    if (tls->addrfp == 0x0) {
+        // This is the first call to enter VLD for the current allocation.
+        // Record the current frame pointer.
+        tls->addrfp = fp;
+    }
+
+    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
+    block = pnew_dbg(size, type, file, line);
+
+    // Reset thread local flags and variables for the next allocation.
+    tls->addrfp = 0x0;
+    tls->flags &= ~VLD_TLS_CRTALLOC;
+
+    return block;
+}
+
+// new_dbg_mfc - This function is just a wrapper around the real MFC debug new
+//   operators that sets appropriate flags to be consulted when the memory is
+//   actually allocated by RtlAllocateHeap.
+//
+//  - pnew_dbg_mfc (IN): Pointer to the particular MFC new operator
+//      implementation to call.
+//
+//  - fp (IN): Frame pointer of the call that initiated this allocation.
+//
+//  - size (IN): The size, in bytes, of the memory block to be allocated.
+//
+//  - file (IN): The name of the file from which this function is being called.
+//
+//  - line (IN): The line number, in the above file, at which this function is
+//      being called.
+//
+//  Return Value:
+//
+//    Returns the value returned by the specified MFC debug new operator.
+//
+void* VisualLeakDetector::new_dbg_mfc (new_dbg_mfc_t  pnew_dbg_mfc,
+                                       SIZE_T         fp,
+                                       size_t         size,
+                                       char const    *file,
+                                       int            line)
+{
+    void  *block;
+    tls_t *tls = vld.gettls();
 
     if (tls->addrfp == 0x0) {
         // This is the first call to enter VLD for the current allocation.
         // Record the current frame pointer.
-        FRAMEPOINTER(fp);
         tls->addrfp = fp;
     }
 
-    if (pcrtd_scalar_new == NULL) {
-        // This is the first call to this function. Link to the real CRT new
-        // operator.
-        msvcrtd = GetModuleHandle(L"msvcrtd.dll");
-        pcrtd_scalar_new = (new_t)GetProcAddress(msvcrtd, "??2@YAPAXI@Z");
+    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
+    block = pnew_dbg_mfc(size, file, line);
+
+    // Reset thread local flags and variables for the next allocation.
+    tls->addrfp = 0x0;
+    tls->flags &= ~VLD_TLS_CRTALLOC;
+
+    return block;
+}
+
+// __realloc_debug - This function is just a wrapper around the real
+//   _realloc_dbg that sets appropriate flags to be consulted when the memory is
+//   actually allocated by RtlAllocateHeap.
+//
+//  - p_realloc_dbg (IN): Pointer to the particular __realloc_dbg implementation
+//      to call.
+//
+//  - fp (IN): Frame pointer from the call that initiated this allocation.
+//
+//  - mem (IN): Pointer to the memory block to be reallocated.
+//
+//  - size (IN): The size of the memory block to reallocate.
+//
+//  - type (IN): The CRT "use type" of the block to be reallocated.
+//
+//  - file (IN): The name of the file from which this function is being called.
+//
+//  - line (IN): The line number, in the above file, at which this function is
+//      being called.
+//
+//  Return Value:
+//
+//    Returns the value returned by the specified _realloc_dbg.
+//
+void* VisualLeakDetector::__realloc_dbg (_realloc_dbg_t  p_realloc_dbg,
+                                         SIZE_T          fp,
+                                         void           *mem,
+                                         size_t          size,
+                                         int             type,
+                                         char const     *file,
+                                         int             line)
+{
+    void  *block;
+    tls_t *tls = vld.gettls();
+
+    // _realloc_dbg is a CRT function and allocates from the CRT heap.
+    tls->flags |= VLD_TLS_CRTALLOC;
+
+    if (tls->addrfp == 0x0) {
+        // This is the first call to enter VLD for the current allocation.
+        // Record the current frame pointer.
+        tls->addrfp = fp;
     }
 
-    // Do tha allocation. The block will be mapped by _RtlAllocateHeap.
-    block = pcrtd_scalar_new(size);
+    // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
+    block = p_realloc_dbg(mem, size, type, file, line);
 
     // Reset thread local flags and variables for the next allocation.
     tls->addrfp = 0x0;
@@ -1512,6 +2055,12 @@ void* VisualLeakDetector::_crtd_scalar_new (unsigned int size)
     return block;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+//
+// Win32 IAT Replacement Functions
+//
+////////////////////////////////////////////////////////////////////////////////
+
 // _GetProcAddress - Calls to GetProcAddress are patched through to this
 //   function. If the requested function is a function that has been patched
 //   through to one of VLD's handlers, then the address of VLD's handler
@@ -1555,1427 +2104,494 @@ FARPROC VisualLeakDetector::_GetProcAddress (HMODULE module, LPCSTR procname)
                 return (FARPROC)entry->replacement;
             }
         }
-        else {
-            if (strcmp(entry->importname, procname) == 0) {
-                return (FARPROC)entry->replacement;
-            }
-        }
-    }
-
-    // The requested function is not a patched function. Just return the real
-    // address of the requested function.
-    return GetProcAddress(module, procname);
-}
-
-// _HeapCreate - Calls to HeapCreate are patched through to this function. This
-//   function is just a wrapper around the real HeapCreate that calls VLD's heap
-//   creation tracking function after the heap has been created.
-//
-//  - options (IN): Heap options.
-//
-//  - initsize (IN): Initial size of the heap.
-//
-//  - maxsize (IN): Maximum size of the heap.
-//
-//  Return Value:
-//
-//    Returns the value returned by HeapCreate.
-//
-HANDLE VisualLeakDetector::_HeapCreate (DWORD options, SIZE_T initsize, SIZE_T maxsize)
-{
-    DWORD64            displacement;
-    SIZE_T             fp;
-    SYMBOL_INFO       *functioninfo;
-    HANDLE             heap;
-    HeapMap::Iterator  heapit;
-    SIZE_T             ra;
-    BYTE               symbolbuffer [sizeof(SYMBOL_INFO) + (MAXSYMBOLNAMELENGTH * sizeof(WCHAR)) - 1] = { 0 };
-    BOOL               symfound;
-
-    // Get the return address within the calling function.
-    FRAMEPOINTER(fp);
-    ra = *((SIZE_T*)fp + 1);
-
-    // Create the heap.
-    heap = HeapCreate(options, initsize, maxsize);
-
-    // Map the created heap handle to a new block map.
-    vld.mapheap(heap);
-
-    // Try to get the name of the function containing the return address.
-    functioninfo = (SYMBOL_INFO*)&symbolbuffer;
-    functioninfo->SizeOfStruct = sizeof(SYMBOL_INFO);
-    functioninfo->MaxNameLen = MAXSYMBOLNAMELENGTH;
-    EnterCriticalSection(&symbollock);
-    symfound = SymFromAddrW(currentprocess, ra, &displacement, functioninfo);
-    LeaveCriticalSection(&symbollock);
-    if (symfound == TRUE) {
-        if (wcscmp(L"_heap_init", functioninfo->Name) == 0) {
-            // HeapCreate was called by _heap_init. This is a static CRT heap.
-            EnterCriticalSection(&vld.m_maplock);
-            heapit = vld.m_heapmap->find(heap);
-            assert(heapit != vld.m_heapmap->end());
-            (*heapit).second->flags |= VLD_HEAP_CRT;
-            LeaveCriticalSection(&vld.m_maplock);
-        }
-    }
-
-    return heap;
-}
-
-// _HeapDestroy - Calls to HeapDestroy are patched through to this function.
-//   This function is just a wrapper around the real HeapDestroy that calls
-//   VLD's heap destruction tracking function after the heap has been destroyed.
-//
-//  - heap (IN): Handle to the heap to be destroyed.
-//
-//  Return Value:
-//
-//    Returns the valued returned by HeapDestroy.
-//
-BOOL VisualLeakDetector::_HeapDestroy (HANDLE heap)
-{
-    // After this heap is destroyed, the heap's address space will be unmapped
-    // from the process's address space. So, we'd better generate a leak report
-    // for this heap now, while we can still read from the memory blocks
-    // allocated to it.
-    vld.reportleaks(heap);
-
-    vld.unmapheap(heap);
-
-    return HeapDestroy(heap);
-}
-
-// _LdrLoadDll - Calls to LdrLoadDll are patched through to this function. This
-//   function invokes the real LdrLoadDll and then re-attaches VLD to all
-//   modules loaded in the process after loading of the new DLL is complete.
-//   All modules must be re-enumerated because the explicit load of the
-//   specified module may result in the implicit load of one or more additional
-//   modules which are dependencies of the specified module.
-//
-//  - searchpath (IN): The path to use for searching for the specified module to
-//      be loaded.
-//
-//  - flags (IN): Pointer to action flags.
-//
-//  - modulename (IN): Pointer to a unicodestring_t structure specifying the
-//      name of the module to be loaded.
-//
-//  - modulehandle (OUT): Address of a HANDLE to receive the newly loaded
-//      module's handle.
-//
-//  Return Value:
-//
-//    Returns the value returned by LdrLoadDll.
-//
-NTSTATUS VisualLeakDetector::_LdrLoadDll (LPWSTR searchpath, PDWORD flags, unicodestring_t *modulename,
-                                          PHANDLE modulehandle)
-{
-    ModuleSet::Iterator  moduleit;
-    ModuleSet           *newmodules;
-    ModuleSet           *oldmodules;
-    NTSTATUS             status;
-
-    // Load the DLL.
-    status = LdrLoadDll(searchpath, flags, modulename, modulehandle);
-    
-    if (STATUS_SUCCESS == status) {
-        // Create a new set of all loaded modules, including any newly loaded
-        // modules.
-        newmodules = new ModuleSet;
-        newmodules->reserve(MODULESETRESERVE);
-        EnterCriticalSection(&vld.m_loaderlock);
-        EnumerateLoadedModulesW64(currentprocess, addloadedmodule, newmodules);
-        LeaveCriticalSection(&vld.m_loaderlock);
-
-        // Attach to all modules included in the set.
-        vld.attachtoloadedmodules(newmodules);
-
-        // Start using the new set of loaded modules.
-        EnterCriticalSection(&vld.m_moduleslock);
-        oldmodules = vld.m_loadedmodules;
-        vld.m_loadedmodules = newmodules;
-        LeaveCriticalSection(&vld.m_moduleslock);
-
-        // Free resources used by the old module list.
-        for (moduleit = oldmodules->begin(); moduleit != oldmodules->end(); ++moduleit) {
-            delete (*moduleit).name;
-            delete (*moduleit).path;
-        }
-        delete oldmodules;
-    }
-
-    return status;
-}
-
-// _mfc42d__scalar_new_dbg - Calls to the MFC debug scalar new operator from
-//   mfc42d.dll are patched through to this function. This function is just a
-//   wrapper around the real MFC debug scalar new operator that sets appropriate
-//   flags to be consulted when the memory is actually allocated by
-//   RtlAllocateHeap.
-//
-//  - size (IN): The size, in bytes, of the memory block to be allocated.
-//
-//  - file (IN): The name of the file from which this function is being called.
-//
-//  - line (IN): The line number, in the above file, at which this function is
-//      being called.
-//
-//  Return Value:
-//
-//    Returns the value returned by the MFC debug scalar new operator.
-//
-void* VisualLeakDetector::_mfc42d__scalar_new_dbg (unsigned int size, const char *file, int line)
-{
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  mfc42d;
-    tls_t   *tls = vld.gettls();
-
-    // The MFC new operators are CRT-based and allocate from the CRT heap.
-    tls->flags |= VLD_TLS_CRTALLOC;
-
-    if (tls->addrfp == 0x0) {
-        // This is the first call to enter VLD for the current allocation.
-        // Record the current frame pointer.
-        FRAMEPOINTER(fp);
-        tls->addrfp = fp;
-    }
-
-    if (pmfc42d__scalar_new_dbg == NULL) {
-        // This is the first call to this function. Link to the real MFC debug
-        // new operator.
-        mfc42d = GetModuleHandle(L"mfc42d.dll");
-        pmfc42d__scalar_new_dbg = (mfc_new_dbg_t)GetProcAddress(mfc42d, (LPCSTR)714);
-    }
-
-    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
-    block = pmfc42d__scalar_new_dbg(size, file, line);
-
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
-
-    return block;
-}
-
-// _mfc42d_scalar_new - Calls to the MFC scalar new operator from mfc42d.dll are
-//   patched through to this function. This function is just a wrapper around
-//   the real MFC scalar new operator that sets appropriate flags to be
-//   consulted when the memory is actually allocated by RtlAllocateHeap.
-//
-//  - size (IN): The size, in bytes, of the memory block to be allocated.
-//
-//  Return Value:
-//
-//    Returns the value returned by the MFC scalar new operator.
-//
-void* VisualLeakDetector::_mfc42d_scalar_new (unsigned int size)
-{
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  mfc42d;
-    tls_t   *tls = vld.gettls();
-
-    // The MFC new operators are CRT-based and allocate from the CRT heap.
-    tls->flags |= VLD_TLS_CRTALLOC;
-
-    if (tls->addrfp == 0x0) {
-        // This is the first call to enter VLD for the current allocation.
-        // Record the current frame pointer.
-        FRAMEPOINTER(fp);
-        tls->addrfp = fp;
-    }
-
-    if (pmfc42d_scalar_new == NULL) {
-        // This is the first call to this function. Link to the real MFC new
-        // operator.
-        mfc42d = GetModuleHandle(L"mfc42d.dll");
-        pmfc42d_scalar_new = (new_t)GetProcAddress(mfc42d, (LPCSTR)711);
-    }
-
-    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
-    block = pmfc42d_scalar_new(size);
-
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
-
-    return block;
-}
-
-// _mfc80d__scalar_new_dbg - Calls to the MFC debug scalar new operator from
-//   mfc80d.dll are patched through to this function. This function is just a
-//   wrapper around the real MFC debug scalar new operator that sets appropriate
-//   flags to be consulted when the memory is actually allocated by
-//   RtlAllocateHeap.
-//
-//  - size (IN): The size, in bytes, of the memory block to be allocated.
-//
-//  - file (IN): The name of the file from which this function is being called.
-//
-//  - line (IN): The line number, in the above file, at which this function is
-//      being called.
-//
-//  Return Value:
-//
-//    Returns the value returned by the MFC debug scalar new operator.
-//
-void* VisualLeakDetector::_mfc80d__scalar_new_dbg (unsigned int size, const char *file, int line)
-{
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  mfc80d;
-    tls_t   *tls = vld.gettls();
-
-    // The MFC new operators are CRT-based and allocate from the CRT heap.
-    tls->flags |= VLD_TLS_CRTALLOC;
-
-    if (tls->addrfp == 0x0) {
-        // This is the first call to enter VLD for the current allocation.
-        // Record the current frame pointer.
-        FRAMEPOINTER(fp);
-        tls->addrfp = fp;
-    }
-
-    if (pmfc80d__scalar_new_dbg == NULL) {
-        // This is the first call to this function. Link to the real MFC debug
-        // new operator.
-        mfc80d = GetModuleHandle(L"mfc80d.dll");
-        pmfc80d__scalar_new_dbg = (mfc_new_dbg_t)GetProcAddress(mfc80d, (LPCSTR)895);
-    }
-
-    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
-    block = pmfc80d__scalar_new_dbg(size, file, line);
-
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
-
-    return block;
-}
-
-// _mfc80d__vector_new_dbg - Calls to the MFC debug vector new operator from
-//   mfc80d.dll are patched through to this function. This function is just a
-//   wrapper around the real MFC debug vector new operator that sets appropriate
-//   flags to be consulted when the memory is actually allocated by
-//   RtlAllocateHeap.
-//
-//  - size (IN): The size, in bytes, of the memory block to be allocated.
-//
-//  - file (IN): The name of the file from which this function is being called.
-//
-//  - line (IN): The line number, in the above file, at which this function is
-//      being called.
-//
-//  Return Value:
-//
-//    Returns the value returned by the MFC debug vector new operator.
-//
-void* VisualLeakDetector::_mfc80d__vector_new_dbg (unsigned int size, const char *file, int line)
-{
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  mfc80d;
-    tls_t   *tls = vld.gettls();
-
-    // The MFC new operators are CRT-based and allocate from the CRT heap.
-    tls->flags |= VLD_TLS_CRTALLOC;
-
-    if (tls->addrfp == 0x0) {
-        // This is the first call to enter VLD for the current allocation.
-        // Record the current frame pointer.
-        FRAMEPOINTER(fp);
-        tls->addrfp = fp;
-    }
-
-    if (pmfc80d__vector_new_dbg == NULL) {
-        // This is the first call to this function. Link to the real MFC debug
-        // new operator.
-        mfc80d = GetModuleHandle(L"mfc80d.dll");
-        pmfc80d__vector_new_dbg = (mfc_new_dbg_t)GetProcAddress(mfc80d, (LPCSTR)269);
-    }
-
-    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
-    block = pmfc80d__vector_new_dbg(size, file, line);
-
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
-
-    return block;
-}
-
-// _mfc80d_scalar_new - Calls to the MFC scalar new operator from mfc80d.dll are
-//   patched through to this function. This function is just a wrapper around
-//   the real MFC scalar new operator that sets appropriate flags to be
-//   consulted when the memory is actually allocated by RtlAllocateHeap.
-//
-//  - size (IN): The size, in bytes, of the memory block to be allocated.
-//
-//  Return Value:
-//
-//    Returns the value returned by the MFC scalar new operator.
-//
-void* VisualLeakDetector::_mfc80d_scalar_new (unsigned int size)
-{
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  mfc80d;
-    tls_t   *tls = vld.gettls();
-
-    // The MFC new operators are CRT-based and allocate from the CRT heap.
-    tls->flags |= VLD_TLS_CRTALLOC;
-
-    if (tls->addrfp == 0x0) {
-        // This is the first call to enter VLD for the current allocation.
-        // Record the current frame pointer.
-        FRAMEPOINTER(fp);
-        tls->addrfp = fp;
-    }
-
-    if (pmfc80d_scalar_new == NULL) {
-        // This is the first call to this function. Link to the real MFC 8.0 new
-        // operator.
-        mfc80d = GetModuleHandle(L"mfc80d.dll");
-        pmfc80d_scalar_new = (new_t)GetProcAddress(mfc80d, (LPCSTR)893);
-    }
-
-    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
-    block = pmfc80d_scalar_new(size);
-
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
-
-    return block;
-}
-
-// _mfc80d_vector_new - Calls to the MFC vector new operator from mfc80d.dll are
-//   patched through to this function. This function is just a wrapper around
-//   the real MFC vector new operator that sets appropriate flags to be
-//   consulted when the memory is actually allocated by RtlAllocateHeap.
-//
-//  - size (IN): The size, in bytes, of the memory block to be allocated.
-//
-//  Return Value:
-//
-//    Returns the value returned by the MFC vector new operator.
-//
-void* VisualLeakDetector::_mfc80d_vector_new (unsigned int size)
-{
-    void    *block;
-    SIZE_T   fp;
-    HMODULE  mfc80d;
-    tls_t   *tls = vld.gettls();
-
-    // The MFC new operators are CRT-based and allocate from the CRT heap.
-    tls->flags |= VLD_TLS_CRTALLOC;
-
-    if (tls->addrfp == 0x0) {
-        // This is the first call to enter VLD for the current allocation.
-        // Record the current frame pointer.
-        FRAMEPOINTER(fp);
-        tls->addrfp = fp;
-    }
-
-    if (pmfc80d_vector_new == NULL) {
-        // This is the first call to this function. Link to the real MFC 8.0 new
-        // operator.
-        mfc80d = GetModuleHandle(L"mfc80d.dll");
-        pmfc80d_vector_new = (new_t)GetProcAddress(mfc80d, (LPCSTR)267);
-    }
-
-    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
-    block = pmfc80d_vector_new(size);
-
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
-
-    return block;
-}
-
-// _RtlAllocateHeap - Calls to RtlAllocateHeap are patched through to this
-//   function. This function invokes the real RtlAllocateHeap and then calls
-//   VLD's allocation tracking function. Pretty much all memory allocations
-//   will eventually result in a call to RtlAllocateHeap, so this is where we
-//   finally map the allocated block.
-//
-//  - heap (IN): Handle to the heap from which to allocate memory.
-//
-//  - flags (IN): Heap allocation control flags.
-//
-//  - size (IN): Size, in bytes, of the block to allocate.
-//
-//  Return Value:
-//
-//    Returns the return value from RtlAllocateHeap.
-//
-LPVOID VisualLeakDetector::_RtlAllocateHeap (HANDLE heap, DWORD flags, SIZE_T size)
-{
-    BOOL                 crtalloc;
-    BOOL                 excluded = FALSE;
-    SIZE_T               fp;
-    LPVOID               block;
-    moduleinfo_t         moduleinfo;
-    ModuleSet::Iterator  moduleit;
-    SIZE_T               returnaddress;
-    tls_t               *tls = vld.gettls();
-
-    // Allocate the block.
-    block = RtlAllocateHeap(heap, flags, size);
-    if ((block != NULL) && vld.enabled()) {
-        if (tls->addrfp == 0x0) {
-            // This is the first call to enter VLD for the current allocation.
-            // Record the current frame pointer.
-            FRAMEPOINTER(fp);
-        }
-        else {
-            fp = tls->addrfp;
-        }
-        crtalloc = (tls->flags & VLD_TLS_CRTALLOC) ? TRUE : FALSE;
-
-        // Reset thread local flags and variables, in case any libraries called
-        // into while mapping the block allocate some memory.
-        tls->addrfp = 0x0;
-        tls->flags &=~VLD_TLS_CRTALLOC;
-
-        // Find the information for the module that initiated this allocation.
-        returnaddress = *((SIZE_T*)fp + 1);
-        moduleinfo.addrhigh = returnaddress;
-        moduleinfo.addrlow  = returnaddress;
-        EnterCriticalSection(&vld.m_moduleslock);
-        moduleit = vld.m_loadedmodules->find(moduleinfo);
-        if (moduleit != vld.m_loadedmodules->end()) {
-            excluded = (*moduleit).flags & VLD_MODULE_EXCLUDED ? TRUE : FALSE;
-        }
-        LeaveCriticalSection(&vld.m_moduleslock);
-        if (!excluded) {
-            // The module that initiated this allocation is included in leak
-            // detection. Map this block to the specified heap.
-            vld.mapblock(heap, block, size, fp, crtalloc);
-        }
-    }
-
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
-
-    return block;
-}
-
-// _RtlFreeHeap - Calls to RtlFreeHeap are patched through to this function.
-//   This function calls VLD's free tracking function and then invokes the real
-//   RtlFreeHeap. Pretty much all memory frees will eventually result in a call
-//   to RtlFreeHeap, so this is where we finally unmap the freed block.
-//
-//  - heap (IN): Handle to the heap to which the block being freed belongs.
-//
-//  - flags (IN): Heap control flags.
-//
-//  - mem (IN): Pointer to the memory block being freed.
-//
-//  Return Value:
-//
-//    Returns the value returned by RtlFreeHeap.
-//
-BOOL VisualLeakDetector::_RtlFreeHeap (HANDLE heap, DWORD flags, LPVOID mem)
-{
-    BOOL status;
-
-    // Unmap the block from the specified heap.
-    vld.unmapblock(heap, mem);
-
-    status = RtlFreeHeap(heap, flags, mem);
-
-    return status;
-}
-
-// _RtlReAllocateHeap - Calls to RtlReAllocateHeap are patched through to this
-//   function. This function invokes the real RtlReAllocateHeap and then calls
-//   VLD's reallocation tracking function. All arguments passed to this function
-//   are passed on to the real RtlReAllocateHeap without modification. Pretty
-//   much all memory re-allocations will eventually result in a call to
-//   RtlReAllocateHeap, so this is where we finally remap the reallocated block.
-//
-//  - heap (IN): Handle to the heap to reallocate memory from.
-//
-//  - flags (IN): Heap control flags.
-//
-//  - mem (IN): Pointer to the currently allocated block which is to be
-//      reallocated.
-//
-//  - size (IN): Size, in bytes, of the block to reallocate.
-//
-//  Return Value:
-//
-//    Returns the value returned by RtlReAllocateHeap.
-//
-LPVOID VisualLeakDetector::_RtlReAllocateHeap (HANDLE heap, DWORD flags, LPVOID mem, SIZE_T size)
-{
-    BOOL                 crtalloc;
-    BOOL                 excluded = FALSE;
-    SIZE_T               fp;
-    moduleinfo_t         moduleinfo;
-    ModuleSet::Iterator  moduleit;
-    LPVOID               newmem;
-    SIZE_T               returnaddress;
-    tls_t               *tls = vld.gettls();
-
-    // Reallocate the block.
-    newmem = RtlReAllocateHeap(heap, flags, mem, size);
-
-    if (newmem != NULL) {
-        if (tls->addrfp == 0x0) {
-            // This is the first call to enter VLD for the current allocation.
-            // Record the current frame pointer.
-            FRAMEPOINTER(fp);
-        }
-        else {
-            fp = tls->addrfp;
-        }
-        crtalloc = (tls->flags & VLD_TLS_CRTALLOC) ? TRUE : FALSE;
-
-        // Reset thread local flags and variables, in case any libraries called
-        // into while remapping the block allocate some memory.
-        tls->addrfp = 0x0;
-        tls->flags &= ~VLD_TLS_CRTALLOC;
-
-        // Find the information for the module that initiated this reallocation.
-        returnaddress = *((SIZE_T*)fp + 1);
-        moduleinfo.addrhigh = returnaddress;
-        moduleinfo.addrlow  = returnaddress;
-        EnterCriticalSection(&vld.m_moduleslock);
-        moduleit = vld.m_loadedmodules->find(moduleinfo);
-        if (moduleit != vld.m_loadedmodules->end()) {
-            excluded = (*moduleit).flags & VLD_MODULE_EXCLUDED ? TRUE : FALSE;
-        }
-        LeaveCriticalSection(&vld.m_moduleslock);
-        if (!excluded) {
-            // The module that initiated this allocation is included in leak
-            // detection. Remap the block.
-            vld.remapblock(heap, mem, newmem, size, fp, crtalloc);
-        }
-    }
-
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
-
-    return newmem;
-}
-
-// AddRef - Calls to IMalloc::AddRef end up here. This function is just a
-//   wrapper around the real IMalloc::AddRef implementation.
-//
-//  Return Value:
-//
-//    Returns the value returned by the system implementation of
-//    IMalloc::AddRef.
-//
-ULONG VisualLeakDetector::AddRef ()
-{
-    assert(m_imalloc != NULL);
-    return m_imalloc->AddRef();
-}
-
-// Alloc - Calls to IMalloc::Alloc end up here. This function is just a wrapper
-//   around the real IMalloc::Alloc implementation that sets appropriate flags
-//   to be consulted when the memory is actually allocated by RtlAllocateHeap.
-//
-//  - size (IN): The size of the memory block to allocate.
-//
-//  Return Value:
-//
-//    Returns the value returned by the system's IMalloc::Alloc implementation.
-//
-LPVOID VisualLeakDetector::Alloc (ULONG size)
-{
-    LPVOID  block;
-    SIZE_T  fp;
-    tls_t  *tls = vld.gettls();
-
-    if (tls->addrfp == 0x0) {
-        // This is the first call to enter VLD for the current allocation.
-        // Record the current frame pointer.
-        FRAMEPOINTER(fp);
-        tls->addrfp = fp;
-    }
-
-    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
-    assert(m_imalloc != NULL);
-    block = m_imalloc->Alloc(size);
-
-    // Reset thread local flags and variables for the next allocation.
-    tls->addrfp = 0x0;
-    tls->flags &= ~VLD_TLS_CRTALLOC;
-
-    return block;
-}
-
-// addloadedmodule - Callback function for EnumerateLoadedModules64. This
-//   function records information about every module loaded in the process,
-//   each time adding the module's information to the provided ModuleSet (the
-//   "context" parameter).
-//
-//   When EnumerateLoadedModules64 has finished calling this function for each
-//   loaded module, then the resulting ModuleSet can be used at any time to get
-//   information about any modules loaded into the process.
-//
-//   - modulepath (IN): The fully qualified path from where the module was
-//       loaded.
-//
-//   - modulebase (IN): The base address at which the module has been loaded.
-//
-//   - modulesize (IN): The size, in bytes, of the loaded module.
-//
-//   - context (IN): Pointer to the ModuleSet to which information about each
-//       module is to be added.
-//
-//  Return Value:
-//
-//    Always returns TRUE, which tells EnumerateLoadedModules64 to continue
-//    enumerating.
-//
-BOOL VisualLeakDetector::addloadedmodule (PCWSTR modulepath, DWORD64 modulebase, ULONG modulesize, PVOID context)
-{
-    size_t        count;
-    patchentry_t *entry;
-    CHAR          extension [_MAX_EXT];
-    CHAR          filename [_MAX_FNAME];
-    UINT          index;
-    moduleinfo_t  moduleinfo;
-    LPSTR         modulenamea;
-    LPSTR         modulepatha;
-    ModuleSet*    newmodules = (ModuleSet*)context;
-    SIZE_T        size;
-    UINT          tablesize = sizeof(m_patchtable) / sizeof(patchentry_t);
-
-    // Convert the module path to ASCII.
-    size = wcslen(modulepath) + 1;
-    modulepatha = new CHAR [size];
-    wcstombs_s(&count, modulepatha, size, modulepath, _TRUNCATE);
-
-    // Extract just the filename and extension from the module path.
-    _splitpath_s(modulepatha, NULL, 0, NULL, 0, filename, _MAX_FNAME, extension, _MAX_EXT);
-    size = strlen(filename) + strlen(extension) + 1;
-    modulenamea = new CHAR [size];
-    strncpy_s(modulenamea, size, filename, _TRUNCATE);
-    strncat_s(modulenamea, size, extension, _TRUNCATE);
-    _strlwr_s(modulenamea, size);
-
-    if (_stricmp(modulenamea, "vld.dll") == 0) {
-        // Record Visual Leak Detector's own base address.
-        vld.m_vldbase = (HMODULE)modulebase;
-    }
-    else {
-        // See if this is a module listed in the patch table. If it is, update
-        // the corresponding patch table entries' module base address.
-        for (index = 0; index < tablesize; index++) {
-            entry = &m_patchtable[index];
-            if (_stricmp(entry->exportmodulename, modulenamea) == 0) {
-                entry->modulebase = (SIZE_T)modulebase;
-            }
-        }
-    }
-
-    // Record the module's information and store it in the set.
-    moduleinfo.addrlow  = (SIZE_T)modulebase;
-    moduleinfo.addrhigh = (SIZE_T)(modulebase + modulesize) - 1;
-    moduleinfo.flags    = 0x0;
-    moduleinfo.name     = modulenamea;
-    moduleinfo.path     = modulepatha;
-    newmodules->insert(moduleinfo);
-
-    return TRUE;
-}
-
-// attachtoloadedmodules - Attaches VLD to all modules contained in the provided
-//   ModuleSet. Not all modules are in the ModuleSet will actually be included
-//   in leak detection. Only modules that import the global VisualLeakDetector
-//   class object, or those that are otherwise explicitly included in leak
-//   detection, will be checked for memory leaks.
-//
-//   When VLD attaches to a module, it means that any of the imports listed in
-//   the import patch table which are imported by the module, will be redirected
-//   to VLD's designated replacements.
-//
-//  - newmodules (IN): Pointer to a ModuleSet containing information about any
-//      loaded modules that need to be attached.
-//
-//  Return Value:
-//
-//    None.
-//
-VOID VisualLeakDetector::attachtoloadedmodules (ModuleSet *newmodules)
-{
-    size_t                count;
-    DWORD64               modulebase;
-    UINT32                moduleflags;
-    IMAGEHLP_MODULE64     moduleimageinfo;
-    LPCSTR                modulename;
-#define MAXMODULENAME (_MAX_FNAME + _MAX_EXT)
-    WCHAR                 modulenamew [MAXMODULENAME];
-    LPCSTR                modulepath;
-    DWORD                 modulesize;
-    ModuleSet::Iterator   newit;
-    ModuleSet::Iterator   oldit;
-    ModuleSet            *oldmodules;
-    BOOL                  refresh;
-    UINT                  tablesize = sizeof(m_patchtable) / sizeof(patchentry_t);
-    ModuleSet::Muterator  updateit;
-
-    // Iterate through the supplied set, until all modules have been attached.
-    for (newit = newmodules->begin(); newit != newmodules->end(); ++newit) {
-        modulebase  = (DWORD64)(*newit).addrlow;
-        moduleflags = 0x0;
-        modulename  = (*newit).name;
-        modulepath  = (*newit).path;
-        modulesize  = (DWORD)((*newit).addrhigh - (*newit).addrlow) + 1;
-
-        refresh = FALSE;
-        EnterCriticalSection(&m_moduleslock);
-        oldmodules = m_loadedmodules;
-        if (oldmodules != NULL) {
-            // This is not the first time we have been called to attach to the
-            // currently loaded modules.
-            oldit = oldmodules->find(*newit);
-            if (oldit != oldmodules->end()) {
-                // We've seen this "new" module loaded in the process before.
-                moduleflags = (*oldit).flags;
-                LeaveCriticalSection(&m_moduleslock);
-                if (moduleispatched((HMODULE)modulebase, m_patchtable, tablesize)) {
-                    // This module is already attached. Just update the module's
-                    // flags, nothing more.
-                    updateit = newit;
-                    (*updateit).flags = moduleflags;
-                    continue;
-                }
-                else {
-                    // This module may have been attached before and has been
-                    // detached. We'll need to try reattaching to it in case it
-                    // was unloaded and then subsequently reloaded.
-                    refresh = TRUE;
-                }
-            }
-            else {
-                LeaveCriticalSection(&m_moduleslock);
-            }
-        }
-        else {
-            LeaveCriticalSection(&m_moduleslock);
-        }
-
-        EnterCriticalSection(&symbollock);
-        if ((refresh == TRUE) && (moduleflags & VLD_MODULE_SYMBOLSLOADED)) {
-            // Discard the previously loaded symbols, so we can refresh them.
-            if (SymUnloadModule64(currentprocess, modulebase) == FALSE) {
-                report(L"WARNING: Visual Leak Detector: Failed to unload the symbols for %s. Function names and line"
-                       L" numbers shown in the memory leak report for %s may be inaccurate.", modulename, modulename);
-            }
-        }
-
-        // Try to load the module's symbols. This ensures that we have loaded
-        // the symbols for every module that has ever been loaded into the
-        // process, guaranteeing the symbols' availability when generating the
-        // leak report.
-        moduleimageinfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
-        if ((SymGetModuleInfoW64(currentprocess, (DWORD64)modulebase, &moduleimageinfo) == TRUE) ||
-            ((SymLoadModule64(currentprocess, NULL, modulepath, NULL, modulebase, modulesize) == modulebase) &&
-            (SymGetModuleInfoW64(currentprocess, modulebase, &moduleimageinfo) == TRUE))) {
-            moduleflags |= VLD_MODULE_SYMBOLSLOADED;
-        }
-        LeaveCriticalSection(&symbollock);
-
-        if (_stricmp("vld.dll", modulename) == 0) {
-            // What happens when a module goes through it's own portal? Bad things.
-            // Like infinite recursion. And ugly bald men wearing dresses. VLD
-            // should not, therefore, attach to itself.
-            continue;
-        }
-
-        mbstowcs_s(&count, modulenamew, MAXMODULENAME, modulename, _TRUNCATE);
-        if ((findimport((HMODULE)modulebase, m_vldbase, "vld.dll", "?vld@@3VVisualLeakDetector@@A") == FALSE) &&
-            (wcsstr(vld.m_forcedmodulelist, modulenamew) == NULL)) {
-            // This module does not import VLD. This means that none of the module's
-            // sources #included vld.h. Exclude this module from leak detection.
-            moduleflags |= VLD_MODULE_EXCLUDED;
-        }
-        else if (!(moduleflags & VLD_MODULE_SYMBOLSLOADED) || (moduleimageinfo.SymType == SymExport)) {
-            // This module is going to be included in leak detection, but complete
-            // symbols for this module couldn't be loaded. This means that any stack
-            // traces through this module may lack information, like line numbers
-            // and function names.
-            report(L"WARNING: Visual Leak Detector: A module, %s, included in memory leak detection\n"
-                   L"  does not have any debugging symbols available, or they could not be located.\n"
-                   L"  Function names and/or line numbers for this module may not be available.\n", modulename);
-        }
-
-        // Update the module's flags in the "new modules" set.
-        updateit = newit;
-        (*updateit).flags = moduleflags;
-
-        // Attach to the module.
-        patchmodule((HMODULE)modulebase, m_patchtable, tablesize);
-    }
-}
-
-// buildsymbolsearchpath - Builds the symbol search path for the symbol handler.
-//   This helps the symbol handler find the symbols for the application being
-//   debugged.
-//
-//  Return Value:
-//
-//    Returns a string containing the search path. The caller is responsible for
-//    freeing the string.
-//
-LPWSTR VisualLeakDetector::buildsymbolsearchpath ()
-{
-    WCHAR   directory [_MAX_DIR];
-    WCHAR   drive [_MAX_DRIVE];
-    LPWSTR  env;
-    DWORD   envlen;
-    SIZE_T  index;
-    SIZE_T  length;
-    HMODULE module;
-    LPWSTR  path = new WCHAR [MAX_PATH];
-    SIZE_T  pos = 0;
-    WCHAR   system [MAX_PATH];
-    WCHAR   windows [MAX_PATH];
-
-    // Oddly, the symbol handler ignores the link to the PDB embedded in the
-    // executable image. So, we'll manually add the location of the executable
-    // to the search path since that is often where the PDB will be located.
-    path[0] = L'\0';
-    module = GetModuleHandle(NULL);
-    GetModuleFileName(module, path, MAX_PATH);
-    _wsplitpath_s(path, drive, _MAX_DRIVE, directory, _MAX_DIR, NULL, 0, NULL, 0);
-    wcsncpy_s(path, MAX_PATH, drive, _TRUNCATE);
-    strapp(&path, directory);
-
-    // When the symbol handler is given a custom symbol search path, it will no
-    // longer search the default directories (working directory, system root,
-    // etc). But we'd like it to still search those directories, so we'll add
-    // them to our custom search path.
-    //
-    // Append the working directory.
-    strapp(&path, L";.\\");
-
-    // Append the Windows directory.
-    if (GetWindowsDirectory(windows, MAX_PATH) != 0) {
-        strapp(&path, L";");
-        strapp(&path, windows);
-    }
-
-    // Append the system directory.
-    if (GetSystemDirectory(system, MAX_PATH) != 0) {
-        strapp(&path, L";");
-        strapp(&path, system);
-    }
-
-    // Append %_NT_SYMBOL_PATH%.
-    envlen = GetEnvironmentVariable(L"_NT_SYMBOL_PATH", NULL, 0);
-    if (envlen != 0) {
-        env = new WCHAR [envlen];
-        if (GetEnvironmentVariable(L"_NT_SYMBOL_PATH", env, envlen) != 0) {
-            strapp(&path, L";");
-            strapp(&path, env);
-        }
-        delete [] env;
-    }
-
-    //  Append %_NT_ALT_SYMBOL_PATH%.
-    envlen = GetEnvironmentVariable(L"_NT_ALT_SYMBOL_PATH", NULL, 0);
-    if (envlen != 0) {
-        env = new WCHAR [envlen];
-        if (GetEnvironmentVariable(L"_NT_ALT_SYMBOL_PATH", env, envlen) != 0) {
-            strapp(&path, L";");
-            strapp(&path, env);
-        }
-        delete [] env;
-    }
-
-    // Remove any quotes from the path. The symbol handler doesn't like them.
-    pos = 0;
-    length = wcslen(path);
-    while (pos < length) {
-        if (path[pos] == L'\"') {
-            for (index = pos; index < length; index++) {
-                path[index] = path[index + 1];
-            }
-        }
-        pos++;
-    }
-
-    return path;
-}
-
-// configure - Configures VLD using values read from the vld.ini file.
-//
-//  Return Value:
-//
-//    None.
-//
-VOID VisualLeakDetector::configure ()
-{
-#define BSIZE 64
-    WCHAR        buffer [BSIZE];
-    WCHAR        filename [MAX_PATH];
-    WCHAR        inipath [MAX_PATH];
-    BOOL         keyopen = FALSE;
-    DWORD        length;
-    HKEY         productkey;
-    LONG         regstatus;
-    struct _stat s;
-    DWORD        valuetype;
-
-    if (_wstat(L".\\vld.ini", &s) == 0) {
-        // Found a copy of vld.ini in the working directory. Use it.
-        wcsncpy_s(inipath, MAX_PATH, L".\\vld.ini", _TRUNCATE);
-    }
-    else {
-        // Get the location of the vld.ini file from the registry.
-        regstatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, VLDREGKEYPRODUCT, 0, KEY_QUERY_VALUE, &productkey);
-        if (regstatus == ERROR_SUCCESS) {
-            keyopen = TRUE;
-            regstatus = RegQueryValueEx(productkey, L"IniFile", NULL, &valuetype, (LPBYTE)&inipath, &length);
-        }
-        if (keyopen) {
-            RegCloseKey(productkey);
-        }
-        if ((regstatus != ERROR_SUCCESS) || (_wstat(inipath, &s) != 0)) {
-            // The location of vld.ini could not be read from the registry. As a
-            // last resort, look in the Windows directory.
-            wcsncpy_s(inipath, MAX_PATH, L"vld.ini", _TRUNCATE);
-        }
-    }
-
-    // Read the boolean options.
-    GetPrivateProfileString(L"Options", L"VLD", L"on", buffer, BSIZE, inipath);
-    if (strtobool(buffer) == FALSE) {
-        m_options |= VLD_OPT_VLDOFF;
-        return;
-    }
-
-    GetPrivateProfileString(L"Options", L"AggregateDuplicates", L"", buffer, BSIZE, inipath);
-    if (strtobool(buffer) == TRUE) {
-        m_options |= VLD_OPT_AGGREGATE_DUPLICATES;
-    }
-
-    GetPrivateProfileString(L"Options", L"SelfTest", L"", buffer, BSIZE, inipath);
-    if (strtobool(buffer) == TRUE) {
-        m_options |= VLD_OPT_SELF_TEST;
-    }
-
-    GetPrivateProfileString(L"Options", L"SlowDebuggerDump", L"", buffer, BSIZE, inipath);
-    if (strtobool(buffer) == TRUE) {
-        m_options |= VLD_OPT_SLOW_DEBUGGER_DUMP;
+        else {
+            if (strcmp(entry->importname, procname) == 0) {
+                return (FARPROC)entry->replacement;
+            }
+        }
     }
 
-    GetPrivateProfileString(L"Options", L"StartDisabled", L"", buffer, BSIZE, inipath);
-    if (strtobool(buffer) == TRUE) {
-        m_options |= VLD_OPT_START_DISABLED;
-    }
+    // The requested function is not a patched function. Just return the real
+    // address of the requested function.
+    return GetProcAddress(module, procname);
+}
 
-    GetPrivateProfileString(L"Options", L"TraceInternalFrames", L"", buffer, BSIZE, inipath);
-    if (strtobool(buffer) == TRUE) {
-        m_options |= VLD_OPT_TRACE_INTERNAL_FRAMES;
-    }
+// _HeapCreate - Calls to HeapCreate are patched through to this function. This
+//   function is just a wrapper around the real HeapCreate that calls VLD's heap
+//   creation tracking function after the heap has been created.
+//
+//  - options (IN): Heap options.
+//
+//  - initsize (IN): Initial size of the heap.
+//
+//  - maxsize (IN): Maximum size of the heap.
+//
+//  Return Value:
+//
+//    Returns the value returned by HeapCreate.
+//
+HANDLE VisualLeakDetector::_HeapCreate (DWORD options, SIZE_T initsize, SIZE_T maxsize)
+{
+    DWORD64            displacement;
+    SIZE_T             fp;
+    SYMBOL_INFO       *functioninfo;
+    HANDLE             heap;
+    HeapMap::Iterator  heapit;
+    SIZE_T             ra;
+    BYTE               symbolbuffer [sizeof(SYMBOL_INFO) + (MAXSYMBOLNAMELENGTH * sizeof(WCHAR)) - 1] = { 0 };
+    BOOL               symfound;
 
-    // Read the integer configuration options.
-    m_maxdatadump = GetPrivateProfileInt(L"Options", L"MaxDataDump", VLD_DEFAULT_MAX_DATA_DUMP, inipath);
-    m_maxtraceframes = GetPrivateProfileInt(L"Options", L"MaxTraceFrames", VLD_DEFAULT_MAX_TRACE_FRAMES, inipath);
-    if (m_maxtraceframes < 1) {
-        m_maxtraceframes = VLD_DEFAULT_MAX_TRACE_FRAMES;
-    }
+    // Get the return address within the calling function.
+    FRAMEPOINTER(fp);
+    ra = *((SIZE_T*)fp + 1);
 
-    // Read the force-include module list.
-    GetPrivateProfileString(L"Options", L"ForceIncludeModules", L"", m_forcedmodulelist, MAXMODULELISTLENGTH, inipath);
-    _wcslwr_s(m_forcedmodulelist, MAXMODULELISTLENGTH);
+    // Create the heap.
+    heap = HeapCreate(options, initsize, maxsize);
 
-    // Read the report destination (debugger, file, or both).
-    GetPrivateProfileString(L"Options", L"ReportFile", L"", filename, MAX_PATH, inipath);
-    if (wcslen(filename) == 0) {
-        wcsncpy_s(filename, MAX_PATH, VLD_DEFAULT_REPORT_FILE_NAME, _TRUNCATE);
-    }
-    _wfullpath(m_reportfilepath, filename, MAX_PATH);
-    GetPrivateProfileString(L"Options", L"ReportTo", L"", buffer, BSIZE, inipath);
-    if (_wcsicmp(buffer, L"both") == 0) {
-        m_options |= (VLD_OPT_REPORT_TO_DEBUGGER | VLD_OPT_REPORT_TO_FILE);
-    }
-    else if (_wcsicmp(buffer, L"file") == 0) {
-        m_options |= VLD_OPT_REPORT_TO_FILE;
-    }
-    else {
-        m_options |= VLD_OPT_REPORT_TO_DEBUGGER;
-    }
+    // Map the created heap handle to a new block map.
+    vld.mapheap(heap);
 
-    // Read the report file encoding (ascii or unicode).
-    GetPrivateProfileString(L"Options", L"ReportEncoding", L"", buffer, BSIZE, inipath);
-    if (_wcsicmp(buffer, L"unicode") == 0) {
-        m_options |= VLD_OPT_UNICODE_REPORT;
-    }
-    if ((m_options & VLD_OPT_UNICODE_REPORT) && !(m_options & VLD_OPT_REPORT_TO_FILE)) {
-        // If Unicode report encoding is enabled, then the report needs to be
-        // sent to a file because the debugger will not display Unicode
-        // characters, it will display question marks in their place instead.
-        m_options |= VLD_OPT_REPORT_TO_FILE;
-        m_status |= VLD_STATUS_FORCE_REPORT_TO_FILE;
+    // Try to get the name of the function containing the return address.
+    functioninfo = (SYMBOL_INFO*)&symbolbuffer;
+    functioninfo->SizeOfStruct = sizeof(SYMBOL_INFO);
+    functioninfo->MaxNameLen = MAXSYMBOLNAMELENGTH;
+    EnterCriticalSection(&symbollock);
+    symfound = SymFromAddrW(currentprocess, ra, &displacement, functioninfo);
+    LeaveCriticalSection(&symbollock);
+    if (symfound == TRUE) {
+        if (wcscmp(L"_heap_init", functioninfo->Name) == 0) {
+            // HeapCreate was called by _heap_init. This is a static CRT heap.
+            EnterCriticalSection(&vld.m_maplock);
+            heapit = vld.m_heapmap->find(heap);
+            assert(heapit != vld.m_heapmap->end());
+            (*heapit).second->flags |= VLD_HEAP_CRT;
+            LeaveCriticalSection(&vld.m_maplock);
+        }
     }
 
-    // Read the stack walking method.
-    GetPrivateProfileString(L"Options", L"StackWalkMethod", L"", buffer, BSIZE, inipath);
-    if (_wcsicmp(buffer, L"safe") == 0) {
-        m_options |= VLD_OPT_SAFE_STACK_WALK;
-    }
+    return heap;
 }
 
-// detachfrommodule - Callback function for EnumerateLoadedModules64 that
-//   detaches Visual Leak Detector from the specified module. If the specified
-//   module has not previously been attached to, then calling this function will
-//   not actually result in any changes.
-//
-//  - modulepath (IN): String containing the name, which may inlcude a path, of
-//      the module to detach from (ignored).
-//
-//  - modulebase (IN): Base address of the module.
-//
-//  - modulesize (IN): Total size of the module (ignored).
+// _HeapDestroy - Calls to HeapDestroy are patched through to this function.
+//   This function is just a wrapper around the real HeapDestroy that calls
+//   VLD's heap destruction tracking function after the heap has been destroyed.
 //
-//  - context (IN): User-supplied context (ignored).
+//  - heap (IN): Handle to the heap to be destroyed.
 //
 //  Return Value:
 //
-//    Always returns TRUE.
+//    Returns the valued returned by HeapDestroy.
 //
-BOOL VisualLeakDetector::detachfrommodule (PCWSTR /*modulepath*/, DWORD64 modulebase, ULONG /*modulesize*/,
-                                           PVOID /*context*/)
+BOOL VisualLeakDetector::_HeapDestroy (HANDLE heap)
 {
-    UINT tablesize = sizeof(m_patchtable) / sizeof(patchentry_t);
+    // After this heap is destroyed, the heap's address space will be unmapped
+    // from the process's address space. So, we'd better generate a leak report
+    // for this heap now, while we can still read from the memory blocks
+    // allocated to it.
+    vld.reportleaks(heap);
 
-    restoremodule((HMODULE)modulebase, m_patchtable, tablesize);
+    vld.unmapheap(heap);
 
-    return TRUE;
+    return HeapDestroy(heap);
 }
 
-// DidAlloc - Calls to IMalloc::DidAlloc will end up here. This function is just
-//   a wrapper around the system implementation of IMalloc::DidAlloc.
+// _LdrLoadDll - Calls to LdrLoadDll are patched through to this function. This
+//   function invokes the real LdrLoadDll and then re-attaches VLD to all
+//   modules loaded in the process after loading of the new DLL is complete.
+//   All modules must be re-enumerated because the explicit load of the
+//   specified module may result in the implicit load of one or more additional
+//   modules which are dependencies of the specified module.
 //
-//  - mem (IN): Pointer to a memory block to inquire about.
+//  - searchpath (IN): The path to use for searching for the specified module to
+//      be loaded.
+//
+//  - flags (IN): Pointer to action flags.
+//
+//  - modulename (IN): Pointer to a unicodestring_t structure specifying the
+//      name of the module to be loaded.
+//
+//  - modulehandle (OUT): Address of a HANDLE to receive the newly loaded
+//      module's handle.
 //
 //  Return Value:
 //
-//    Returns the value returned by the system implementation of
-//    IMalloc::DidAlloc.
+//    Returns the value returned by LdrLoadDll.
 //
-INT VisualLeakDetector::DidAlloc (LPVOID mem)
+NTSTATUS VisualLeakDetector::_LdrLoadDll (LPWSTR searchpath, PDWORD flags, unicodestring_t *modulename,
+                                          PHANDLE modulehandle)
 {
-    assert(m_imalloc != NULL);
-    return m_imalloc->DidAlloc(mem);
+    ModuleSet::Iterator  moduleit;
+    ModuleSet           *newmodules;
+    ModuleSet           *oldmodules;
+    NTSTATUS             status;
+
+    EnterCriticalSection(&vld.m_loaderlock);
+
+    // Load the DLL.
+    status = LdrLoadDll(searchpath, flags, modulename, modulehandle);
+    
+    if (STATUS_SUCCESS == status) {
+        // Create a new set of all loaded modules, including any newly loaded
+        // modules.
+        newmodules = new ModuleSet;
+        newmodules->reserve(MODULESETRESERVE);
+        EnumerateLoadedModulesW64(currentprocess, addloadedmodule, newmodules);
+
+        // Attach to all modules included in the set.
+        vld.attachtoloadedmodules(newmodules);
+
+        // Start using the new set of loaded modules.
+        EnterCriticalSection(&vld.m_moduleslock);
+        oldmodules = vld.m_loadedmodules;
+        vld.m_loadedmodules = newmodules;
+        LeaveCriticalSection(&vld.m_moduleslock);
+
+        // Free resources used by the old module list.
+        for (moduleit = oldmodules->begin(); moduleit != oldmodules->end(); ++moduleit) {
+            delete (*moduleit).name;
+            delete (*moduleit).path;
+        }
+        delete oldmodules;
+    }
+
+    LeaveCriticalSection(&vld.m_loaderlock);
+
+    return status;
 }
 
-// enabled - Determines if memory leak detection is enabled for the current
-//   thread.
+// _RtlAllocateHeap - Calls to RtlAllocateHeap are patched through to this
+//   function. This function invokes the real RtlAllocateHeap and then calls
+//   VLD's allocation tracking function. Pretty much all memory allocations
+//   will eventually result in a call to RtlAllocateHeap, so this is where we
+//   finally map the allocated block.
+//
+//  - heap (IN): Handle to the heap from which to allocate memory.
+//
+//  - flags (IN): Heap allocation control flags.
+//
+//  - size (IN): Size, in bytes, of the block to allocate.
 //
 //  Return Value:
 //
-//    Returns true if Visual Leak Detector is enabled for the current thread.
-//    Otherwise, returns false.
+//    Returns the return value from RtlAllocateHeap.
 //
-BOOL VisualLeakDetector::enabled ()
+LPVOID VisualLeakDetector::_RtlAllocateHeap (HANDLE heap, DWORD flags, SIZE_T size)
 {
-    tls_t *tls = vld.gettls();
+    BOOL                 crtalloc;
+    BOOL                 excluded = FALSE;
+    SIZE_T               fp;
+    LPVOID               block;
+    moduleinfo_t         moduleinfo;
+    ModuleSet::Iterator  moduleit;
+    SIZE_T               returnaddress;
+    tls_t               *tls = vld.gettls();
 
-    if (!(m_status & VLD_STATUS_INSTALLED)) {
-        // Memory leak detection is not yet enabled because VLD is still
-        // initializing.
-        return FALSE;
-    }
+    // Allocate the block.
+    block = RtlAllocateHeap(heap, flags, size);
+    if ((block != NULL) && vld.enabled()) {
+        if (tls->addrfp == 0x0) {
+            // This is the first call to enter VLD for the current allocation.
+            // Record the current frame pointer.
+            FRAMEPOINTER(fp);
+        }
+        else {
+            fp = tls->addrfp;
+        }
+        crtalloc = (tls->flags & VLD_TLS_CRTALLOC) ? TRUE : FALSE;
 
-    if (!(tls->flags & VLD_TLS_DISABLED) && !(tls->flags & VLD_TLS_ENABLED)) {
-        // The enabled/disabled state for the current thread has not been 
-        // initialized yet. Use the default state.
-        if (m_options & VLD_OPT_START_DISABLED) {
-            tls->flags |= VLD_TLS_DISABLED;
+        // Reset thread local flags and variables, in case any libraries called
+        // into while mapping the block allocate some memory.
+        tls->addrfp = 0x0;
+        tls->flags &=~VLD_TLS_CRTALLOC;
+
+        // Find the information for the module that initiated this allocation.
+        returnaddress = *((SIZE_T*)fp + 1);
+        moduleinfo.addrhigh = returnaddress;
+        moduleinfo.addrlow  = returnaddress;
+        EnterCriticalSection(&vld.m_moduleslock);
+        moduleit = vld.m_loadedmodules->find(moduleinfo);
+        if (moduleit != vld.m_loadedmodules->end()) {
+            excluded = (*moduleit).flags & VLD_MODULE_EXCLUDED ? TRUE : FALSE;
         }
-        else {
-            tls->flags |= VLD_TLS_ENABLED;
+        LeaveCriticalSection(&vld.m_moduleslock);
+        if (!excluded) {
+            // The module that initiated this allocation is included in leak
+            // detection. Map this block to the specified heap.
+            vld.mapblock(heap, block, size, fp, crtalloc);
         }
     }
 
-    return ((tls->flags & VLD_TLS_ENABLED) != 0);
+    // Reset thread local flags and variables for the next allocation.
+    tls->addrfp = 0x0;
+    tls->flags &= ~VLD_TLS_CRTALLOC;
+
+    return block;
 }
 
-// eraseduplicates - Erases, from the block maps, blocks that appear to be
-//   duplicate leaks of an already identified leak.
+// _RtlFreeHeap - Calls to RtlFreeHeap are patched through to this function.
+//   This function calls VLD's free tracking function and then invokes the real
+//   RtlFreeHeap. Pretty much all memory frees will eventually result in a call
+//   to RtlFreeHeap, so this is where we finally unmap the freed block.
 //
-//  - element (IN): BlockMap Iterator referencing the block of which to search
-//      for duplicates.
+//  - heap (IN): Handle to the heap to which the block being freed belongs.
+//
+//  - flags (IN): Heap control flags.
+//
+//  - mem (IN): Pointer to the memory block being freed.
 //
 //  Return Value:
 //
-//    Returns the number of duplicate blocks erased from the block map.
+//    Returns the value returned by RtlFreeHeap.
 //
-SIZE_T VisualLeakDetector::eraseduplicates (const BlockMap::Iterator &element)
+BOOL VisualLeakDetector::_RtlFreeHeap (HANDLE heap, DWORD flags, LPVOID mem)
 {
-    BlockMap::Iterator  blockit;
-    BlockMap           *blockmap;
-    blockinfo_t        *elementinfo;
-    SIZE_T              erased = 0;
-    HeapMap::Iterator   heapit;
-    blockinfo_t        *info;
-    BlockMap::Iterator  previt;
+    BOOL status;
 
-    elementinfo = (*element).second;
+    // Unmap the block from the specified heap.
+    vld.unmapblock(heap, mem);
 
-    // Iteratate through all block maps, looking for blocks with the same size
-    // and callstack as the specified element.
-    for (heapit = m_heapmap->begin(); heapit != m_heapmap->end(); ++heapit) {
-        blockmap = &(*heapit).second->blockmap;
-        for (blockit = blockmap->begin(); blockit != blockmap->end(); ++blockit) {
-            if (blockit == element) {
-                // Don't delete the element of which we are searching for
-                // duplicates.
-                continue;
-            }
-            info = (*blockit).second;
-            if ((info->size == elementinfo->size) && (*(info->callstack) == *(elementinfo->callstack))) {
-                // Found a duplicate. Erase it.
-                delete info->callstack;
-                delete info;
-                previt = blockit - 1;
-                blockmap->erase(blockit);
-                blockit = previt;
-                erased++;
-            }
-        }
-    }
+    status = RtlFreeHeap(heap, flags, mem);
 
-    return erased;
+    return status;
 }
 
-// Free - Calls to IMalloc::Free will end up here. This function is just a
-//   wrapper around the real IMalloc::Free implementation.
-//
-//  - mem (IN): Pointer to the memory block to be freed.
+// _RtlReAllocateHeap - Calls to RtlReAllocateHeap are patched through to this
+//   function. This function invokes the real RtlReAllocateHeap and then calls
+//   VLD's reallocation tracking function. All arguments passed to this function
+//   are passed on to the real RtlReAllocateHeap without modification. Pretty
+//   much all memory re-allocations will eventually result in a call to
+//   RtlReAllocateHeap, so this is where we finally remap the reallocated block.
 //
-//  Return Value:
+//  - heap (IN): Handle to the heap to reallocate memory from.
 //
-//    None.
+//  - flags (IN): Heap control flags.
 //
-VOID VisualLeakDetector::Free (LPVOID mem)
-{
-    assert(m_imalloc != NULL);
-    m_imalloc->Free(mem);
-}
-
-// GetSize - Calls to IMalloc::GetSize will end up here. This function is just a
-//   wrapper around the real IMalloc::GetSize implementation.
+//  - mem (IN): Pointer to the currently allocated block which is to be
+//      reallocated.
 //
-//  - mem (IN): Pointer to the memory block to inquire about.
+//  - size (IN): Size, in bytes, of the block to reallocate.
 //
 //  Return Value:
 //
-//    Returns the value returned by the system implementation of
-//    IMalloc::GetSize.
+//    Returns the value returned by RtlReAllocateHeap.
 //
-ULONG VisualLeakDetector::GetSize (LPVOID mem)
+LPVOID VisualLeakDetector::_RtlReAllocateHeap (HANDLE heap, DWORD flags, LPVOID mem, SIZE_T size)
 {
-    assert(m_imalloc != NULL);
-    return m_imalloc->GetSize(mem);
-}
+    BOOL                 crtalloc;
+    BOOL                 excluded = FALSE;
+    SIZE_T               fp;
+    moduleinfo_t         moduleinfo;
+    ModuleSet::Iterator  moduleit;
+    LPVOID               newmem;
+    SIZE_T               returnaddress;
+    tls_t               *tls = vld.gettls();
 
-// gettls - Obtains the thread local strorage structure for the calling thread.
-//
-//  Return Value:
-//
-//    Returns a pointer to the thread local storage structure. (This function
-//    always succeeds).
-//
-tls_t* VisualLeakDetector::gettls ()
-{
-    tls_t *tls;
-    
-    // Get the pointer to this thread's thread local storage structure.
-    tls = (tls_t*)TlsGetValue(m_tlsindex);
-    assert(GetLastError() == ERROR_SUCCESS);
+    // Reallocate the block.
+    newmem = RtlReAllocateHeap(heap, flags, mem, size);
 
-    if (tls == NULL) {
-        // This thread's thread local storage structure has not been allocated.
-        tls = new tls_t;
-        TlsSetValue(m_tlsindex, tls);
+    if (newmem != NULL) {
+        if (tls->addrfp == 0x0) {
+            // This is the first call to enter VLD for the current allocation.
+            // Record the current frame pointer.
+            FRAMEPOINTER(fp);
+        }
+        else {
+            fp = tls->addrfp;
+        }
+        crtalloc = (tls->flags & VLD_TLS_CRTALLOC) ? TRUE : FALSE;
+
+        // Reset thread local flags and variables, in case any libraries called
+        // into while remapping the block allocate some memory.
         tls->addrfp = 0x0;
-        tls->flags = 0x0;
-        tls->threadid = GetCurrentThreadId();
+        tls->flags &= ~VLD_TLS_CRTALLOC;
 
-        // Add this thread's TLS to the TlsSet.
-        EnterCriticalSection(&m_tlslock);
-        m_tlsset->insert(tls);
-        LeaveCriticalSection(&m_tlslock);
+        // Find the information for the module that initiated this reallocation.
+        returnaddress = *((SIZE_T*)fp + 1);
+        moduleinfo.addrhigh = returnaddress;
+        moduleinfo.addrlow  = returnaddress;
+        EnterCriticalSection(&vld.m_moduleslock);
+        moduleit = vld.m_loadedmodules->find(moduleinfo);
+        if (moduleit != vld.m_loadedmodules->end()) {
+            excluded = (*moduleit).flags & VLD_MODULE_EXCLUDED ? TRUE : FALSE;
+        }
+        LeaveCriticalSection(&vld.m_moduleslock);
+        if (!excluded) {
+            // The module that initiated this allocation is included in leak
+            // detection. Remap the block.
+            vld.remapblock(heap, mem, newmem, size, fp, crtalloc);
+        }
     }
 
-    return tls;
-}
+    // Reset thread local flags and variables for the next allocation.
+    tls->addrfp = 0x0;
+    tls->flags &= ~VLD_TLS_CRTALLOC;
 
-// HeapMinimize - Calls to IMalloc::HeapMinimize will end up here. This function
-//   is just a wrapper around the real IMalloc::HeapMinimize implementation.
-//
-//  Return Value:
-//
-//    None.
-//
-VOID VisualLeakDetector::HeapMinimize ()
-{
-    assert(m_imalloc != NULL);
-    m_imalloc->HeapMinimize();
+    return newmem;
 }
 
-// mapblock - Tracks memory allocations. Information about allocated blocks is
-//   collected and then the block is mapped to this information.
-//
-//  - heap (IN): Handle to the heap from which the block has been allocated.
+////////////////////////////////////////////////////////////////////////////////
 //
-//  - mem (IN): Pointer to the memory block being allocated.
+// COM IAT Replacement Functions
 //
-//  - size (IN): Size, in bytes, of the memory block being allocated.
+////////////////////////////////////////////////////////////////////////////////
+
+// _CoGetMalloc - Calls to CoGetMalloc are patched through to this function.
+//   This function returns a pointer to Visual Leak Detector's implementation
+//   of the IMalloc interface, instead of returning a pointer to the system
+//   implementation. This allows VLD's implementation of the IMalloc interface
+//   (which is basically a thin wrapper around the system implementation) to be
+//   invoked in place of the system implementation.
 //
-//  - framepointer (IN): Framepointer at the time this allocation first entered
-//      VLD's code. This is used from determining the starting point for the
-//      stack trace.
+//  - context (IN): Reserved; value must be 1.
 //
-//  - crtalloc (IN): Should be set to TRUE if this allocation is a CRT memory
-//      block. Otherwise should be FALSE.
+//  - imalloc (IN): Address of a pointer to receive the address of VLD's
+//      implementation of the IMalloc interface.
 //
 //  Return Value:
 //
-//    None.
+//    Always returns S_OK.
 //
-VOID VisualLeakDetector::mapblock (HANDLE heap, LPCVOID mem, SIZE_T size, SIZE_T framepointer, BOOL crtalloc)
+HRESULT VisualLeakDetector::_CoGetMalloc (DWORD context, LPMALLOC *imalloc)
 {
-    blockinfo_t        *blockinfo;
-    BlockMap::Iterator  blockit;
-    BlockMap           *blockmap;
-    HeapMap::Iterator   heapit;
-    static SIZE_T       serialnumber = 0;
+    static CoGetMalloc_t pCoGetMalloc = NULL;
 
-    // Record the block's information.
-    blockinfo = new blockinfo_t;
-    if (m_options & VLD_OPT_SAFE_STACK_WALK) {
-        blockinfo->callstack = new SafeCallStack;
-    }
-    else {
-        blockinfo->callstack = new FastCallStack;
-    }
-    if (m_options & VLD_OPT_TRACE_INTERNAL_FRAMES) {
-        // Passing NULL for the frame pointer argument will force the stack
-        // trace to begin at the current frame.
-        blockinfo->callstack->getstacktrace(m_maxtraceframes, NULL);
-    }
-    else {
-        // Start the stack trace at the call that first entered VLD's code.
-        blockinfo->callstack->getstacktrace(m_maxtraceframes, (SIZE_T*)framepointer);
+    HMODULE ole32;
+
+    *imalloc = (LPMALLOC)&vld;
+
+    if (pCoGetMalloc == NULL) {
+        // This is the first call to this function. Link to the real
+        // CoGetMalloc and get a pointer to the system implementation of the
+        // IMalloc interface.
+        ole32 = GetModuleHandle(L"ole32.dll");
+        pCoGetMalloc = (CoGetMalloc_t)GetProcAddress(ole32, "CoGetMalloc");
+        pCoGetMalloc(context, &vld.m_imalloc);
     }
-    blockinfo->serialnumber = serialnumber++;
-    blockinfo->size = size;
 
-    // Insert the block's information into the block map.
-    EnterCriticalSection(&m_maplock);
-    heapit = m_heapmap->find(heap);
-    if (heapit == m_heapmap->end()) {
-        // We haven't mapped this heap to a block map yet. Do it now.
-        mapheap(heap);
-        heapit = m_heapmap->find(heap);
-        assert(heapit != m_heapmap->end());
-    }
-    if (crtalloc == TRUE) {
-        // The heap that this block was allocated from is a CRT heap.
-        (*heapit).second->flags |= VLD_HEAP_CRT;
+    return S_OK;
+}
+
+// _CoTaskMemAlloc - Calls to CoTaskMemAlloc are patched through to this
+//   function. This function is just a wrapper around the real CoTaskMemAlloc
+//   that sets appropriate flags to be consulted when the memory is actually
+//   allocated by RtlAllocateHeap.
+//
+//  - size (IN): Size of the memory block to allocate.
+//
+//  Return Value:
+//
+//    Returns the value returned from CoTaskMemAlloc.
+//
+LPVOID VisualLeakDetector::_CoTaskMemAlloc (ULONG size)
+{
+    static CoTaskMemAlloc_t pCoTaskMemAlloc = NULL;
+
+    LPVOID   block;
+    SIZE_T   fp;
+    HMODULE  ole32;
+    tls_t   *tls = vld.gettls();
+
+    if (tls->addrfp == 0x0) {
+        // This is the first call to enter VLD for the current allocation.
+        // Record the current frame pointer.
+        FRAMEPOINTER(fp);
+        tls->addrfp = fp;
     }
-    blockmap = &(*heapit).second->blockmap;
-    blockit = blockmap->insert(mem, blockinfo);
-    if (blockit == blockmap->end()) {
-        // A block with this address has already been allocated. The
-        // previously allocated block must have been freed (probably by some
-        // mechanism unknown to VLD), or the heap wouldn't have allocated it
-        // again. Replace the previously allocated info with the new info.
-        blockit = blockmap->find(mem);
-        delete (*blockit).second->callstack;
-        delete (*blockit).second;
-        blockmap->erase(blockit);
-        blockmap->insert(mem, blockinfo);
+
+    if (pCoTaskMemAlloc == NULL) {
+        // This is the first call to this function. Link to the real
+        // CoTaskMemAlloc.
+        ole32 = GetModuleHandle(L"ole32.dll");
+        pCoTaskMemAlloc = (CoTaskMemAlloc_t)GetProcAddress(ole32, "CoTaskMemAlloc");
     }
-    LeaveCriticalSection(&m_maplock);
+
+    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
+    block = pCoTaskMemAlloc(size);
+
+    // Reset thread local flags and variables for the next allocation.
+    tls->addrfp = 0x0;
+    tls->flags &= ~VLD_TLS_CRTALLOC;
+    
+    return block;
 }
 
-// mapheap - Tracks heap creation. Creates a block map for tracking individual
-//   allocations from the newly created heap and then maps the heap to this
-//   block map.
+// _CoTaskMemRealloc - Calls to CoTaskMemRealloc are patched through to this
+//   function. This function is just a wrapper around the real CoTaskMemRealloc
+//   that sets appropriate flags to be consulted when the memory is actually
+//   allocated by RtlAllocateHeap.
 //
-//  - heap (IN): Handle to the newly created heap.
+//  - mem (IN): Pointer to the memory block to reallocate.
+//
+//  - size (IN): Size, in bytes, of the block to reallocate.
 //
 //  Return Value:
 //
-//    None.
+//    Returns the value returned from CoTaskMemRealloc.
 //
-VOID VisualLeakDetector::mapheap (HANDLE heap)
+LPVOID VisualLeakDetector::_CoTaskMemRealloc (LPVOID mem, ULONG size)
 {
-    heapinfo_t        *heapinfo;
-    HeapMap::Iterator  heapit;
+    static CoTaskMemRealloc_t pCoTaskMemRealloc = NULL;
 
-    // Create a new block map for this heap and insert it into the heap map.
-    heapinfo = new heapinfo_t;
-    heapinfo->blockmap.reserve(BLOCKMAPRESERVE);
-    heapinfo->flags = 0x0;
-    EnterCriticalSection(&m_maplock);
-    heapit = m_heapmap->insert(heap, heapinfo);
-    if (heapit == m_heapmap->end()) {
-        // Somehow this heap has been created twice without being destroyed,
-        // or at least it was destroyed without VLD's knowledge. Unmap the heap
-        // from the existing heapinfo, and remap it to the new one.
-        report(L"WARNING: Visual Leak Detector detected a duplicate heap (" ADDRESSFORMAT L").\n", heap);
-        heapit = m_heapmap->find(heap);
-        unmapheap((*heapit).first);
-        m_heapmap->insert(heap, heapinfo);
+    LPVOID   block;
+    SIZE_T   fp;
+    HMODULE  ole32;
+    tls_t   *tls = vld.gettls();
+
+    if (tls->addrfp == 0x0) {
+        // This is the first call to enter VLD for the current allocation.
+        // Record the current frame pointer.
+        FRAMEPOINTER(fp);
+        tls->addrfp = fp;
     }
-    LeaveCriticalSection(&m_maplock);
+
+    if (pCoTaskMemRealloc == NULL) {
+        // This is the first call to this function. Link to the real
+        // CoTaskMemRealloc.
+        ole32 = GetModuleHandle(L"ole32.dll");
+        pCoTaskMemRealloc = (CoTaskMemRealloc_t)GetProcAddress(ole32, "CoTaskMemRealloc");
+    }
+
+    // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
+    block = pCoTaskMemRealloc(mem, size);
+
+    // Reset thread local flags and variables for the next allocation.
+    tls->addrfp = 0x0;
+    tls->flags &= ~VLD_TLS_CRTALLOC;
+
+    return block;
 }
 
-// QueryInterface - Calls to IMalloc::QueryInterface will end up here. This
-//   function is just a wrapper around the real IMalloc::QueryInterface
-//   implementation.
+////////////////////////////////////////////////////////////////////////////////
 //
-//  - iid (IN): COM interface ID to query about.
+// Public COM IMalloc Implementation Functions
 //
-//  - object (IN): Address of a pointer to receive the requested interface
-//      pointer.
+////////////////////////////////////////////////////////////////////////////////
+
+// AddRef - Calls to IMalloc::AddRef end up here. This function is just a
+//   wrapper around the real IMalloc::AddRef implementation.
 //
 //  Return Value:
 //
 //    Returns the value returned by the system implementation of
-//    IMalloc::QueryInterface.
+//    IMalloc::AddRef.
 //
-HRESULT VisualLeakDetector::QueryInterface (REFIID iid, LPVOID *object)
+ULONG VisualLeakDetector::AddRef ()
 {
     assert(m_imalloc != NULL);
-    return m_imalloc->QueryInterface(iid, object);
+    return m_imalloc->AddRef();
 }
 
-// Realloc - Calls to IMalloc::Realloc will end up here. This function is just a
-//   wrapper around the real IMalloc::Realloc implementation that sets
-//   appropriate flags to be consulted when the memory is actually allocated by
-//   RtlAllocateHeap.
-//
-//  - mem (IN): Pointer to the memory block to reallocate.
+// Alloc - Calls to IMalloc::Alloc end up here. This function is just a wrapper
+//   around the real IMalloc::Alloc implementation that sets appropriate flags
+//   to be consulted when the memory is actually allocated by RtlAllocateHeap.
 //
-//  - size (IN): Size, in bytes, of the memory block to reallocate.
+//  - size (IN): The size of the memory block to allocate.
 //
 //  Return Value:
 //
-//    Returns the value returned by the system implementation of
-//    IMalloc::Realloc.
+//    Returns the value returned by the system's IMalloc::Alloc implementation.
 //
-LPVOID VisualLeakDetector::Realloc (LPVOID mem, ULONG size)
+LPVOID VisualLeakDetector::Alloc (ULONG size)
 {
     LPVOID  block;
     SIZE_T  fp;
@@ -2988,351 +2604,145 @@ LPVOID VisualLeakDetector::Realloc (LPVOID mem, ULONG size)
         tls->addrfp = fp;
     }
 
-    // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
+    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
     assert(m_imalloc != NULL);
-    block = m_imalloc->Realloc(mem, size);
+    block = m_imalloc->Alloc(size);
 
     // Reset thread local flags and variables for the next allocation.
     tls->addrfp = 0x0;
     tls->flags &= ~VLD_TLS_CRTALLOC;
-    
+
     return block;
 }
 
-// Release - Calls to IMalloc::Release will end up here. This function is just
-//   a wrapper around the real IMalloc::Release implementation.
+// DidAlloc - Calls to IMalloc::DidAlloc will end up here. This function is just
+//   a wrapper around the system implementation of IMalloc::DidAlloc.
+//
+//  - mem (IN): Pointer to a memory block to inquire about.
 //
 //  Return Value:
 //
 //    Returns the value returned by the system implementation of
-//    IMalloc::Release.
+//    IMalloc::DidAlloc.
 //
-ULONG VisualLeakDetector::Release ()
+INT VisualLeakDetector::DidAlloc (LPVOID mem)
 {
     assert(m_imalloc != NULL);
-    return m_imalloc->Release();
+    return m_imalloc->DidAlloc(mem);
 }
 
-// remapblock - Tracks reallocations. Unmaps a block from its previously
-//   collected information and remaps it to updated information.
-//
-//  Note: If the block itself remains at the same address, then the block's
-//   information can simply be updated rather than having to actually erase and
-//   reinsert the block.
-//
-//  - heap (IN): Handle to the heap from which the memory is being reallocated.
-//
-//  - mem (IN): Pointer to the memory block being reallocated.
-//
-//  - newmem (IN): Pointer to the memory block being returned to the caller
-//      that requested the reallocation. This pointer may or may not be the same
-//      as the original memory block (as pointed to by "mem").
-//
-//  - size (IN): Size, in bytes, of the new memory block.
-//
-//  - framepointer (IN): The frame pointer at which this reallocation entered
-//      VLD's code. Used for determining the starting point of the stack trace.
+// Free - Calls to IMalloc::Free will end up here. This function is just a
+//   wrapper around the real IMalloc::Free implementation.
 //
-//  - crtalloc (IN): Should be set to TRUE if this reallocation is for a CRT
-//      memory block. Otherwise should be set to FALSE.
+//  - mem (IN): Pointer to the memory block to be freed.
 //
 //  Return Value:
 //
 //    None.
 //
-VOID VisualLeakDetector::remapblock (HANDLE heap, LPCVOID mem, LPCVOID newmem, SIZE_T size, SIZE_T framepointer,
-                                     BOOL crtalloc)
+VOID VisualLeakDetector::Free (LPVOID mem)
 {
-    BlockMap::Iterator   blockit;
-    BlockMap            *blockmap;
-    HeapMap::Iterator    heapit;
-    blockinfo_t         *info;
-
-    if (newmem != mem) {
-        // The block was not reallocated in-place. Instead the old block was
-        // freed and a new block allocated to satisfy the new size.
-        unmapblock(heap, mem);
-        mapblock(heap, newmem, size, framepointer, crtalloc);
-        return;
-    }
-
-    // The block was reallocated in-place. Find the existing blockinfo_t
-    // entry in the block map and update it with the new callstack and size.
-    EnterCriticalSection(&m_maplock);
-    heapit = m_heapmap->find(heap);
-    if (heapit == m_heapmap->end()) {
-        // We haven't mapped this heap to a block map yet. Obviously the
-        // block has also not been mapped to a blockinfo_t entry yet either,
-        // so treat this reallocation as a brand-new allocation (this will
-        // also map the heap to a new block map).
-        mapblock(heap, newmem, size, framepointer, crtalloc);
-        LeaveCriticalSection(&m_maplock);
-        return;
-    }
-
-    // Find the block's blockinfo_t structure so that we can update it.
-    blockmap = &(*heapit).second->blockmap;
-    blockit = blockmap->find(mem);
-    if (blockit == blockmap->end()) {
-        // The block hasn't been mapped to a blockinfo_t entry yet.
-        // Treat this reallocation as a new allocation.
-        mapblock(heap, newmem, size, framepointer, crtalloc);
-        LeaveCriticalSection(&m_maplock);
-        return;
-    }
-
-    // Found the blockinfo_t entry for this block. Update it with
-    // a new callstack and new size.
-    info = (*blockit).second;
-    info->callstack->clear();
-    if (crtalloc) {
-        // The heap that this block was allocated from is a CRT heap.
-        (*heapit).second->flags |= VLD_HEAP_CRT;
-    }
-    LeaveCriticalSection(&m_maplock);
+    assert(m_imalloc != NULL);
+    m_imalloc->Free(mem);
+}
 
-    // Update the block's callstack and size.
-    if (m_options & VLD_OPT_TRACE_INTERNAL_FRAMES) {
-        // Passing NULL for the frame pointer argument will force
-        // the stack trace to begin at the current frame.
-        info->callstack->getstacktrace(m_maxtraceframes, NULL);
-    }
-    else {
-        // Start the stack trace at the call that first entered
-        // VLD's code.
-        info->callstack->getstacktrace(m_maxtraceframes, (SIZE_T*)framepointer);
-    }
-    info->size = size;
+// GetSize - Calls to IMalloc::GetSize will end up here. This function is just a
+//   wrapper around the real IMalloc::GetSize implementation.
+//
+//  - mem (IN): Pointer to the memory block to inquire about.
+//
+//  Return Value:
+//
+//    Returns the value returned by the system implementation of
+//    IMalloc::GetSize.
+//
+ULONG VisualLeakDetector::GetSize (LPVOID mem)
+{
+    assert(m_imalloc != NULL);
+    return m_imalloc->GetSize(mem);
 }
 
-// reportconfig - Generates a brief report summarizing Visual Leak Detector's
-//   configuration, as loaded from the vld.ini file.
+// HeapMinimize - Calls to IMalloc::HeapMinimize will end up here. This function
+//   is just a wrapper around the real IMalloc::HeapMinimize implementation.
 //
 //  Return Value:
 //
 //    None.
 //
-VOID VisualLeakDetector::reportconfig ()
+VOID VisualLeakDetector::HeapMinimize ()
 {
-    if (m_options & VLD_OPT_AGGREGATE_DUPLICATES) {
-        report(L"    Aggregating duplicate leaks.\n");
-    }
-    if (wcslen(m_forcedmodulelist) != 0) {
-        report(L"    Forcing inclusion of these modules in leak detection: %s\n", m_forcedmodulelist);
-    }
-    if (m_maxdatadump != VLD_DEFAULT_MAX_DATA_DUMP) {
-        if (m_maxdatadump == 0) {
-            report(L"    Suppressing data dumps.\n");
-        }
-        else {
-            report(L"    Limiting data dumps to %lu bytes.\n", m_maxdatadump);
-        }
-    }
-    if (m_maxtraceframes != VLD_DEFAULT_MAX_TRACE_FRAMES) {
-        report(L"    Limiting stack traces to %u frames.\n", m_maxtraceframes);
-    }
-    if (m_options & VLD_OPT_UNICODE_REPORT) {
-        report(L"    Generating a Unicode (UTF-16) encoded report.\n");
-    }
-    if (m_options & VLD_OPT_REPORT_TO_FILE) {
-        if (m_options & VLD_OPT_REPORT_TO_DEBUGGER) {
-            report(L"    Outputting the report to the debugger and to %s\n", m_reportfilepath);
-        }
-        else {
-            report(L"    Outputting the report to %s\n", m_reportfilepath);
-        }
-    }
-    if (m_options & VLD_OPT_SLOW_DEBUGGER_DUMP) {
-        report(L"    Outputting the report to the debugger at a slower rate.\n");
-    }
-    if (m_options & VLD_OPT_SAFE_STACK_WALK) {
-        report(L"    Using the \"safe\" (but slow) stack walking method.\n");
-    }
-    if (m_options & VLD_OPT_SELF_TEST) {
-        report(L"    Perfoming a memory leak self-test.\n");
-    }
-    if (m_options & VLD_OPT_START_DISABLED) {
-        report(L"    Starting with memory leak detection disabled.\n");
-    }
-    if (m_options & VLD_OPT_TRACE_INTERNAL_FRAMES) {
-        report(L"    Including heap and VLD internal frames in stack traces.\n");
-    }
+    assert(m_imalloc != NULL);
+    m_imalloc->HeapMinimize();
 }
 
-// reportleaks - Generates a memory leak report for the specified heap.
+// QueryInterface - Calls to IMalloc::QueryInterface will end up here. This
+//   function is just a wrapper around the real IMalloc::QueryInterface
+//   implementation.
 //
-//  - heap (IN): Handle to the heap for which to generate a memory leak
-//      report.
+//  - iid (IN): COM interface ID to query about.
+//
+//  - object (IN): Address of a pointer to receive the requested interface
+//      pointer.
 //
 //  Return Value:
 //
-//    None.
+//    Returns the value returned by the system implementation of
+//    IMalloc::QueryInterface.
 //
-VOID VisualLeakDetector::reportleaks (HANDLE heap)
+HRESULT VisualLeakDetector::QueryInterface (REFIID iid, LPVOID *object)
 {
-    LPCVOID              address;
-    LPCVOID              block;
-    BlockMap::Iterator   blockit;
-    BlockMap            *blockmap;
-    crtdbgblockheader_t *crtheader;
-    SIZE_T               duplicates;
-    heapinfo_t          *heapinfo;
-    HeapMap::Iterator    heapit;
-    blockinfo_t         *info;
-    SIZE_T               size;
-
-    // Find the heap's information (blockmap, etc).
-    EnterCriticalSection(&m_maplock);
-    heapit = m_heapmap->find(heap);
-    if (heapit == m_heapmap->end()) {
-        // Nothing is allocated from this heap. No leaks.
-        LeaveCriticalSection(&m_maplock);
-        return;
-    }
-
-    heapinfo = (*heapit).second;
-    blockmap = &heapinfo->blockmap;
-    for (blockit = blockmap->begin(); blockit != blockmap->end(); ++blockit) {
-        // Found a block which is still in the BlockMap. We've identified a
-        // potential memory leak.
-        block = (*blockit).first;
-        info = (*blockit).second;
-        address = block;
-        size = info->size;
-        if (heapinfo->flags & VLD_HEAP_CRT) {
-            // This block is allocated to a CRT heap, so the block has a CRT
-            // memory block header prepended to it.
-            crtheader = (crtdbgblockheader_t*)block;
-            if (CRT_USE_TYPE(crtheader->use) == CRT_USE_INTERNAL) {
-                // This block is marked as being used internally by the CRT.
-                // The CRT will free the block after VLD is destroyed.
-                continue;
-            }
-            // The CRT header is more or less transparent to the user, so
-            // the information about the contained block will probably be
-            // more useful to the user. Accordingly, that's the information
-            // we'll include in the report.
-            address = CRTDBGBLOCKDATA(block);
-            size = crtheader->size;
-        }
-        // It looks like a real memory leak.
-        if (m_leaksfound == 0) {
-            report(L"WARNING: Visual Leak Detector detected memory leaks!\n");
-        }
-        m_leaksfound++;
-        report(L"---------- Block %ld at " ADDRESSFORMAT L": %u bytes ----------\n", info->serialnumber, address, size);
-        if (m_options & VLD_OPT_AGGREGATE_DUPLICATES) {
-            // Aggregate all other leaks which are duplicates of this one
-            // under this same heading, to cut down on clutter.
-            duplicates = eraseduplicates(blockit);
-            if (duplicates) {
-                report(L"A total of %lu leaks match this size and call stack. Showing only the first one.\n",
-                       duplicates + 1);
-                m_leaksfound += duplicates;
-            }
-        }
-        // Dump the call stack.
-        report(L"  Call Stack:\n");
-        info->callstack->dump(m_options & VLD_OPT_TRACE_INTERNAL_FRAMES);
-        // Dump the data in the user data section of the memory block.
-        if (m_maxdatadump != 0) {
-            report(L"  Data:\n");
-            if (m_options & VLD_OPT_UNICODE_REPORT) {
-                dumpmemoryw(address, (m_maxdatadump < size) ? m_maxdatadump : size);
-            }
-            else {
-                dumpmemorya(address, (m_maxdatadump < size) ? m_maxdatadump : size);
-            }
-        }
-        report(L"\n");
-    }
-
-    LeaveCriticalSection(&m_maplock);
+    assert(m_imalloc != NULL);
+    return m_imalloc->QueryInterface(iid, object);
 }
 
-// unmapblock - Tracks memory blocks that are freed. Unmaps the specified block
-//   from the block's information, relinquishing internally allocated resources.
+// Realloc - Calls to IMalloc::Realloc will end up here. This function is just a
+//   wrapper around the real IMalloc::Realloc implementation that sets
+//   appropriate flags to be consulted when the memory is actually allocated by
+//   RtlAllocateHeap.
 //
-//  - heap (IN): Handle to the heap to which this block is being freed.
+//  - mem (IN): Pointer to the memory block to reallocate.
 //
-//  - mem (IN): Pointer to the memory block being freed.
+//  - size (IN): Size, in bytes, of the memory block to reallocate.
 //
 //  Return Value:
 //
-//    None.
+//    Returns the value returned by the system implementation of
+//    IMalloc::Realloc.
 //
-VOID VisualLeakDetector::unmapblock (HANDLE heap, LPCVOID mem)
+LPVOID VisualLeakDetector::Realloc (LPVOID mem, ULONG size)
 {
-    BlockMap::Iterator  blockit;
-    BlockMap           *blockmap;
-    HeapMap::Iterator   heapit;
-    blockinfo_t        *info;
+    LPVOID  block;
+    SIZE_T  fp;
+    tls_t  *tls = vld.gettls();
 
-    // Find this heap's block map.
-    EnterCriticalSection(&m_maplock);
-    heapit = m_heapmap->find(heap);
-    if (heapit == m_heapmap->end()) {
-        // We don't have a block map for this heap. We must not have monitored
-        // this allocation (probably happened before VLD was initialized).
-        LeaveCriticalSection(&m_maplock);
-        return;
+    if (tls->addrfp == 0x0) {
+        // This is the first call to enter VLD for the current allocation.
+        // Record the current frame pointer.
+        FRAMEPOINTER(fp);
+        tls->addrfp = fp;
     }
 
-    // Find this block in the block map.
-    blockmap = &(*heapit).second->blockmap;
-    blockit = blockmap->find(mem);
-    if (blockit == blockmap->end()) {
-        // This block is not in the block map. We must not have monitored this
-        // allocation (probably happened before VLD was initialized).
-        LeaveCriticalSection(&m_maplock);
-        return;
-    }
+    // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
+    assert(m_imalloc != NULL);
+    block = m_imalloc->Realloc(mem, size);
 
-    // Free the blockinfo_t structure and erase it from the block map.
-    info = (*blockit).second;
-    delete info->callstack;
-    delete info;
-    blockmap->erase(blockit);
-    LeaveCriticalSection(&m_maplock);
+    // Reset thread local flags and variables for the next allocation.
+    tls->addrfp = 0x0;
+    tls->flags &= ~VLD_TLS_CRTALLOC;
+    
+    return block;
 }
 
-// unmapheap - Tracks heap destruction. Unmaps the specified heap from its block
-//   map. The block map is cleared and deleted, relinquishing internally
-//   allocated resources.
-//
-//  - heap (IN): Handle to the heap which is being destroyed.
+// Release - Calls to IMalloc::Release will end up here. This function is just
+//   a wrapper around the real IMalloc::Release implementation.
 //
 //  Return Value:
 //
-//    None.
+//    Returns the value returned by the system implementation of
+//    IMalloc::Release.
 //
-VOID VisualLeakDetector::unmapheap (HANDLE heap)
+ULONG VisualLeakDetector::Release ()
 {
-    BlockMap::Iterator  blockit;
-    BlockMap           *blockmap;
-    heapinfo_t         *heapinfo;
-    HeapMap::Iterator   heapit;
-
-    // Find this heap's block map.
-    EnterCriticalSection(&m_maplock);
-    heapit = m_heapmap->find(heap);
-    if (heapit == m_heapmap->end()) {
-        // This heap hasn't been mapped. We must not have monitored this heap's
-        // creation (probably happened before VLD was initialized).
-        LeaveCriticalSection(&m_maplock);
-        return;
-    }
-
-    // Free all of the blockinfo_t structures stored in the block map.
-    heapinfo = (*heapit).second;
-    blockmap = &heapinfo->blockmap;
-    for (blockit = blockmap->begin(); blockit != blockmap->end(); ++blockit) {
-        delete (*blockit).second->callstack;
-        delete (*blockit).second;
-    }
-    delete heapinfo;
-
-    // Remove this heap's block map from the heap map.
-    m_heapmap->erase(heapit);
-    LeaveCriticalSection(&m_maplock);
+    assert(m_imalloc != NULL);
+    return m_imalloc->Release();
 }
diff --git a/development/Win32/vld/src/vld.h b/development/Win32/vld/src/vld.h
new file mode 100644 (file)
index 0000000..234c87f
--- /dev/null
@@ -0,0 +1,97 @@
+////////////////////////////////////////////////////////////////////////////////\r
+//\r
+//  Visual Leak Detector - Import Library Header\r
+//  Copyright (c) 2006 Dan Moulding\r
+//\r
+//  This library is free software; you can redistribute it and/or\r
+//  modify it under the terms of the GNU Lesser General Public\r
+//  License as published by the Free Software Foundation; either\r
+//  version 2.1 of the License, or (at your option) any later version.\r
+//\r
+//  This library is distributed in the hope that it will be useful,\r
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+//  Lesser General Public License for more details.\r
+//\r
+//  You should have received a copy of the GNU Lesser General Public\r
+//  License along with this library; if not, write to the Free Software\r
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
+//\r
+//  See COPYING.txt for the full terms of the GNU Lesser General Public License.\r
+//\r
+////////////////////////////////////////////////////////////////////////////////\r
+\r
+#pragma once\r
+\r
+#ifdef _DEBUG\r
+\r
+#pragma comment(lib, "vld.lib")\r
+\r
+// Force a symbolic reference to the global VisualLeakDetector class object from\r
+// the DLL. This enusres that the DLL is loaded and linked with the program,\r
+// even if no code otherwise imports any of the DLL's exports.\r
+#pragma comment(linker, "/include:__imp_?vld@@3VVisualLeakDetector@@A")\r
+\r
+////////////////////////////////////////////////////////////////////////////////\r
+//\r
+//  Visual Leak Detector APIs\r
+//\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif // __cplusplus\r
+\r
+// VLDDisable - Disables Visual Leak Detector's memory leak detection at\r
+//   runtime. If memory leak detection is already disabled, then calling this\r
+//   function has no effect.\r
+//\r
+//  Note: In multithreaded programs, this function operates on a per-thread\r
+//    basis. In other words, if you call this function from one thread, then\r
+//    memory leak detection is only disabled for that thread. If memory leak\r
+//    detection is enabled for other threads, then it will remain enabled for\r
+//    those other threads. It was designed to work this way to insulate you,\r
+//    the programmer, from having to ensure thread synchronization when calling\r
+//    VLDEnable() and VLDDisable(). Without this, calling these two functions\r
+//    unsychronized could result in unpredictable and unintended behavior.\r
+//    But this also means that if you want to disable memory leak detection\r
+//    process-wide, then you need to call this function from every thread in\r
+//    the process.\r
+//\r
+//  Return Value:\r
+//\r
+//    None.\r
+//\r
+__declspec(dllimport) void VLDDisable ();\r
+\r
+// VLDEnable - Enables Visual Leak Detector's memory leak detection at runtime.\r
+//   If memory leak detection is already enabled, which it is by default, then\r
+//   calling this function has no effect.\r
+//\r
+//  Note: In multithreaded programs, this function operates on a per-thread\r
+//    basis. In other words, if you call this function from one thread, then\r
+//    memory leak detection is only enabled for that thread. If memory leak\r
+//    detection is disabled for other threads, then it will remain disabled for\r
+//    those other threads. It was designed to work this way to insulate you,\r
+//    the programmer, from having to ensure thread synchronization when calling\r
+//    VLDEnable() and VLDDisable(). Without this, calling these two functions\r
+//    unsychronized could result in unpredictable and unintended behavior.\r
+//    But this also means that if you want to enable memory leak detection\r
+//    process-wide, then you need to call this function from every thread in\r
+//    the process.\r
+//\r
+//  Return Value:\r
+//\r
+//    None.\r
+//\r
+__declspec(dllimport) void VLDEnable ();\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif // __cplusplus\r
+\r
+#else // !_DEBUG\r
+\r
+#define VLDEnable()\r
+#define VLDDisable()\r
+\r
+#endif // _DEBUG\r
index 9ff15e5e938bb97f6d20559d1fde4c8d6135abc6..eb29ef267bde72fd3c39d50fb5a42c18ff730311 100644 (file)
@@ -1,5 +1,4 @@
 ////////////////////////////////////////////////////////////////////////////////
-//  $Id: vldapi.cpp,v 1.19 2006/11/18 03:12:35 dmouldin Exp $
 //
 //  Visual Leak Detector - Exported APIs
 //  Copyright (c) 2005-2006 Dan Moulding
index cb2d13972c474c53a80239983d1ad2d02528d1e7..b6dff2eed34cf08da5a00e8aa48be5f6fb95359b 100644 (file)
@@ -1,5 +1,4 @@
 ////////////////////////////////////////////////////////////////////////////////
-//  $Id: vldheap.cpp,v 1.13 2006/11/18 03:12:35 dmouldin Exp $
 //
 //  Visual Leak Detector - Internal C++ Heap Management
 //  Copyright (c) 2006 Dan Moulding
@@ -35,7 +34,7 @@ CRITICAL_SECTION  vldheaplock;         // Serializes access to VLD's private hea
 
 // Local helper functions.
 static inline void vlddelete (void *block);
-static inline void* vldnew (unsigned int size, const char *file, int line);
+static inline void* vldnew (size_t size, const char *file, int line);
 
 // scalar delete operator - Delete operator used to free internally used memory
 //   back to VLD's private heap.
@@ -105,7 +104,7 @@ void operator delete [] (void *block, const char *, int)
 //    If the allocation succeeds, a pointer to the allocated memory block is
 //    returned. If the allocation fails, NULL is returned.
 //
-void* operator new (unsigned int size, const char *file, int line)
+void* operator new (size_t size, const char *file, int line)
 {
     return vldnew(size, file, line);
 }
@@ -126,7 +125,7 @@ void* operator new (unsigned int size, const char *file, int line)
 //    If the allocation succeeds, a pointer to the allocated memory block is
 //    returned. If the allocation fails, NULL is returned.
 //
-void* operator new [] (unsigned int size, const char *file, int line)
+void* operator new [] (size_t size, const char *file, int line)
 {
     return vldnew(size, file, line);
 }
@@ -182,7 +181,7 @@ void vlddelete (void *block)
 //    If the memory allocation succeeds, a pointer to the allocated memory
 //    block is returned. If the allocation fails, NULL is returned.
 //
-void* vldnew (unsigned int size, const char *file, int line)
+void* vldnew (size_t size, const char *file, int line)
 {
     vldblockheader_t *header = (vldblockheader_t*)RtlAllocateHeap(vldheap, 0x0, size + sizeof(vldblockheader_t));
     static SIZE_T     serialnumber = 0;
@@ -210,4 +209,4 @@ void* vldnew (unsigned int size, const char *file, int line)
 
     // Return a pointer to the beginning of the data section of the block.
     return (void*)VLDBLOCKDATA(header);
-}
\ No newline at end of file
+}
index ccbc07621c761e71c0c78be6761ea31d02406293..72bd91c091d617098c4f67307c93139491627474 100644 (file)
@@ -1,5 +1,4 @@
 ////////////////////////////////////////////////////////////////////////////////
-//  $Id: vldheap.h,v 1.11 2006/11/18 03:12:35 dmouldin Exp $
 //
 //  Visual Leak Detector - Internal C++ Heap Management Definitions
 //  Copyright (c) 2006 Dan Moulding
@@ -72,7 +71,7 @@ typedef struct vldblockheader_s
     struct vldblockheader_s *prev;          // Pointer to the preceding block in the list of internally allocated blocks.
     const char              *file;          // Name of the file where this block was allocated.
     int                      line;          // Line number within the above file where this block was allocated.
-    unsigned int             size;          // The size of this memory block, not including this header.
+    size_t                   size;          // The size of this memory block, not including this header.
     SIZE_T                   serialnumber;  // Each block is assigned a unique serial number, starting from zero.
 } vldblockheader_t;
 
@@ -87,8 +86,8 @@ void operator delete (void *block);
 void operator delete [] (void *block);
 void operator delete (void *block, const char *file, int line);
 void operator delete [] (void *block, const char *file, int line);
-void* operator new (unsigned int size, const char *file, int line);
-void* operator new [] (unsigned int size, const char *file, int line);
+void* operator new (size_t size, const char *file, int line);
+void* operator new [] (size_t size, const char *file, int line);
 
 // All calls to the new operator from within VLD are mapped to the version of
 // new that allocates from VLD's private heap.
index ed87293baf0de7118bbd52724359beb67666f771..2c0760767534d9884dd0e4bcce1ed50ba9065690 100644 (file)
@@ -1,8 +1,7 @@
 ////////////////////////////////////////////////////////////////////////////////
-//  $Id: vldint.h,v 1.45 2006/11/18 05:17:09 dmouldin Exp $
 //
 //  Visual Leak Detector - VisualLeakDetector Class Definition
-//  Copyright (c) 2005-2006 Dan Moulding
+//  Copyright (c) 2005-2009 Dan Moulding
 //
 //  This library is free software; you can redistribute it and/or
 //  modify it under the terms of the GNU Lesser General Public
@@ -42,12 +41,27 @@ Applications should never include this header."
 #define SELFTESTTEXTA       "Memory Leak Self-Test"
 #define SELFTESTTEXTW       L"Memory Leak Self-Test"
 #define VLDREGKEYPRODUCT    L"Software\\Visual Leak Detector"
-#define VLDVERSION          L"1.9f"
+#define VLDVERSION          L"1.9h"
 
 // The Visual Leak Detector APIs.
 extern "C" __declspec(dllexport) void VLDDisable ();
 extern "C" __declspec(dllexport) void VLDEnable ();
 
+// Function pointer types for explicit dynamic linking with functions listed in
+// the import patch table.
+typedef void* (__cdecl *_calloc_dbg_t) (size_t, size_t, int, const char*, int);
+typedef void* (__cdecl *_malloc_dbg_t) (size_t, int, const char *, int);
+typedef void* (__cdecl *_realloc_dbg_t) (void *, size_t, int, const char *, int);
+typedef void* (__cdecl *calloc_t) (size_t, size_t);
+typedef HRESULT (__stdcall *CoGetMalloc_t) (DWORD, LPMALLOC *);
+typedef LPVOID (__stdcall *CoTaskMemAlloc_t) (ULONG);
+typedef LPVOID (__stdcall *CoTaskMemRealloc_t) (LPVOID, ULONG);
+typedef void* (__cdecl *malloc_t) (size_t);
+typedef void* (__cdecl *new_t) (size_t);
+typedef void* (__cdecl *new_dbg_crt_t) (size_t, int, const char *, int);
+typedef void* (__cdecl *new_dbg_mfc_t) (size_t, const char *, int);
+typedef void* (__cdecl *realloc_t) (void *, size_t);
+
 // Data is collected for every block allocated from any heap in the process.
 // The data is stored in this structure and these structures are stored in
 // a BlockMap which maps each of these structures to its corresponding memory
@@ -100,7 +114,7 @@ typedef struct moduleinfo_s {
 typedef Set<moduleinfo_t> ModuleSet;
 
 // Thread local storage structure. Every thread in the process gets its own copy
-// of this structure. Thread specific information, such as the currentl leak
+// of this structure. Thread specific information, such as the current leak
 // detection status (enabled or disabled) and the address that initiated the
 // current allocation is stored here.
 typedef struct tls_s {
@@ -148,73 +162,88 @@ public:
     VisualLeakDetector();
     ~VisualLeakDetector();
 
-    // Public IMalloc methods - for support of COM-based memory leak detection.
-    ULONG __stdcall AddRef ();
-    LPVOID __stdcall Alloc (ULONG size);
-    INT __stdcall DidAlloc (LPVOID mem);
-    VOID __stdcall Free (LPVOID mem);
-    ULONG __stdcall GetSize (LPVOID mem);
-    VOID __stdcall HeapMinimize ();
+////////////////////////////////////////////////////////////////////////////////
+// Public CRT and MFC Common Handlers
+//
+// Many heap functions are indirectly rerouted to these handlers. One common
+// function exists for each heap function with a given signature. These
+// handlers are not direct IAT replacements, but are called by the individual
+// IAT replacement functions.
+////////////////////////////////////////////////////////////////////////////////
+    // Standard CRT and MFC common handlers
+    void* _calloc (calloc_t pcalloc, SIZE_T fp, size_t num, size_t size);
+    void* _malloc (malloc_t pmalloc, SIZE_T fp, size_t size);
+    void* _new (new_t pnew, SIZE_T fp, size_t size); 
+    void* _realloc (realloc_t prealloc, SIZE_T fp, void *mem, size_t size);
+
+    // Debug CRT and MFC common handlers
+    void* __calloc_dbg (_calloc_dbg_t p_calloc_dbg, SIZE_T fp, size_t num, size_t size, int type, char const *file, int line);
+    void* __malloc_dbg (_malloc_dbg_t p_malloc_dbg, SIZE_T fp, size_t size, int type, char const *file, int line);
+    void* new_dbg_crt (new_dbg_crt_t pnew_dbg_crt, SIZE_T fp, size_t size, int type, char const *file, int line);
+    void* new_dbg_mfc (new_dbg_crt_t pnew_dbg, SIZE_T fp, size_t size, int type, char const *file, int line);
+    void* new_dbg_mfc (new_dbg_mfc_t pnew_dbg_mfc, SIZE_T fp, size_t size, char const *file, int line);
+    void* __realloc_dbg (_realloc_dbg_t p_realloc_dbg, SIZE_T fp, void *mem, size_t size, int type, char const *file, int line);
+
+////////////////////////////////////////////////////////////////////////////////
+// Public IMalloc methods - for support of COM-based memory leak detection.
+////////////////////////////////////////////////////////////////////////////////
+    ULONG   __stdcall AddRef ();
+    LPVOID  __stdcall Alloc (ULONG size);
+    INT     __stdcall DidAlloc (LPVOID mem);
+    VOID    __stdcall Free (LPVOID mem);
+    ULONG   __stdcall GetSize (LPVOID mem);
+    VOID    __stdcall HeapMinimize ();
     HRESULT __stdcall QueryInterface (REFIID iid, LPVOID *object);
-    LPVOID __stdcall Realloc (LPVOID mem, ULONG size);
-    ULONG __stdcall Release ();
+    LPVOID  __stdcall Realloc (LPVOID mem, ULONG size);
+    ULONG   __stdcall Release ();
 
 private:
-    // Import patching replacement functions - see each function definition for details.
-    static HRESULT __stdcall _CoGetMalloc (DWORD context, LPMALLOC *imalloc);
-    static LPVOID __stdcall _CoTaskMemAlloc (ULONG size);
-    static LPVOID __stdcall _CoTaskMemRealloc (LPVOID mem, ULONG size);
-    static void* __cdecl _crt80d__calloc_dbg (size_t num, size_t size, int type, const char *file, int line);
-    static void* __cdecl _crt80d__malloc_dbg (size_t size, int type, const char *file, int line);
-    static void* __cdecl _crt80d__realloc_dbg (void *mem, size_t size, int type, const char *file, int line);
-    static void* __cdecl _crt80d__scalar_new_dbg (unsigned int size, int type, const char *file, int line);
-    static void* __cdecl _crt80d__vector_new_dbg (unsigned int size, int type, const char *file, int line);
-    static void* __cdecl _crt80d_calloc (size_t num, size_t size);
-    static void* __cdecl _crt80d_malloc (size_t size);
-    static void* __cdecl _crt80d_realloc (void *mem, size_t size);
-    static void* __cdecl _crt80d_scalar_new (unsigned int size);
-    static void* __cdecl _crt80d_vector_new (unsigned int size);
-    static void* __cdecl _crtd__calloc_dbg (size_t num, size_t size, int type, const char *file, int line);
-    static void* __cdecl _crtd__malloc_dbg (size_t size, int type, const char *file, int line);
-    static void* __cdecl _crtd__realloc_dbg (void *mem, size_t size, int type, const char *file, int line);
-    static void* __cdecl _crtd__scalar_new_dbg (unsigned int size, int type, const char *file, int line);
-    static void* __cdecl _crtd_calloc (size_t num, size_t size);
-    static void* __cdecl _crtd_malloc (size_t size);
-    static void* __cdecl _crtd_realloc (void *mem, size_t size);
-    static void* __cdecl _crtd_scalar_new (unsigned int size);
-    static FARPROC __stdcall _GetProcAddress(HMODULE module, LPCSTR procname);
-    static HANDLE __stdcall _HeapCreate (DWORD options, SIZE_T initsize, SIZE_T maxsize);
-    static BOOL __stdcall _HeapDestroy (HANDLE heap);
-    static NTSTATUS __stdcall _LdrLoadDll (LPWSTR searchpath, PDWORD flags, unicodestring_t *modulename,
-                                           PHANDLE modulehandle);
-    static void* __cdecl _mfc42d__scalar_new_dbg (unsigned int size, const char *file, int line);
-    static void* __cdecl _mfc42d_scalar_new (unsigned int size);
-    static void* __cdecl _mfc80d__scalar_new_dbg (unsigned int size, const char *file, int line);
-    static void* __cdecl _mfc80d__vector_new_dbg (unsigned int size, const char *file, int line);
-    static void* __cdecl _mfc80d_scalar_new (unsigned int size);
-    static void* __cdecl _mfc80d_vector_new (unsigned int size);
-    static LPVOID __stdcall _RtlAllocateHeap (HANDLE heap, DWORD flags, SIZE_T size);
-    static BOOL __stdcall _RtlFreeHeap (HANDLE heap, DWORD flags, LPVOID mem);
-    static LPVOID __stdcall _RtlReAllocateHeap (HANDLE heap, DWORD flags, LPVOID mem, SIZE_T size);
-
-    // Private functions - see each function definition for details.
-    static BOOL __stdcall addloadedmodule (PCWSTR modulepath, DWORD64 modulebase, ULONG modulesize, PVOID context);
-    VOID attachtoloadedmodules (ModuleSet *newmodules);
+////////////////////////////////////////////////////////////////////////////////
+// Private leak detection functions - see each function definition for details.
+////////////////////////////////////////////////////////////////////////////////
+    VOID   attachtoloadedmodules (ModuleSet *newmodules);
     LPWSTR buildsymbolsearchpath ();
-    VOID configure ();
-    static BOOL __stdcall detachfrommodule (PCWSTR modulepath, DWORD64 modulebase, ULONG modulesize, PVOID context);
-    BOOL enabled ();
+    VOID   configure ();
+    BOOL   enabled ();
     SIZE_T eraseduplicates (const BlockMap::Iterator &element);
     tls_t* gettls ();
-    VOID mapblock (HANDLE heap, LPCVOID mem, SIZE_T size, SIZE_T framepointer, BOOL crtalloc);
-    VOID mapheap (HANDLE heap);
-    VOID remapblock (HANDLE heap, LPCVOID mem, LPCVOID newmem, SIZE_T size, SIZE_T framepointer, BOOL crtalloc);
-    VOID reportconfig ();
-    VOID reportleaks (HANDLE heap);
-    VOID unmapblock (HANDLE heap, LPCVOID mem);
-    VOID unmapheap (HANDLE heap);
+    VOID   mapblock (HANDLE heap, LPCVOID mem, SIZE_T size, SIZE_T framepointer, BOOL crtalloc);
+    VOID   mapheap (HANDLE heap);
+    VOID   remapblock (HANDLE heap, LPCVOID mem, LPCVOID newmem, SIZE_T size, SIZE_T framepointer, BOOL crtalloc);
+    VOID   reportconfig ();
+    VOID   reportleaks (HANDLE heap);
+    VOID   unmapblock (HANDLE heap, LPCVOID mem);
+    VOID   unmapheap (HANDLE heap);
+
+    // Static functions (callbacks)
+    static BOOL __stdcall addloadedmodule (PCWSTR modulepath, DWORD64 modulebase, ULONG modulesize, PVOID context);
+    static BOOL __stdcall detachfrommodule (PCWSTR modulepath, DWORD64 modulebase, ULONG modulesize, PVOID context);
+
+////////////////////////////////////////////////////////////////////////////////
+// IAT replacement functions - see each function definition for details.
+//
+// Because there are so many virtually identical CRT and MFC replacement
+// functions, they are excluded from the class to reduce the amount of noise
+// within this class's code. See crtmfcpatch.cpp for those functions.
+////////////////////////////////////////////////////////////////////////////////
+    // Win32 IAT replacement functions
+    static FARPROC  __stdcall _GetProcAddress (HMODULE module, LPCSTR procname);
+    static HANDLE   __stdcall _HeapCreate (DWORD options, SIZE_T initsize, SIZE_T maxsize);
+    static BOOL     __stdcall _HeapDestroy (HANDLE heap);
+    static NTSTATUS __stdcall _LdrLoadDll (LPWSTR searchpath, PDWORD flags, unicodestring_t *modulename,
+                                           PHANDLE modulehandle);
+    static LPVOID   __stdcall _RtlAllocateHeap (HANDLE heap, DWORD flags, SIZE_T size);
+    static BOOL     __stdcall _RtlFreeHeap (HANDLE heap, DWORD flags, LPVOID mem);
+    static LPVOID   __stdcall _RtlReAllocateHeap (HANDLE heap, DWORD flags, LPVOID mem, SIZE_T size);
 
-    // Private data.
+    // COM IAT replacement functions
+    static HRESULT __stdcall _CoGetMalloc (DWORD context, LPMALLOC *imalloc);
+    static LPVOID  __stdcall _CoTaskMemAlloc (ULONG size);
+    static LPVOID  __stdcall _CoTaskMemRealloc (LPVOID mem, ULONG size);
+
+////////////////////////////////////////////////////////////////////////////////
+// Private data
+////////////////////////////////////////////////////////////////////////////////
     WCHAR                m_forcedmodulelist [MAXMODULELISTLENGTH]; // List of modules to be forcefully included in leak detection.
     HeapMap             *m_heapmap;           // Map of all active heaps in the process.
     IMalloc             *m_imalloc;           // Pointer to the system implementation of IMalloc.
@@ -258,6 +287,6 @@ private:
 };
 
 // Configuration option default values
-#define VLD_DEFAULT_MAX_DATA_DUMP    0xffffffff
-#define VLD_DEFAULT_MAX_TRACE_FRAMES 0xffffffff
+#define VLD_DEFAULT_MAX_DATA_DUMP    256
+#define VLD_DEFAULT_MAX_TRACE_FRAMES 64
 #define VLD_DEFAULT_REPORT_FILE_NAME L".\\memory_leak_report.txt"
index 2c95d2de47975681578dac041785bba8b03faf4c..0b8b77172a0bb8e73d24115d802121a177dd42cc 100644 (file)
@@ -22,6 +22,8 @@
 #//
 #////////////////////////////////////////////////////////////////////////////////
 
+cmake_minimum_required(VERSION 2.6.4)
+
 project(vld)
 
 include(CheckCXXSourceCompiles)
@@ -44,10 +46,14 @@ if (NOT HAVE_DEBUGGING_TOOLS_FOR_WINDOWS)
        message(FATAL_ERROR "")
 endif (NOT HAVE_DEBUGGING_TOOLS_FOR_WINDOWS)
 
+set(vld_path ${CMAKE_CURRENT_SOURCE_DIR}/../..)
+
 file(GLOB vld_sources ${vld_path}/src/*.cpp)
 file(GLOB vld_headers ${vld_path}/src/*.h)
 
 add_definitions(-DVLD_BUILD -DUNICODE -D_UNICODE)
 
-add_library(vld SHARED ${vld_sources} ${vld_headers} ${vld_path}/include/vld.h)
+
+add_library(vld SHARED ${vld_sources} ${vld_headers})
+
   
index d1e94bbc8d09eb4131cd24842be17157451b9adf..bc611bcc4d5041debeeefd4c1e4e225f845df7ec 100644 (file)
@@ -23,9 +23,5 @@
 #////////////////////////////////////////////////////////////////////////////////
 
 # This triggers the useage of vld in all other projects
-include_directories(${vld_path}/include)
-set(CMAKE_C_FLAGS_DEBUG   "${CMAKE_C_FLAGS_DEBUG}   /FIvld.h")
-set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /FIvld.h")
-set(vld_dll vld)
-
-add_subdirectory(${vld_path}/tools/cmake ${CMAKE_BINARY_DIR}/vld)
+set(CMAKE_C_FLAGS_DEBUG   "${CMAKE_C_FLAGS_DEBUG}   /FI${vld_path}/src/vld.h")
+set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /FI${vld_path}/src/vld.h")
index bb4c6a9253f1690d64011e4ab219dbbeb7b959c9..701ee0923020e7f595cff1e7436eec111ac6dc41 100644 (file)
@@ -1,5 +1,4 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;  $Id: vld.ini,v 1.7 2006/11/18 03:12:35 dmouldin Exp $
 ;;
 ;;  Visual Leak Detector - Initialization/Configuration File
 ;;  Copyright (c) 2006 Dan Moulding