]> git.lyx.org Git - features.git/commitdiff
add leak tool for msvc 'Visual Leak Detection' 1.9f: original files
authorPeter Kümmel <syntheticpp@gmx.net>
Sun, 2 Dec 2007 11:05:21 +0000 (11:05 +0000)
committerPeter Kümmel <syntheticpp@gmx.net>
Sun, 2 Dec 2007 11:05:21 +0000 (11:05 +0000)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@21911 a592a061-630c-0410-9148-cb99ea01b6c8

19 files changed:
development/Win32/vld/CHANGES.txt [new file with mode: 0644]
development/Win32/vld/COPYING.txt [new file with mode: 0644]
development/Win32/vld/README.html [new file with mode: 0644]
development/Win32/vld/include/vld.h [new file with mode: 0644]
development/Win32/vld/src/callstack.cpp [new file with mode: 0644]
development/Win32/vld/src/callstack.h [new file with mode: 0644]
development/Win32/vld/src/map.h [new file with mode: 0644]
development/Win32/vld/src/ntapi.cpp [new file with mode: 0644]
development/Win32/vld/src/ntapi.h [new file with mode: 0644]
development/Win32/vld/src/set.h [new file with mode: 0644]
development/Win32/vld/src/tree.h [new file with mode: 0644]
development/Win32/vld/src/utility.cpp [new file with mode: 0644]
development/Win32/vld/src/utility.h [new file with mode: 0644]
development/Win32/vld/src/vld.cpp [new file with mode: 0644]
development/Win32/vld/src/vldapi.cpp [new file with mode: 0644]
development/Win32/vld/src/vldheap.cpp [new file with mode: 0644]
development/Win32/vld/src/vldheap.h [new file with mode: 0644]
development/Win32/vld/src/vldint.h [new file with mode: 0644]
development/Win32/vld/vld.ini [new file with mode: 0644]

diff --git a/development/Win32/vld/CHANGES.txt b/development/Win32/vld/CHANGES.txt
new file mode 100644 (file)
index 0000000..1c6f100
--- /dev/null
@@ -0,0 +1,344 @@
+Visual Leak Detector (VLD) Version 1.9f (beta)
+
+  Change Log / Release Notes
+  
+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.
+    
+  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)
+----------------------------
+  New Features/Enhancements:
+  + Added a master on/off switch configuration option to vld.ini that can be
+    used to completely disable Visual Leak Detector.
+    
+  Bugs Fixed:
+  + 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.
+    
+  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
+    when it is written too quickly.
+  
+  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:
+  + Source compiles under Visual Studio 2005 and the binaries are compatible
+    with applications that link with the Visual Studio 2005 C Runtime Library
+    (msvcr80d.dll).
+
+  Known Restrictions in this Release:
+  + 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, MFC 7.1, or MFC 8.0 is not complete
+    yet. Some memory leaks from such MFC-based programs may not be detected. A
+    workaround for this restriction is to forcefully include the MFC DLLs in
+    memory leak detection, by setting the "ForceIncludeModules" configuration
+    option to: "mfc70d.dll mfc71d.dll mfc80d.dll" and explicitly adding vld.lib
+    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, which is fully
+    supported.
+
+1.9a beta (9 March 2006)
+------------------------
+  New Features/Enhancments:
+  + All new leak detection engine detects most, if not all, in-process memory
+    leaks, not just leaks from "new" or "malloc", including COM-based leaks.
+
+  + Packaged as an easier-to-use DLL. There's no longer any need to carefully
+    decide which modules should be linked with the VLD library. Instead, you
+    just include the vld.h header file in at least one source file from each
+    module (DLL or EXE) to be included in memory leak detection.
+
+  + Configuration is done from an INI file instead of using preprocessor macros.
+    This allows VLD's configuration to be changed without needing to recompile
+    the program.
+
+  + Many new configuration options have been added. One of the most often
+    requested option that has been added is the option to save the leak report
+    to a file instead of, or in addition to, the debugger.
+
+  Bugs Fixed:
+  + The improved design of the new leak detection engine has resolved all of the
+    previously known restrictions in version 1.0.
+
+  Known Restrictions in this Release:
+  + 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, MFC 7.1, or MFC 8.0 is not complete
+    yet. Some memory leaks from such MFC-based programs may not be detected. A
+    workaround for this restriction is to forcefully include the MFC DLLs in
+    memory leak detection, by setting the "ForceIncludeModules" configuration
+    option to: "mfc70d.dll mfc71d.dll mfc80d.dll" and explicitly adding vld.lib
+    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, which is fully
+    supported.
+
+
+1.0 (5 August 2005)
+-------------------
+  New Features/Enhancements:
+  + Memory leak detection can now be selectively disabled and enabled at
+    runtime, using provided APIs. This provides a straightforward way of
+    allowing VLD to selectively "ignore" certain allocations. It can also be
+    used to disable VLD altogether at runtime, improving application performance
+    without needing to recompile.
+
+  + If there are multiple identical memory leaks (i.e. leaks that originate from
+    the same call stack and that leak the same size memory block) then VLD can
+    optionally aggregate all of the repeated leaks, showing only the first such
+    leaked block in detail in the memory leak report. A tally of the total
+    number of leaks that match that particular size and call stack accompanies
+    the information for that leak.
+
+  + When VLD is initialized at program startup, the library type which was
+    linked-in is displayed. This can help verify that the expected VLD library
+    (either single-threaded static, multithreaded static, or multithreaded DLL)
+    is being linked with your program.
+
+  + The Visual Leak Detector name is displayed on most messages output to the
+    debugger to easily differentiate VLD's output from the output produced by
+    the built-in memory leak detector.
+
+  + If any of the compile-time configuration options have been changed from
+    their default values, then the current state of the option is displayed in
+    the debugger when VLD is initialized.
+
+  + VLD's memory leak self-checking capability (checking for leaks in VLD
+    itself) can be verified using a new preprocessor macro that allows VLD to
+    perform a self-test at runtime.
+
+  Bugs Fixed:
+  + If the MFC libraries are statically linked to the program being debugged,
+    then MFC will erroneously report memory leaks in the Visual Leak Detector
+    code and may cause an access violation while attempting to report the false
+    memory leaks. These bogus leaks are always reported as "client block at
+    <address>, subtype bf42" and are claimed to be "invalid objects".
+
+  + VLD will leak a fixed-sized block of memory when the program exits if VLD
+    failed to initialize because the Debug Help library (dbghelp.dll) could not
+    be loaded.
+
+  + In multithreaded programs, if the program's main thread terminates before
+    other threads in the same process, then VLD may cause an access violation
+    while freeing resources used internally by VLD.
+
+
+0.9i beta (30 April 2005)
+-------------------------
+  New Features/Enhancements:
+  + Added support in the source code for x64 architecture. The pre-built
+    libraries will continue to support 32-bit only. If you need 64-bit support
+    you'll need to build 64-bit versions of the libraries from source. Note that
+    x64 is the only 64-bit architecture supported at this time. Itanium (aka
+    IA-64) is NOT currently supported.
+
+  Bugs Fixed:
+  + VLD does not report memory leaks that are the result of a failure to free
+    memory allocated via a call to realloc().
+  + In multithreaded programs, if the program's main thread terminates before
+    other threads in the same process, then VLD may cause an access violation
+    while checking for memory leaks.
+  + If VLD cannot find the source file and line number information for a program
+    address, the last known file and line number will be repeated in the call
+    stack section of the memory leak report. The correct behavior should be for
+    VLD to print "File and line number not available" for that call stack entry.
+
+
+0.9h beta (22 April 2005)
+-------------------------
+  Bugs Fixed:
+  + Access Violations occur at random places within the VLD code when using
+    VLD version 0.9g.
+  + When using VLD version 0.9g, VLD may fail to report some memory leaks.
+
+
+0.9g beta (22 April 2005)
+-------------------------
+  New Features/Enhancements:
+  + Replaced the temporary internal search algorithm with a permanent search
+    algorithm that is much faster. Programs that dynamically allocate a large
+    number of memory blocks (tens of thousands or more) will see the most
+    significant performance boost from this version of VLD versus the previous
+    version. Overall, this is the fastest version of VLD released to date.
+
+
+0.9f beta (13 April 2005)
+-------------------------
+  New Features/Enhancements:
+  + Changed the internal search algorithm to a temporary simpler, but
+    more stable algorithm. A permanent algorithm which should be much
+    more efficient will be in a forthcoming release.
+
+  Bugs Fixed:
+  + Access Violation at line 319 in vldutil.cpp may occur when running a
+    program linked with the VLD library.
+
+
+0.9e beta (12 April 2005)
+-------------------------
+  New Features/Enhancements:
+  + VLD no longer uses any STL containers or STL strings. This solves all of the
+    compatibility problems with Visual Studio .NET when using the pre-built
+    VLD libraries.
+
+  + The configuration preprocessor macros now work with C programs without the
+    need to call VLDConfigure from within the program being debugged.
+    Because VLDConfigure is now obsolete, it has been removed.
+
+  + One new source file (vldutil.cpp) and one new header (vldutil.h) have been
+    added. They contain utility functions and utility classes that replace
+    functionality previously performed by STL containers and strings.
+
+  + The VisualLeakDetector global class object is now constructed at C runtime
+    initialization (i.e. it resides in the "compiler" initialization area).
+    Because VLD no longer uses any STL components, there is no longer the risk
+    that VLD will conflict with any STL libraries that also are constructed at
+    C runtime initialization. The end result is that VLD starts running earlier
+    and is destroyed later, which leads to more accurate leak detection.
+
+  Bugs Fixed:
+  + Linking to the VLD 0.9d libraries from the VLD distribution under Visual
+    Studio .NET results in a number of linker "unresolved external symbol"
+    errors. Unresolved symbols include "__declspec(dllimport) void __cdecl
+    std::_Xran(void)" and "__declspec(dllimport) private: void __thiscall
+    std::basic_string,class std::allocator >::_Eos(unsigned int)", among others.
+
+  + Call stacks do not appear in the memory leak report when linking against
+    release VLD libraries built from source with Visual Studio .NET.
+
+  + If the preprocessor macro VLD_MAX_DATA_DUMP is defined as 0 (zero), then VLD
+    will get stuck in an infinite loop, repeatedly printing the same information
+    while attempting to display the memory leak report in the debugger's output
+    window.
+
+
+0.9d beta (30 March 2005)
+-------------------------
+  New Features/Enhancements:
+  + This version of VLD brings with it some major changes to the way VLD
+    interfaces with programs that use it. Instead of requiring that VLD be built
+    from source and then linked with the application, VLD is now packaged as a
+    pre-built static library. For those who just want to use VLD and are not
+    interested in modifying the source, this eliminates the complexities of
+    building VLD from source. A single header file, vld.h, has been added. To
+    link with the static library, this header needs to be included in one of the
+    program's source files. Please see the README.txt file for details on how
+    these changes affect how to use Visual Leak Detector.
+
+  + The Microsoft Debug Help Library (dbghelp.dll) version 6.3 is now included
+    with the VLD distribution.
+
+
+0.9c beta (17 March 2005)
+-------------------------
+  Bugs Fixed:
+  + Compile error, "error C2039: 'size' : is not a member of '_CrtMemBlockHeader'"
+    occurs at line 644 of vld.cpp when building VLD with the VLD_MAX_DATA_DUMP
+    preprocessor macro defined.
+
+
+0.9b beta (15 March 2005)
+-------------------------
+  Bugs Fixed:
+  + VLD fails to detect memory leaks in class constructors if the objects
+    constructed are global objects.
+
+  + If a debug executable is built with certain compiler optimizations turned on,
+    specifically frame pointer omission optimization or automatic inlining, then
+    theoretically VLD may produce incomplete or inaccurate stack traces or might
+    fail to produce stack traces altogether.
+
+
+0.9a beta (12 March 2005)
+-------------------------
+  Initial Public Release
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/development/Win32/vld/COPYING.txt b/development/Win32/vld/COPYING.txt
new file mode 100644 (file)
index 0000000..073dd57
--- /dev/null
@@ -0,0 +1,458 @@
+                 GNU LESSER GENERAL PUBLIC LICENSE
+                      Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+                 GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+\f
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                           NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
\ No newline at end of file
diff --git a/development/Win32/vld/README.html b/development/Win32/vld/README.html
new file mode 100644 (file)
index 0000000..7182f55
--- /dev/null
@@ -0,0 +1,747 @@
+<?xml version="1.0" encoding="iso-8859-1"?>\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr">\r
+\r
+<head>\r
+    <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />\r
+\r
+    <style title="Visual Leak Detector" type="text/css" media="screen,print">\r
+        body {\r
+            margin: 0;\r
+            font-family: verdana, sans-serif;\r
+        }\r
+\r
+        #masthead {\r
+            border-width: 0 0 1px 0;\r
+            border-style: solid;\r
+            border-color: #808080;\r
+            color: #ffffff;\r
+            background-color: #3569cc;\r
+        }\r
+\r
+        #content {\r
+            margin: 1em 1em 1em 1em;\r
+            font-size: 10pt;\r
+        }\r
+\r
+        #toc {\r
+            float: right;\r
+            color: #000000;\r
+            background-color: #ffeda5;\r
+        }\r
+\r
+        h1 {\r
+            margin: 0 0 0 0;\r
+            padding: 0.5em 1em 0 1em;\r
+            text-align: right;\r
+            font-size: 24pt;\r
+            font-family: arial, sans-serif;\r
+        }\r
+\r
+        h2 {\r
+            margin-top: 0;\r
+            border-width: 2px;\r
+            border-style: solid;\r
+            border-color: #3569cc;\r
+            padding-left: 1em;\r
+            font-size: 16pt;\r
+            font-family: "trebuchet ms", sans-serif;\r
+            letter-spacing: -1pt;\r
+            color: #000000;\r
+            background-color: #6599fc;\r
+        }\r
+\r
+        h3 {\r
+            font-size: 11pt;\r
+        }\r
+\r
+        li {\r
+            margin-bottom: 1em;\r
+        }\r
+\r
+        #toc h2 {\r
+            margin: 0;\r
+            border-width: 2px 2px 2px 0;\r
+            border-style: solid;\r
+            border-color: #6599fc;\r
+            text-align: center;\r
+            color: #ffffff;\r
+            background-color: #3569cc;\r
+        }\r
+\r
+        #toc ul {\r
+            margin-left: 0;\r
+            padding: 0;\r
+            list-style: none;\r
+        }\r
+\r
+        #toc li {\r
+            margin: 1em;\r
+        }\r
+\r
+        a {\r
+            color: #0000ff;\r
+            background-color: inherit;\r
+            text-decoration:none;\r
+        }\r
+\r
+        a:hover {\r
+            text-decoration: underline;\r
+        }\r
+\r
+        a:visited {\r
+            color: #0000ff;\r
+            background-color: inherit;\r
+        }\r
+\r
+        .api {\r
+            font-size: 12pt;\r
+            font-weight: bold;\r
+        }\r
+\r
+        .code {\r
+            font-family: "courier new", monospace;\r
+            color: #000000;\r
+            background-color: #e0e0e0;\r
+        }\r
+\r
+        .filename {\r
+            font-style: italic;\r
+        }\r
+\r
+        .function {\r
+            font-style: italic;\r
+        }\r
+\r
+        .note {\r
+            margin-left: 2em;\r
+        }\r
+\r
+        .operator {\r
+            font-style: italic;\r
+        }\r
+\r
+        .option {\r
+            font-size: 10pt;\r
+            font-weight: bold;\r
+        }\r
+\r
+        ul.vcsearchpath {\r
+            border-width: 1px;\r
+            border-style: dashed;\r
+            border-color: #000000;\r
+            color: #000000;\r
+            background-color: #ffeda5;\r
+            list-style: none;\r
+        }\r
+\r
+        ul.vcsearchpath li {\r
+            margin-bottom: 0;\r
+        }\r
+\r
+        #slogan {\r
+            margin-bottom: 0;\r
+            padding: 0 1em 1em 1em;\r
+            border-width: 0 0 1px 0;\r
+            border-style: solid;\r
+            border-color: #404040;\r
+            text-align: right;\r
+            font-size: larger;\r
+            font-style: italic;\r
+            color: #6599fc;\r
+            background-color: inherit;\r
+        }\r
+\r
+        #copyright {\r
+            text-align: right;\r
+            font-family: georgia, serif;\r
+            color: #808080;\r
+            background-color: inherit;\r
+        }\r
+\r
+        #compliance {\r
+            text-align: right;\r
+        }\r
+\r
+        #compliance img {\r
+            border: 0;\r
+        }\r
+        \r
+        blockquote {\r
+            font-style: italic;\r
+        }\r
+    </style>\r
+\r
+    <title>Visual Leak Detector (Beta)</title>\r
+\r
+</head>\r
+\r
+\r
+\r
+\r
+<body>\r
+\r
+<div id="masthead">\r
+\r
+<h1>Visual&nbsp;Leak&nbsp;Detector&nbsp;1.9f (Beta)</h1>\r
+\r
+<p id="slogan">Enhanced Memory Leak Detection for Visual&nbsp;C++</p>\r
+\r
+</div> <!-- #masthead -->\r
+\r
+\r
+\r
+\r
+<div id="content">\r
+\r
+<div id="toc">\r
+\r
+<h2>Table of Contents</h2>\r
+\r
+<ul>\r
+    <li><a href="#intro">Introduction</a></li>\r
+\r
+    <li><a href="#use">Using Visual&nbsp;Leak&nbsp;Detector</a></li>\r
+\r
+    <li><a href="#configure">Configuration Options</a></li>\r
+\r
+    <li><a href="#control">Controlling Leak Detection at Runtime</a></li>\r
+\r
+    <li><a href="#build">Building Visual&nbsp;Leak&nbsp;Detector from Source</a></li>\r
+\r
+    <li><a href="#x64">Windows x64 Support</a></li>\r
+\r
+    <li><a href="#faq">Frequently Asked Questions</a></li>\r
+\r
+    <li><a href="#restrictions">Known Restrictions</a></li>\r
+\r
+    <li><a href="#license">License</a></li>\r
+\r
+    <li><a href="#contact">Contacting the Author</a></li>\r
+</ul>\r
+\r
+</div> <!-- #toc -->\r
+\r
+\r
+\r
+\r
+<h2 id="intro">Introduction</h2>\r
+\r
+<p>Visual&nbsp;C++ provides built-in memory leak detection, but its capabilities are minimal at best. This memory leak\r
+   detector was created as a free alternative to the built-in memory leak detector provided with Visual&nbsp;C++. Here\r
+   are some of Visual&nbsp;Leak&nbsp;Detector's features, none of which exist in the built-in detector:</p>\r
+\r
+<ul>\r
+    <li>Provides a complete stack trace for each leaked block, including source file and line number information when\r
+        available.</li>\r
+\r
+    <li>Detects most, if not all, types of in-process memory leaks including COM-based leaks, and pure Win32 heap-based\r
+    leaks.</li>\r
+\r
+    <li>Selected modules (DLLs or even the main EXE) can be excluded from leak detection.</li>\r
+\r
+    <li>Provides complete data dumps (in hex and ASCII) of leaked blocks.</li>\r
+\r
+    <li>Customizable memory leak report: can be saved to a file or sent to the debugger and can include a variable level\r
+    of detail.</li>\r
+</ul>\r
+\r
+<p>Other after-market leak detectors for Visual&nbsp;C++ are already available. But most of the really popular ones,\r
+   like Purify and BoundsChecker, are very expensive. A few free alternatives exist, but they're often too intrusive,\r
+   restrictive, or unreliable. Visual&nbsp;Leak&nbsp;Detector is currently the only freely available memory leak\r
+   detector for Visual C++ that provides all of the above professional-level features packaged neatly in an easy-to-use\r
+   library.</p>\r
+\r
+<p>Visual Leak Detector is <a href="#license">licensed</a> free of charge as a service to the Windows developer\r
+   community. If you find it to be useful and would like to just say "Thanks!", or you think it stinks and would like to\r
+   say "This thing sucks!", please feel free to <a href="mailto:dmoulding@gmail.com">drop me a note</a>. Or, if you'd\r
+   prefer, you can <a href="#contact">contribute a small donation</a>. Both are very appreciated.</p>\r
+\r
+\r
+\r
+\r
+<h2 id="use">Using Visual&nbsp;Leak&nbsp;Detector</h2>\r
+\r
+<p>This section briefly describes the basics of using Visual&nbsp;Leak&nbsp;Detector (VLD).</p>\r
+\r
+<p><strong>Important! :</strong> Before using VLD with any Visual C++ project, you must first add the Visual Leak\r
+   Detector include and library directories to the Visual C++ include and library directory search paths:</p>\r
+\r
+<ul>\r
+    <li><strong>Visual&nbsp;C++ 8</strong>: Go to Tools -> Options -> Projects and Solutions -> VC++ Directories.\r
+        Select "Include files" from the "Show Directories For" drop-down menu. Add the\r
+        <span class="filename">include</span> subdirectory from the Visual Leak Detector installation directory. Move it\r
+        to the bottom of the list. Then select "Library files" from the drop-down menu and add the\r
+        <span class="filename">lib</span> subdirectory from the Visual Leak Detector installation directory. Again, move\r
+        it to the bottom of the list.</li>\r
+        \r
+    <li><strong>Visual&nbsp;C++ 7</strong>: Go to Project Properties -> C/C++ -> General -> Additional Include\r
+        Directories and add the <span class="filename">include</span> subdirectory from the Visual Leak Detector\r
+        installation directory. Move it to the bottom of the list. Then select Additional Library Directories and add\r
+        the <span class="filename">lib</span> subdirectory from the Visual Leak Detector installation directory. Again,\r
+        move it to the bottom of the list.</li>\r
+\r
+    <li><strong>Visual&nbsp;C++ 6</strong>: Go to Tools -> Options -> Directories. Select "Include files" from\r
+        the "Show Directories For" drop-down menu. Add the <span class="filename">include</span> subdirectory\r
+        from the Visual Leak Detector installation directory. Move it to the bottom of the list. Then select "Library\r
+        files" from the drop-down menu and add the <span class="filename">lib</span> subdirectory from the Visual Leak\r
+        Detector installation directory. Again, move it to the bottom of the list.</li>\r
+</ul>\r
+        \r
+<p>To use VLD with your project, follow these simple steps:</p>\r
+\r
+<ol>\r
+    <li>In at least one C/C++ source file from your program, include the <span class="filename">vld.h</span> header\r
+        file. It should not matter which file you add the include statement to. It also should not matter in what order\r
+        the header is included in relation to other headers. The only exception is\r
+        <span class="filename">stdafx.h</span> (or any other precompiled header). A precompiled header, such as\r
+        <span class="filename">stdafx.h</span>, must always be the first header included in a source file, so\r
+        <span class="filename">vld.h</span> must be included after any precompiled headers.</li>\r
+\r
+    <li>If your program contains one or more DLLs that you would also like to check for memory leaks, then also include\r
+        <span class="filename">vld.h</span> in at least one source file from each DLL to be included in leak\r
+        detection.</li>\r
+\r
+    <li>Build the debug version of your program.</li>\r
+</ol>\r
+\r
+<p class="note"><strong>Note:</strong> Unlike earlier (pre-1.9) versions of VLD, it is now acceptable to include\r
+   <span class="filename">vld.h</span> in every source file, or to include it in a common header that is included by\r
+   many or all source files. Only one copy of the VLD code will be loaded into the process, regardless of how many\r
+   source files include <span class="filename">vld.h</span>.</p>\r
+\r
+<p>VLD will detect memory leaks in your program whenever you run the debug version. When you run the program under the\r
+   Visual&nbsp;C++ debugger, a report of all the memory leaks detected will be displayed in the debugger's output window\r
+   when your program exits (the report can optionally be saved to a file instead, see\r
+   <span class="option">ReportFile</span> under <a href="#configure">Configuration Options</a>). Double-clicking on a\r
+   source file's line number in the memory leak report will take you to that file and line in the editor window,\r
+   allowing easy navigation of the code path leading up to the allocation that resulted in the memory leak.</p>\r
+\r
+<p class="note"><strong>Note:</strong> When you build release versions of your program, VLD will not be linked into the\r
+   executable. So it is safe to leave <span class="filename">vld.h</span> included in your source files when doing\r
+   release builds. Doing so will not result in any performance degradation or any other undesirable overhead.</p>\r
+\r
+\r
+\r
+\r
+<h2 id="configure">Configuration Options</h2>\r
+\r
+<p>There are a several configuration options that control specific aspects of VLD's operation. These configuration\r
+   options are stored in the <span class="filename">vld.ini</span> configuration file. By default, the configuration\r
+   file should be in the Visual Leak Detector installation directory. However, the configuration file can be copied to\r
+   the program's working directory, in which case the configuration settings in that copy of\r
+   <span class="filename">vld.ini</span> will apply only when debugging that one program.</p>\r
+\r
+<dl>\r
+    <dt class="option">VLD</dt>\r
+    <dd>\r
+        <p>This option acts as a master on/off switch. By default, this option is set to "on". To <em>completely\r
+        disable</em> Visual Leak Detector at runtime, set this option to "off". When VLD is turned off using this\r
+        option, it will do nothing but print a message to the debugger indicating that it has been turned off.</p>\r
+    </dd>\r
+    \r
+    <dt class="option">AggregateDuplicates</dt>\r
+    <dd>\r
+        <p>Normally, VLD displays each individual leaked block in detail. Setting this option to "yes" will make VLD\r
+           aggregate all leaks that share the same size and call stack under a single entry in the memory leak report.\r
+           Only the first leaked block will be reported in detail. No other identical leaks will be displayed. Instead,\r
+           a tally showing the total number of leaks matching that size and call stack will be shown. This can be useful\r
+           if there are only a few sources of leaks, but those few sources are repeatedly leaking a very large number of\r
+           memory blocks.</p>\r
+    </dd>\r
+\r
+    <dt class="option">ForceIncludeModules</dt>\r
+    <dd>\r
+        <p>In some rare cases, it may be necessary to include a module in leak detection, but it may not be possible to\r
+           include <span class="filename">vld.h</span> in any of the module's sources. In such cases, this option can be\r
+           used to force VLD to include those modules in leak detection. List the names of the modules (DLLs) to be\r
+           forcefully included in leak detection. If you do use this option, it's advisable to also add\r
+           <span class="filename">vld.lib</span> to the list of library modules in the linker options of your project's\r
+           settings.</p>\r
+\r
+        <p class="note"><strong>Caution:</strong> Use this option only when absolutely necessary. In some situations,\r
+           use of this option may result in unpredictable behavior including false leak reports and/or crashes. It's\r
+           best to stay away from this option unless you are sure you understand what you are doing.</p>\r
+    </dd>\r
+\r
+    <dt class="option">MaxDataDump</dt>\r
+    <dd>\r
+        <p>Set this option to an integer value to limit the amount of data displayed in memory block data dumps. When\r
+           this number of bytes of data have been dumped, the dump will stop. This can be useful if any of the leaked\r
+           blocks are very large and the debugger's output window becomes too cluttered. You can set this option to 0\r
+           (zero) if you want to suppress data dumps altogether.</p>\r
+    </dd>\r
+\r
+    <dt class="option">MaxTraceFrames</dt>\r
+    <dd>\r
+        <p>By default, VLD will trace the call stack for each allocated block as far back as possible. Each frame traced\r
+           adds additional overhead (in both CPU time and memory usage) to your debug executable. If you'd like to limit\r
+           this overhead, you can define this macro to an integer value. The stack trace will stop when it has traced\r
+           this number of frames. The frame count may include some of the "internal" frames which, by default, are not\r
+           displayed in the debugger's output window (see <span class="option">TraceInternalFrames</span> below). In\r
+           some cases there may be about three or four "internal" frames at the beginning of the call stack. Keep this\r
+           in mind when using this macro, or you may not see the number of frames you expect.</p>\r
+    </dd>\r
+\r
+    <dt class="option">ReportEncoding</dt>\r
+    <dd>\r
+        <p>When the memory leak report is saved to a file, the report may optionally be Unicode encoded instead of using\r
+           the default ASCII encoding. This might be useful if the data contained in leaked blocks is likely to consist\r
+           of Unicode text. Set this option to "unicode" to generate a Unicode encoded report.</p>\r
+    </dd>\r
+\r
+    <dt class="option">ReportFile</dt>\r
+    <dd>\r
+        <p>Use this option to specify the name and location of the file in which to save the memory leak report when\r
+           using a file as the report destination, as specified by the <span class="option">ReportTo</span> option. If\r
+           no file is specified here, then VLD will save the report in a file named "memory_leak_report.txt" in the\r
+           working directory of the program.</p>\r
+    </dd>\r
+\r
+    <dt class="option">ReportTo</dt>\r
+    <dd>\r
+        <p>The memory leak report may be sent to a file in addition to, or instead of, the debugger. Use this option to\r
+           specify which type of destination to use. Specify one of "debugger" (the default), "file", or "both".</p>\r
+    </dd>\r
+\r
+    <dt class="option">SelfTest</dt>\r
+    <dd>\r
+        <p>VLD has the ability to check itself for memory leaks. This feature is always active. Every time you run VLD,\r
+           in addition to checking your own program for memory leaks, it is also checking itself for leaks. Setting this\r
+           option to "on" forces VLD to intentionally leak a small amount of memory: a 21-character block filled with\r
+           the text "Memory Leak Self-Test". This provides a way to test VLD's ability to check itself for memory leaks\r
+           and verify that this capability is working correctly. This option is usually only useful for debugging VLD\r
+           itself.</p>\r
+    </dd>\r
+    \r
+    <dt class="option">SlowDebuggerDump</dt>\r
+    <dd>\r
+        <p>If enabled, this option causes Visual Leak Detector to write the memory leak report to the debugger's output\r
+           window at a slower than normal rate. This option is specifically designed to work around a known issue with\r
+           some older versions of Visual Studio where some data sent to the output window might be lost if it is sent\r
+           too quickly. If you notice that some information seems to be missing from the memory leak report, try turning\r
+           this on.</p>\r
+    </dd>\r
+\r
+    <dt class="option">StackWalkMethod</dt>\r
+    <dd>\r
+        <p>Selects the method to be used for walking the stack to obtain call stacks for allocated memory blocks. The\r
+           default "fast" method may not always be able to successfully trace completely through all call stacks. In\r
+           such cases, the "safe" method may prove to be more reliable in obtaining the full stack trace. The\r
+           disadvantage with the "safe" method is that it is significantly slower than the "fast" method and will\r
+           probably result in very noticeable performance degradation of the program being debugged. In most cases it\r
+           should be okay to leave this option set to "fast". If you experience problems getting VLD to show call\r
+           stacks, you can try setting this option to "safe".</p>\r
+\r
+        <p>If you do use the "safe" method, and notice a significant performance decrease, you may want to consider\r
+           using the <span class="option">MaxTraceFrames</span> option to limit the number of frames traced to a\r
+           relatively small number. This can reduce the amount of time spent tracing the stack by a very large\r
+           amount.</p>\r
+    </dd>\r
+\r
+    <dt class="option">StartDisabled</dt>\r
+    <dd>\r
+        <p>Set this option to "yes" to disable memory leak detection initially. This can be useful if you need to be\r
+           able to selectively enable memory leak detection from runtime, without needing to rebuild the executable;\r
+           however, this option should be used with caution. Any memory leaks that may occur before memory leak\r
+           detection is enabled at runtime will go undetected. For example, if the constructor of some global variable\r
+           allocates memory before execution reaches a subsequent call to <span class="function">VLDEnable</span>, then\r
+           VLD will not be able to detect if the memory allocated by the global variable is never freed. Refer to the\r
+           following section on <a href="#control">controlling leak detection at runtime</a> for details on using the\r
+           runtime APIs which can be useful in conjunction with this option.</p>\r
+    </dd>\r
+\r
+    <dt class="option">TraceInternalFrames</dt>\r
+    <dd>\r
+        <p>This option determines whether or not all frames of the call stack, including frames internal to the heap,\r
+           are traced. There will always be a number of frames on the call stack which are internal to Visual Leak\r
+           Detector and C/C++ or Win32 heap APIs that aren't generally useful for determining the cause of a leak.\r
+           Normally these frames are skipped during the stack trace, which somewhat reduces the time spent tracing and\r
+           amount of data collected and stored in memory. Including all frames in the stack trace, all the way down into\r
+           VLD's own code can, however, be useful for debugging VLD itself.</p>\r
+    </dd>\r
+</dl>\r
+\r
+\r
+\r
+\r
+<h2 id="control">Controlling Leak Detection at Runtime</h2>\r
+\r
+<p>Using the default configuration, VLD's memory leak detection will be enabled during the entire run of your program.\r
+   In certain scenarios it may be desirable to selectively disable memory leak detection in certain segments of your\r
+   code. VLD provides simple APIs for controlling the state of memory leak detection at runtime. To access these APIs,\r
+   include <span class="filename">vld.h</span> in the source file that needs to use them.</p>\r
+\r
+<dl>\r
+    <dt class="api">VLDDisable</dt>\r
+    <dd>\r
+        <p>This function disables memory leak detection. After calling this function, memory leak detection will remain\r
+           disabled until it is explicitly re-enabled via a call to VLDEnable.</p>\r
+\r
+        <pre class="code">void VLDDisable (void);</pre>\r
+\r
+        <h3>Arguments:</h3>\r
+\r
+        <p>This function accepts no arguments.</p>\r
+\r
+        <h3>Return Value:</h3>\r
+\r
+        <p>None (this function always succeeds).</p>\r
+\r
+        <h3>Notes:</h3>\r
+\r
+        <p>This function controls memory leak detection on a per-thread basis. In other words, calling this function\r
+           disables memory leak detection for only the thread that called the function. Memory leak detection will\r
+           remain enabled for any other threads in the same process. This insulates the programmer from having to\r
+           synchronize multiple threads that disable and enable memory leak detection. However, note also that this\r
+           means that in order to disable memory leak detection process-wide, this function must be called from every\r
+           thread in the process.</p>\r
+    </dd>\r
+\r
+\r
+    <dt class="api">VLDEnable</dt>\r
+    <dd>\r
+        <p>This function enables memory leak detection if it was previously disabled. After calling this function,\r
+           memory leak detection will remain enabled unless it is explicitly disabled again via a call to\r
+           VLDDisable().</p>\r
+\r
+        <pre class="code">void VLDEnable (void);</pre>\r
+\r
+        <h3>Arguments:</h3>\r
+\r
+        <p>This function accepts no arguments.</p>\r
+\r
+        <h3>Return Value:</h3>\r
+\r
+        <p>None (this function always succeeds).</p>\r
+\r
+        <h3>Notes:</h3>\r
+\r
+        <p>This function controls memory leak detection on a per-thread basis. See the remarks for\r
+           <span class="function">VLDDisable</span> regarding multithreading and memory leak detection for details.\r
+           Those same concepts also apply to this function.</p>\r
+    </dd>\r
+</dl>\r
+\r
+\r
+\r
+\r
+<h2 id="build">Building Visual&nbsp;Leak&nbsp;Detector from Source</h2>\r
+\r
+<p>Because Visual&nbsp;Leak&nbsp;Detector is open source, it can be built from source if you want to tweak it to your\r
+   liking. The most difficult part about building VLD from source is getting your build environment correctly set up.\r
+   But if you follow these instructions carefully, the  process should be fairly painless.</p>\r
+\r
+<ol>\r
+    <li>VLD depends on the Debug Help Library. This library is part of\r
+        <a href="http://www.microsoft.com/whdc/devtools/debugging/default.mspx">Debugging Tools for Windows</a> (DTfW).\r
+        Download and install DTfW in order to install the required headers and libraries. I recommend installing version\r
+        6.5 of DTfW. Newer versions may also work, but older versions will probably not work. Be sure to manually select\r
+        to install the SDK files during the DTfW installation or the headers and libraries will not be installed (they\r
+        are not installed with a default installation).</li>\r
+\r
+    <li>Visual&nbsp;C++ will need to be made aware of where it can find the Debug Help Library header and library files.\r
+        Add the <span class="filename">sdk\inc</span> and <span class="filename">sdk\lib</span> subdirectories from the\r
+        DTfW installation directory to the include and library search paths in Visual&nbsp;C++. (See the section above\r
+        on <a href="#use">using Visual Leak Detector</a> on instructions for adding to these search paths).\r
+    </li>\r
+\r
+    <li>VLD also requires a reasonably up-to-date Platform&nbsp;SDK. It is known to work with the latest SDK (as of this\r
+        writing) which is the Windows Server 2003 R2 SDK. It should also work with earlier SDKs, such as the Windows XP\r
+        SP2 SDK or may even work with SDKs as old as the February 2003 SDK. If in doubt,\r
+        <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&amp;displaylang=en">update\r
+        your Platform&nbsp;SDK</a> to the latest version.</li>\r
+\r
+    <li>Again, Visual&nbsp;C++ will need to know where to find the Platform&nbsp;SDK headers and libraries. Add the\r
+        <span class="filename">Include</span> and <span class="filename">Lib</span> subdirectories from the\r
+        Platform&nbsp;SDK installation directory to the Include and Library search paths, respectively. The\r
+        Platform&nbsp;SDK directories should be placed just after the DTfW directories.</li>\r
+</ol>\r
+\r
+<p>To summarize, your Visual&nbsp;C++ include search path should look something like this:</p>\r
+\r
+<ul class="vcsearchpath">\r
+   <li>C:\Program&nbsp;Files\Debugging&nbsp;Tools&nbsp;for&nbsp;Windows\sdk\inc</li>\r
+\r
+   <li>C:\Program&nbsp;Files\Microsoft&nbsp;Platform&nbsp;SDK\Include</li>\r
+\r
+   <li>C:\Program&nbsp;Files\Microsoft&nbsp;Visual&nbsp;Studio\VCx\Include</li>\r
+   \r
+   <li>...</li>\r
+</ul>\r
+\r
+<p>And your Visual&nbsp;C++ library search path should look like this:</p>\r
+\r
+<ul class="vcsearchpath">\r
+   <li>C:\Program&nbsp;Files\Debugging&nbsp;Tools&nbsp;for&nbsp;Windows\sdk\lib</li>\r
+\r
+   <li>C:\Program&nbsp;Files\Microsoft&nbsp;Platform&nbsp;SDK\Lib</li>\r
+\r
+   <li>C:\Program&nbsp;Files\Microsoft&nbsp;Visual&nbsp;Studio\VCx\Lib</li>\r
+   \r
+   <li>...</li>\r
+</ul>\r
+\r
+<p>In the above examples, "VCx" could be "VC", "VC7", or "VC98" (or possibly other values) depending on which version of\r
+   Visual Studio you have installed. Also, the name of your Platform&nbsp;SDK directory will probably be different from\r
+   the example depending on which version of the Platform&nbsp;SDK you have installed.</p>\r
+\r
+<p>Once you have completed all of the above steps, your build environment should be ready. To build VLD, just open the\r
+   <span class="filename">vld.sln</span> solution file and do a full build.</p>\r
+\r
+<p>When actually running the built project, <span class="filename">vld.dll</span> will expect to find the Debug Help\r
+   Library as a private assembly. The private assembly must be located in the same directory as\r
+   <span class="filename">vld.dll</span> (either the <span class="filename">Release</span> or\r
+   <span class="filename">Debug</span> directory by default). Otherwise, when VLD is loaded, an error message will pop\r
+   up indicating that the program failed to initialize, and you will see a message similar to the following in the\r
+   debugger's output window:</p>\r
+   <blockquote><p>LDR: LdrpWalkImportDescriptor() failed to probe C:\Projects\vld\Release\vld.dll for its manifest,\r
+   ntstatus 0xc0150002</p></blockquote>\r
+   \r
+<p>To ensure that <span class="filename">vld.dll</span> finds the required private assembly, you need to copy\r
+   <span class="filename">dbghelp.dll</span> and <span class="filename">Microsoft.DTfW.DHL.manifest</span> to the\r
+   same directory that <span class="filename">vld.dll</span> is in.</p>\r
+\r
+\r
+\r
+\r
+<h2 id="x64">Windows x64 Support</h2>\r
+\r
+<p>The VLD source code has been modified to add support for x64-based 64-bit Windows. However, the binary contained in\r
+   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\r
+   version of VLD from source. To build the 64-bit version, follow the instructions for <a href="#build">building VLD\r
+   from source</a>. So long as it is built using a x64-compatible compiler in 64-bit mode, the resulting DLL will be a\r
+   64-bit binary.</p>\r
+\r
+<p class="note"><strong>Note:</strong> I have not personally tested the 64-bit extensions so they are not absolutely\r
+   guaranteed to work out-of-the-box. There may be a few lingering 64-bit compiler errors that still need to be worked\r
+   out. If you need 64-bit support and run into problems trying to build the source in 64-bit mode, please\r
+   <a href="mailto:dmoulding@gmail.com">let me know</a>. I'll be glad to assist in getting the 64-bit code working\r
+   properly.</p>\r
+\r
+\r
+\r
+\r
+<h2 id="faq">Frequently Asked Questions</h2>\r
+\r
+<dl>\r
+    <dt>When I try to compile my program with VLD, it fails and the compiler gives this error: <strong>Cannot open include file:\r
+    'vld.h': No such file or directory</strong>.</dt>\r
+    <dd>\r
+        <p>The compiler can't find the header file that VLD installed. This probably means that VLD's include\r
+        subdirectory has not been added to the Visual C++ include search path. See the section above about\r
+        <a href="#use">Using Visual Leak Detector</a> for instructions on how to add VLD's directories to the search\r
+        path.</p>\r
+    </dd>\r
+    <dt>In the memory leak report, the callstack contains many lines that say\r
+        <strong>"File and line number unvailable"</strong> or <strong>"Function name unavailable"</strong>.</dt>\r
+    <dd>\r
+        <p>This may mean that VLD couldn't find the symbol database for your program. The symbol database is ususally in\r
+           a file named <span class="filename">[my-program-name].pdb</span>. If this file is not located in the same\r
+           directory as the program itself, then VLD will probably not find it and can't show any file or function\r
+           names.</p>\r
+    </dd>\r
+</dl>\r
+\r
+\r
+\r
+\r
+<h2 id="restrictions">Known Restrictions</h2>\r
+\r
+<p>Known restrictions/limitations in this version of VLD include:</p>\r
+\r
+<ul>\r
+   <li>Memory allocations made through calls to functions loaded from a DLL using delayed loading may not be\r
+       detected.</li> \r
+\r
+   <li>Support for programs that use MFC 7.0 or MFC 7.1 is not complete yet. Some memory leaks from such MFC-based\r
+       programs may not be detected. A possible workaround for this restriction is to try forcefully including the MFC\r
+       DLLs in memory leak detection, by setting the <span class="option">ForceIncludeModules</span> configuration\r
+       option to: "mfc70d.dll mfc71d.dll" and explicitly adding <span class="filename">vld.lib</span> as an input file\r
+       on the linker command line (can be added through project settings by adding it to the list of library modules in\r
+       the linker options). This restriction does not apply to programs that use MFC 4.2 or MFC 8.0 which are both fully\r
+       supported.</li>\r
+       \r
+   <li>Visual Leak Detector may report leaks internal to Visual Leak Detector if the main thread of the process\r
+       terminates while other threads are still running.</li>\r
+       \r
+   <li>On Windows 2000 and earlier operating systems, you may need to manually add the\r
+       <span class="filename">bin\Microsoft.VC80.CRT</span> subdirectory from the Visual Leak Detector installation\r
+       directory to the system PATH environment variable. Also, <span class="filename">dbghelp.dll</span> will probably\r
+       need to be manually copied to the directory where the program being debugged resides. Otherwise the system may\r
+       not find the required DLLs when running VLD.</li>\r
+       \r
+    <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\r
+        go undetected (note that loading more than one copy of the C Runtime DLL at the same time is probably a bad idea\r
+        to begin with).</li>\r
+</ul>\r
+\r
+\r
+\r
+\r
+<h2 id="license">License</h2>\r
+\r
+<p>Visual&nbsp;Leak&nbsp;Detector is distributed under the terms of the\r
+   <a href="http://www.gnu.org/copyleft/lesser.html">GNU Lesser General Public License</a>. This license allows you to\r
+   use the VLD library with your own programs without restriction. However, if you build a program (or another library)\r
+   that is <em>based</em> on the VLD source code, or uses parts of the VLD source code in it, then some restrictions\r
+   will apply. What this means is that you are free to ship and use the distributed version of the VLD DLL with regular\r
+   commercial programs. But if you create a modified version of VLD, that modified version must remain "free software".\r
+   See the <span class="filename"><a href="COPYING.txt">COPYING.txt</a></span> file for details.</p>\r
+\r
+<p>The Debug Help Library (<span class="filename">dbghelp.dll</span>) and Microsoft C Runtime Library\r
+   (<span class="filename">msvcr80.dll</span>) distributed with this software are not part of\r
+   Visual&nbsp;Leak&nbsp;Detector and are not covered under the terms of the GNU Lesser General Public License. They are\r
+   separately copyrighted works of Microsoft Corporation. Microsoft reserves all its rights to its copyrights in the\r
+   Debug Help Library and Microsoft C Runtime Library. Neither your use of the Visual&nbsp;Leak&nbsp;Detector software,\r
+   nor your license under the GNU Lesser General Public license grant you any rights to use the Debug Help Library or\r
+   Microsoft C Runtime Library in <strong>ANY WAY</strong> (for example, redistributing them) that would infringe upon\r
+   Microsoft Corporation's copyright in the Debug Help Library or Microsoft C Runtime Library.</p>\r
+\r
+<h3>NO WARRANTY</h3>\r
+\r
+<p>BECAUSE VISUAL LEAK DETECTOR ("THE SOFTWARE") IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO\r
+   THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER\r
+   PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT\r
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE\r
+   QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL\r
+   NECESSARY SERVICING, REPAIR OR CORRECTION.</p>\r
+\r
+<p>IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY\r
+   WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE LICENSING TERMS SET FORTH ABOVE, BE LIABLE TO YOU\r
+   FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY\r
+   TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED\r
+   BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR\r
+   OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</p>\r
+\r
+\r
+\r
+\r
+<h2 id="contact">Contacting the Author</h2>\r
+\r
+<p>Please forward any bug reports, questions, comments or suggestions to me at\r
+<a href="mailto:dmoulding@gmail.com">dmoulding@gmail.com.</a></p>\r
+\r
+<p>Donations to help support ongoing development of Visual Leak Detector are very appreciated!</p>\r
+\r
+<form action="https://www.paypal.com/cgi-bin/webscr" method="post">\r
+    <div>\r
+    <input type="hidden" name="cmd" value="_s-xclick" />\r
+    <input type="image" src="https://www.paypal.com/en_US/i/btn/x-click-but21.gif" name="submit" alt="Make payments with PayPal - it's fast, free and secure!" />\r
+    <input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----MIIHJwYJKoZIhvcNAQcEoIIHGDCCBxQCAQExggEwMIIBLAIBADCBlDCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20CAQAwDQYJKoZIhvcNAQEBBQAEgYB96070OV1fBDnfqkGvVtR2bQf+WKQk1DquH9rhxL3QPke1DxmckKvbKQwjqYRjZN+FbaFky71Lz75RsdeJHKcxgcJWw6cMYOI2xrmsa4Vjp00iOPjKGpMBE7roPqnnZT7l36wBBVk7Hbnm8A3MHsqTQXN9/S/rbngN57tANCbsRTELMAkGBSsOAwIaBQAwgaQGCSqGSIb3DQEHATAUBggqhkiG9w0DBwQIfRWj6EIw0C+AgYCtBQ3JuPXxq/j/RpOCteLqJqyePyFExF3ic44Doj4py33hRo9EqJrSUTbigQVT2eHkwQWS9Exs8L9aeBQQahsZNbUCyLgqPvXOOG/Zk+5Xj/2m2oBZ5AMW8rdPVCYJ7NhAc92aiU2yObd/I8n4mLGDRf768HhASKwe/LGmZiH2bKCCA4cwggODMIIC7KADAgECAgEAMA0GCSqGSIb3DQEBBQUAMIGOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC1BheVBhbCBJbmMuMRMwEQYDVQQLFApsaXZlX2NlcnRzMREwDwYDVQQDFAhsaXZlX2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbTAeFw0wNDAyMTMxMDEzMTVaFw0zNTAyMTMxMDEzMTVaMIGOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC1BheVBhbCBJbmMuMRMwEQYDVQQLFApsaXZlX2NlcnRzMREwDwYDVQQDFAhsaXZlX2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwUdO3fxEzEtcnI7ZKZL412XvZPugoni7i7D7prCe0AtaHTc97CYgm7NsAtJyxNLixmhLV8pyIEaiHXWAh8fPKW+R017+EmXrr9EaquPmsVvTywAAE1PMNOKqo2kl4Gxiz9zZqIajOm1fZGWcGS0f5JQ2kBqNbvbg2/Za+GJ/qwUCAwEAAaOB7jCB6zAdBgNVHQ4EFgQUlp98u8ZvF71ZP1LXChvsENZklGswgbsGA1UdIwSBszCBsIAUlp98u8ZvF71ZP1LXChvsENZklGuhgZSkgZEwgY4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLUGF5UGFsIEluYy4xEzARBgNVBAsUCmxpdmVfY2VydHMxETAPBgNVBAMUCGxpdmVfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAgV86VpqAWuXvX6Oro4qJ1tYVIT5DgWpE692Ag422H7yRIr/9j/iKG4Thia/Oflx4TdL+IFJBAyPK9v6zZNZtBgPBynXb048hsP16l2vi0k5Q2JKiPDsEfBhGI+HnxLXEaUWAcVfCsQFvd2A1sxRr67ip5y2wwBelUecP3AjJ+YcxggGaMIIBlgIBATCBlDCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbi\r
+BWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20CAQAwCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTA1MDgwMTE5NDQ0NlowIwYJKoZIhvcNAQkEMRYEFKLDwHJFsU6L329159saLBrfszYcMA0GCSqGSIb3DQEBAQUABIGAe4Mjshnc1RvJU9zF6nL8zPJ+nHO2ct1CbS1WFkQMWvh2NTwlIVSZFWSLJQZ32kNoyseoxUvE587qdBKyMOATXjchDeMr1y815+GWE6Ffqw3rWw/ytfVEtEJd4yUUq0gHqFACul4nWM5zP5A3zkLZEVN3gAmX1eLbMIcSCKuVafM=-----END PKCS7-----" />\r
+    </div>\r
+</form>\r
+\r
+<p id="compliance">\r
+    <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>\r
+    <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>\r
+</p>\r
+\r
+<p id="copyright">Copyright &copy; 2005-2006 Dan Moulding</p>\r
+\r
+</div> <!-- #content -->\r
+\r
+</body>\r
+\r
+</html>
\ No newline at end of file
diff --git a/development/Win32/vld/include/vld.h b/development/Win32/vld/include/vld.h
new file mode 100644 (file)
index 0000000..db136ce
--- /dev/null
@@ -0,0 +1,98 @@
+////////////////////////////////////////////////////////////////////////////////
+//  $Id: vld.h,v 1.29 2006/11/18 03:12:35 dmouldin Exp $
+//
+//  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 _DEBUG
+
+#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")
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+__declspec(dllimport) 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.
+//
+__declspec(dllimport) void VLDEnable ();
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#else // !_DEBUG
+
+#define VLDEnable()
+#define VLDDisable()
+
+#endif // _DEBUG
\ No newline at end of file
diff --git a/development/Win32/vld/src/callstack.cpp b/development/Win32/vld/src/callstack.cpp
new file mode 100644 (file)
index 0000000..7057694
--- /dev/null
@@ -0,0 +1,441 @@
+////////////////////////////////////////////////////////////////////////////////
+//  $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
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#include <cassert>
+#include <windows.h>
+#define __out_xcount(x) // Workaround for the specstrings.h bug in the Platform SDK.
+#define DBGHELP_TRANSLATE_TCHAR
+#include <dbghelp.h>    // Provides symbol handling services.
+#define VLDBUILD
+#include "callstack.h"  // This class' header.
+#include "utility.h"    // Provides various utility functions.
+#include "vldheap.h"    // Provides internal new and delete operators.
+#include "vldint.h"     // Provides access to VLD internals.
+
+#define MAXSYMBOLNAMELENGTH 256
+
+// Imported global variables.
+extern HANDLE             currentprocess;
+extern HANDLE             currentthread;
+extern CRITICAL_SECTION   stackwalklock;
+extern CRITICAL_SECTION   symbollock;
+
+// Constructor - Initializes the CallStack with an initial size of zero and one
+//   Chunk of capacity.
+//
+CallStack::CallStack ()
+{
+    m_capacity   = CALLSTACKCHUNKSIZE;
+    m_size       = 0;
+    m_status     = 0x0;
+    m_store.next = NULL;
+    m_topchunk   = &m_store;
+    m_topindex   = 0;
+}
+
+// Copy Constructor - For efficiency, we want to avoid ever making copies of
+//   CallStacks (only pointer passing or reference passing should be performed).
+//   The sole purpose of this copy constructor is to ensure that no copying is
+//   being done inadvertently.
+//
+CallStack::CallStack (const CallStack &)
+{
+    // Don't make copies of CallStacks!
+    assert(FALSE);
+}
+
+// Destructor - Frees all memory allocated to the CallStack.
+//
+CallStack::~CallStack ()
+{
+    CallStack::chunk_t *chunk = m_store.next;
+    CallStack::chunk_t *temp;
+
+    while (chunk) {
+        temp = chunk;
+        chunk = temp->next;
+        delete temp;
+    }
+}
+
+// operator = - Assignment operator. For efficiency, we want to avoid ever
+//   making copies of CallStacks (only pointer passing or reference passing
+//   should be performed). The sole purpose of this assignment operator is to
+//   ensure that no copying is being done inadvertently.
+//
+CallStack& CallStack::operator = (const CallStack &)
+{
+    // Don't make copies of CallStacks!
+    assert(FALSE);
+    return *this;
+}
+
+// operator == - Equality operator. Compares the CallStack to another CallStack
+//   for equality. Two CallStacks are equal if they are the same size and if
+//   every frame in each is identical to the corresponding frame in the other.
+//
+//  other (IN) - Reference to the CallStack to compare the current CallStack
+//    against for equality.
+//
+//  Return Value:
+//
+//    Returns true if the two CallStacks are equal. Otherwise returns false.
+//
+BOOL CallStack::operator == (const CallStack &other) const
+{
+    const CallStack::chunk_t *chunk = &m_store;
+    UINT32                    index;
+    const CallStack::chunk_t *otherchunk = &other.m_store;
+    const CallStack::chunk_t *prevchunk = NULL;
+
+    if (m_size != other.m_size) {
+        // They can't be equal if the sizes are different.
+        return FALSE;
+    }
+
+    // Walk the chunk list and within each chunk walk the frames array until we
+    // either find a mismatch, or until we reach the end of the call stacks.
+    while (prevchunk != m_topchunk) {
+        for (index = 0; index < ((chunk == m_topchunk) ? m_topindex : CALLSTACKCHUNKSIZE); index++) {
+            if (chunk->frames[index] != otherchunk->frames[index]) {
+                // Found a mismatch. They are not equal.
+                return FALSE;
+            }
+        }
+        prevchunk = chunk;
+        chunk = chunk->next;
+        otherchunk = otherchunk->next;
+    }
+
+    // Reached the end of the call stacks. They are equal.
+    return TRUE;
+}
+
+// operator [] - Random access operator. Retrieves the frame at the specified
+//   index.
+//
+//   Note: We give up a bit of efficiency here, in favor of efficiency of push
+//     operations. This is because walking of a CallStack is done infrequently
+//     (only if a leak is found), whereas pushing is done very frequently (for
+//     each frame in the program's call stack when the program allocates some
+//     memory).
+//
+//  - index (IN): Specifies the index of the frame to retrieve.
+//
+//  Return Value:
+//
+//    Returns the program counter for the frame at the specified index. If the
+//    specified index is out of range for the CallStack, the return value is
+//    undefined.
+//
+SIZE_T CallStack::operator [] (UINT32 index) const
+{
+    UINT32                    count;
+    const CallStack::chunk_t *chunk = &m_store;
+    UINT32                    chunknumber = index / CALLSTACKCHUNKSIZE;
+
+    for (count = 0; count < chunknumber; count++) {
+        chunk = chunk->next;
+    }
+
+    return chunk->frames[index % CALLSTACKCHUNKSIZE];
+}
+
+// clear - Resets the CallStack, returning it to a state where no frames have
+//   been pushed onto it, readying it for reuse.
+//
+//   Note: Calling this function does not release any memory allocated to the
+//     CallStack. We give up a bit of memory-usage efficiency here in favor of
+//     performance of push operations.
+//
+//  Return Value:
+//
+//    None.
+//
+VOID CallStack::clear ()
+{
+    m_size     = 0;
+    m_topchunk = &m_store;
+    m_topindex = 0;
+}
+
+// dump - Dumps a nicely formatted rendition of the CallStack, including
+//   symbolic information (function names and line numbers) if available.
+//
+//   Note: The symbol handler must be initialized prior to calling this
+//     function.
+//
+//  - showinternalframes (IN): If true, then all frames in the CallStack will be
+//      dumped. Otherwise, frames internal to the heap will not be dumped.
+//
+//  Return Value:
+//
+//    None.
+//
+VOID CallStack::dump (BOOL showinternalframes) const
+{
+    DWORD            displacement;
+    DWORD64          displacement64;
+    BOOL             foundline;
+    UINT32           frame;
+    SYMBOL_INFO     *functioninfo;
+    LPWSTR           functionname;
+    SIZE_T           programcounter;
+    IMAGEHLP_LINE64  sourceinfo = { 0 };
+    BYTE             symbolbuffer [sizeof(SYMBOL_INFO) + (MAXSYMBOLNAMELENGTH * sizeof(WCHAR)) - 1] = { 0 };
+
+    if (m_status & CALLSTACK_STATUS_INCOMPLETE) {
+        // This call stack appears to be incomplete. Using StackWalk64 may be
+        // more reliable.
+        report(L"    HINT: The following call stack may be incomplete. Setting \"StackWalkMethod\"\n"
+               L"      in the vld.ini file to \"safe\" instead of \"fast\" may result in a more\n"
+               L"      complete stack trace.\n");
+    }
+
+    // Initialize structures passed to the symbol handler.
+    functioninfo = (SYMBOL_INFO*)&symbolbuffer;
+    functioninfo->SizeOfStruct = sizeof(SYMBOL_INFO);
+    functioninfo->MaxNameLen = MAXSYMBOLNAMELENGTH;
+    sourceinfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+
+    // Iterate through each frame in the call stack.
+    for (frame = 0; frame < m_size; frame++) {
+        // Try to get the source file and line number associated with
+        // this program counter address.
+        programcounter = (*this)[frame];
+        EnterCriticalSection(&symbollock);
+        if ((foundline = SymGetLineFromAddrW64(currentprocess, programcounter, &displacement, &sourceinfo)) == TRUE) {
+            if (!showinternalframes) {
+                _wcslwr_s(sourceinfo.FileName, wcslen(sourceinfo.FileName) + 1);
+                if (wcsstr(sourceinfo.FileName, L"afxmem.cpp") ||
+                    wcsstr(sourceinfo.FileName, L"dbgheap.c") ||
+                    wcsstr(sourceinfo.FileName, L"malloc.c") ||
+                    wcsstr(sourceinfo.FileName, L"new.cpp") ||
+                    wcsstr(sourceinfo.FileName, L"newaop.cpp")) {
+                    // Don't show frames in files internal to the heap.
+                    continue;
+                }
+            }
+        }
+
+        // Try to get the name of the function containing this program
+        // counter address.
+        if (SymFromAddrW(currentprocess, (*this)[frame], &displacement64, functioninfo)) {
+            functionname = functioninfo->Name;
+        }
+        else {
+            functionname = L"(Function name unavailable)";
+        }
+        LeaveCriticalSection(&symbollock);
+
+        // Display the current stack frame's information.
+        if (foundline) {
+            report(L"    %s (%d): %s\n", sourceinfo.FileName, sourceinfo.LineNumber, functionname);
+        }
+        else {
+            report(L"    " ADDRESSFORMAT L" (File and line number not available): ", (*this)[frame]);
+            report(L"%s\n", functionname);
+        }
+    }
+}
+
+// push_back - Pushes a frame's program counter onto the CallStack. Pushes are
+//   always appended to the back of the chunk list (aka the "top" chunk).
+//
+//   Note: This function will allocate additional memory as necessary to make
+//     room for new program counter addresses.
+//
+//  - programcounter (IN): The program counter address of the frame to be pushed
+//      onto the CallStack.
+//
+//  Return Value:
+//
+//    None.
+//
+VOID CallStack::push_back (const SIZE_T programcounter)
+{
+    CallStack::chunk_t *chunk;
+
+    if (m_size == m_capacity) {
+        // At current capacity. Allocate additional storage.
+        chunk = new CallStack::chunk_t;
+        chunk->next = NULL;
+        m_topchunk->next = chunk;
+        m_topchunk = chunk;
+        m_topindex = 0;
+        m_capacity += CALLSTACKCHUNKSIZE;
+    }
+    else if (m_topindex == CALLSTACKCHUNKSIZE) {
+        // There is more capacity, but not in this chunk. Go to the next chunk.
+        // Note that this only happens if this CallStack has previously been
+        // cleared (clearing resets the data, but doesn't give up any allocated
+        // space).
+        m_topchunk = m_topchunk->next;
+        m_topindex = 0;
+    }
+
+    m_topchunk->frames[m_topindex++] = programcounter;
+    m_size++;
+}
+
+// getstacktrace - Traces the stack as far back as possible, or until 'maxdepth'
+//   frames have been traced. Populates the CallStack with one entry for each
+//   stack frame traced.
+//
+//   Note: This function uses a very efficient method to walk the stack from
+//     frame to frame, so it is quite fast. However, unconventional stack frames
+//     (such as those created when frame pointer omission optimization is used)
+//     will not be successfully walked by this function and will cause the
+//     stack trace to terminate prematurely.
+//
+//  - maxdepth (IN): Maximum number of frames to trace back.
+//
+//  - framepointer (IN): Frame (base) pointer at which to begin the stack trace.
+//      If NULL, then the stack trace will begin at this function.
+//
+//  Return Value:
+//
+//    None.
+//
+VOID FastCallStack::getstacktrace (UINT32 maxdepth, SIZE_T *framepointer)
+{
+    UINT32  count = 0;
+
+    if (framepointer == NULL) {
+        // Begin the stack trace with the current frame. Obtain the current
+        // frame pointer.
+        FRAMEPOINTER(framepointer);
+    }
+
+    while (count < maxdepth) {
+        if ((SIZE_T*)*framepointer < framepointer) {
+            if ((SIZE_T*)*framepointer == NULL) {
+                // Looks like we reached the end of the stack.
+                break;
+            }
+            else {
+                // Invalid frame pointer. Frame pointer addresses should always
+                // increase as we move up the stack.
+                m_status |= CALLSTACK_STATUS_INCOMPLETE;
+                break;
+            }
+        }
+        if ((SIZE_T)*framepointer & (sizeof(SIZE_T*) - 1)) {
+            // Invalid frame pointer. Frame pointer addresses should always
+            // be aligned to the size of a pointer. This probably means that
+            // we've encountered a frame that was created by a module built with
+            // frame pointer omission (FPO) optimization turned on.
+            m_status |= CALLSTACK_STATUS_INCOMPLETE;
+            break;
+        }
+        if (IsBadReadPtr((SIZE_T*)*framepointer, sizeof(SIZE_T*))) {
+            // Bogus frame pointer. Again, this probably means that we've
+            // encountered a frame built with FPO optimization.
+            m_status |= CALLSTACK_STATUS_INCOMPLETE;
+            break;
+        }
+        count++;
+        push_back(*(framepointer + 1));
+        framepointer = (SIZE_T*)*framepointer;
+    }
+}
+
+// getstacktrace - Traces the stack as far back as possible, or until 'maxdepth'
+//   frames have been traced. Populates the CallStack with one entry for each
+//   stack frame traced.
+//
+//   Note: This function uses a documented Windows API to walk the stack. This
+//     API is supposed to be the most reliable way to walk the stack. It claims
+//     to be able to walk stack frames that do not follow the conventional stack
+//     frame layout. However, this robustness comes at a cost: it is *extremely*
+//     slow compared to walking frames by following frame (base) pointers.
+//
+//  - maxdepth (IN): Maximum number of frames to trace back.
+//
+//  - framepointer (IN): Frame (base) pointer at which to begin the stack trace.
+//      If NULL, then the stack trace will begin at this function.
+//
+//  Return Value:
+//
+//    None.
+//
+VOID SafeCallStack::getstacktrace (UINT32 maxdepth, SIZE_T *framepointer)
+{
+    DWORD        architecture;
+    CONTEXT      context;
+    UINT32       count = 0;
+    STACKFRAME64 frame;
+    SIZE_T       programcounter;
+    SIZE_T       stackpointer;
+
+    if (framepointer == NULL) {
+        // Begin the stack trace with the current frame. Obtain the current
+        // frame pointer.
+        FRAMEPOINTER(framepointer);
+    }
+
+    // Get the required values for initialization of the STACKFRAME64 structure
+    // to be passed to StackWalk64(). Required fields are AddrPC and AddrFrame.
+#if defined(_M_IX86) || defined(_M_X64)
+    architecture   = X86X64ARCHITECTURE;
+    programcounter = *(framepointer + 1);
+    stackpointer   = *framepointer;  // An approximation.
+    context.BPREG  = *framepointer;
+    context.IPREG  = programcounter;
+    context.SPREG  = stackpointer;
+#else
+// If you want to retarget Visual Leak Detector to another processor
+// architecture then you'll need to provide architecture-specific code to
+// obtain the program counter and stack pointer from the given frame pointer.
+#error "Visual Leak Detector is not supported on this architecture."
+#endif // _M_IX86 || _M_X64
+
+    // Initialize the STACKFRAME64 structure.
+    memset(&frame, 0x0, sizeof(frame));
+    frame.AddrFrame.Offset = *framepointer;
+    frame.AddrFrame.Mode   = AddrModeFlat;
+    frame.AddrPC.Offset    = programcounter;
+    frame.AddrPC.Mode      = AddrModeFlat;
+    frame.AddrStack.Offset = stackpointer;
+    frame.AddrStack.Mode   = AddrModeFlat;
+
+    // Walk the stack.
+    EnterCriticalSection(&stackwalklock);
+    while (count < maxdepth) {
+        count++;
+        if (!StackWalk64(architecture, currentprocess, currentthread, &frame, &context, NULL,
+                         SymFunctionTableAccess64, SymGetModuleBase64, NULL)) {
+            // Couldn't trace back through any more frames.
+            break;
+        }
+        if (frame.AddrFrame.Offset == 0) {
+            // End of stack.
+            break;
+        }
+
+        // Push this frame's program counter onto the CallStack.
+        push_back((SIZE_T)frame.AddrPC.Offset);
+    }
+    LeaveCriticalSection(&stackwalklock);
+}
diff --git a/development/Win32/vld/src/callstack.h b/development/Win32/vld/src/callstack.h
new file mode 100644 (file)
index 0000000..b4d3d66
--- /dev/null
@@ -0,0 +1,117 @@
+////////////////////////////////////////////////////////////////////////////////
+//  $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
+//
+//  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
+
+#ifndef VLDBUILD
+#error \
+"This header should only be included by Visual Leak Detector when building it from source. \
+Applications should never include this header."
+#endif
+
+#include <windows.h>
+
+#define CALLSTACKCHUNKSIZE 32 // Number of frame slots in each CallStack chunk.
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//  The CallStack Class
+//
+//    CallStack objects can be used for obtaining, storing, and displaying the
+//    call stack at a given point during program execution.
+//
+//    The primary data structure used by the CallStack is similar in concept to
+//    a STL vector, but is specifically tailored for use by VLD, making it more
+//    efficient than a standard STL vector.
+//
+//    Inside the CallStack are a number of "chunks" which are arranged in a
+//    linked list. Each chunk contains an array of frames (each frame is
+//    represented by a program counter address). If we run out of space when
+//    pushing new frames onto an existing chunk in the CallStack chunk list,
+//    then a new chunk is allocated and appended to the end of the list. In this
+//    way, the CallStack can grow dynamically as needed. New frames are always
+//    pushed onto the chunk at the end of the list known as the "top" chunk.
+//
+class CallStack
+{
+public:
+    CallStack ();
+    CallStack (const CallStack &other);
+    ~CallStack ();
+
+    // Public APIs - see each function definition for details.
+    VOID clear ();
+    VOID dump (BOOL showinternalframes) const;
+    virtual VOID getstacktrace (UINT32 maxdepth, SIZE_T *framepointer) = 0;
+    CallStack& operator = (const CallStack &other);
+    BOOL operator == (const CallStack &other) const;
+    SIZE_T operator [] (UINT32 index) const;
+    VOID push_back (const SIZE_T programcounter);
+
+protected:
+    // Protected data.
+    UINT32 m_status;                    // Status flags:
+#define CALLSTACK_STATUS_INCOMPLETE 0x1 //   If set, the stack trace stored in this CallStack appears to be incomplete.
+
+private:
+    // The chunk list is made of a linked list of Chunks.
+    typedef struct chunk_s {
+        struct chunk_s *next;                        // Pointer to the next chunk in the chunk list.
+        SIZE_T          frames [CALLSTACKCHUNKSIZE]; // Pushed frames (program counter addresses) are stored in this array.
+    } chunk_t;
+
+    // Private data.
+    UINT32              m_capacity; // Current capacity limit (in frames)
+    UINT32              m_size;     // Current size (in frames)
+    CallStack::chunk_t  m_store;    // Pointer to the underlying data store (i.e. head of the chunk list)
+    CallStack::chunk_t *m_topchunk; // Pointer to the chunk at the top of the stack
+    UINT32              m_topindex; // Index, within the top chunk, of the top of the stack
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//  The FastCallStack Class
+//
+//    This class is a specialization of the CallStack class which provides a
+//    very fast stack tracing function.
+//
+class FastCallStack : public CallStack
+{
+public:
+    VOID getstacktrace (UINT32 maxdepth, SIZE_T *framepointer);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//  The SafeCallStack Class
+//
+//    This class is a specialization of the CallStack class which provides a
+//    more robust, but quite slow, stack tracing function.
+//
+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/map.h b/development/Win32/vld/src/map.h
new file mode 100644 (file)
index 0000000..8f06549
--- /dev/null
@@ -0,0 +1,358 @@
+////////////////////////////////////////////////////////////////////////////////
+//  $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
+//
+//  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
+
+#ifndef VLDBUILD
+#error \
+"This header should only be included by Visual Leak Detector when building it from source. \
+Applications should never include this header."
+#endif
+
+#include "tree.h" // Provides access to the Tree template class.
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//  The Pair Template Class
+//
+//  This is a lightweight STL-like pair template, for use with the lightweight
+//  Map class template.
+//
+//  Note that while this is a STL-like class, it is not a full STL-compliant
+//  implementation of the STL pair utility class. It provides just the bare
+//  minimum functionality required by the Visual Leak Detector Map template
+//  class below.
+//
+template <typename Tf, typename Ts>
+class Pair {
+public:
+    // Constructor
+    Pair ()
+    {
+        first = Tf();
+        second = Ts();
+    }
+
+    // Constructor with initializers.
+    Pair (const Tf &f, const Ts &s)
+    {
+        first = f;
+        second = s;
+    }
+
+    // Less-than operator - Compares this Pair with another Pair to determine
+    //   if this Pair is less than the other Pair. The Pair with the smallest
+    //   "first" value is the lesser Pair.
+    //
+    //  - other (IN): The other pair to compare against.
+    //
+    //  Return Value:
+    //
+    //    Returns true if this Pair is less than the other Pair. Otherwise
+    //    returns false.
+    //
+    BOOL operator < (const Pair &other) const
+    {
+        return (first < other.first);
+    }
+
+    // Public data.
+    Tf first;  // The first value of the pair.
+    Ts second; // The second value of the pair.
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//  The Map Template Class
+//
+//  This is a lightweidht STL-like map template. It makes use of the Tree class
+//  template to enable fast insert, find, and erase operations.
+//
+//  Note that while this is a STL-like class, it is not a full STL-compliant
+//  implementation of the STL map container. It contains just the bare minimum
+//  functionality required by Visual Leak Detector. Because of its "lightweight"
+//  nature, this map class has a noticeable performance advantage over some
+//  other standard STL map implementations.
+//
+template <typename Tk, typename Tv>
+class Map {
+public:
+    class Iterator {
+    public:
+        // Constructor
+        Iterator ()
+        {
+            // Plainly constructed iterators don't reference anything.
+            m_node = NULL;
+            m_tree = NULL;
+        }
+
+        // operator != - Inequality operator for Map Iterators. Two Map
+        //   Iterators are considered equal if and only if they both reference
+        //   the same key/value pair in the same Map.
+        //
+        //  - other (IN): The other Map Iterator to compare against.
+        //
+        //  Return Value:
+        //
+        //    Returns true if the specified Map Iterator is not equal to this
+        //    Map Iterator; otherwise, returns false.
+        //
+        BOOL operator != (const Iterator &other) const
+        {
+            return ((m_tree != other.m_tree) || (m_node != other.m_node));
+        }
+
+        // operator * - Dereference operator for Map Iterators.
+        //
+        //  Note:  The reference returned by this function is "const", so the
+        //    value referenced by the Iterator may not be modified through the
+        //    Iterator. This is a departure from STL iterator behavior.
+        //
+        //    Also, dereferencing an Iterator which does not reference a valid
+        //    value in the Map is undefined and will almost certainly cause a
+        //    crash.
+        //
+        //  Return Value:
+        //
+        //    Returns a const reference to the key/value pair in the Map
+        //    referenced by the Iterator.
+        //
+        const Pair<Tk, Tv>& operator * () const
+        {
+            return m_node->key;
+        }
+
+        // operator ++ - Prefix increment operator for Map Iterators. Causes the
+        //   Iterator to reference the in-oder successor of the key/value pair
+        //   currently referenced by the Iterator. If the Iterator is currently
+        //   referencing the largest key/value pair in the Map, then the
+        //   resulting Iterator will reference the Map's end (the NULL pair).
+        //
+        //  Note: Incrementing an Iterator which does not reference a valid
+        //    key/value pair in the Map is undefined and will almost certainly
+        //    cause a crash.
+        //
+        //  Return Value:
+        //
+        //    Returns the Iterator after it has been incremented.
+        // 
+        Iterator& operator ++ (int)
+        {
+            m_node = m_tree->next(m_node);
+            return *this;
+        }
+
+        // operator ++ - Postfix increment operator for Map Iterators. Causes
+        //   the Iterator to reference the in-order successor of the key/value
+        //   pair currently referenced by the Iterator. If the Iterator is
+        //   currently referencing the largest key/value pair in the Map, then
+        //   the resulting Iterator will reference the Map's end (the NULL
+        //   pair).
+        //
+        //  Note: Incrementing an Iterator which does not reference a valid
+        //    key/value pair in the Map is undefined and will almost certainly
+        //    cause a crash.
+        //
+        //  Return Value:
+        //
+        //    Returns the Iterator before it has been incremented.
+        // 
+        Iterator operator ++ ()
+        {
+            typename Tree<Pair<Tk, Tv> >::node_t *cur = m_node;
+
+            m_node = m_tree->next(m_node);
+            return Iterator(m_tree, cur);
+        }
+
+        // operator - - Subtraction operator for Map Iterators. Causes the
+        //   the Iterator to reference a key/value pair that is an in-order
+        //   predecessor of the currently refereced key/value pair.
+        //
+        //  - num (IN): Number indicating the number of preceding key/value
+        //      pairs to decrement the iterator.
+        //
+        //  Return Value:
+        //
+        //    Returns an Iterator referencing the key/value pair that precedes
+        //    the original Iterator by "num" pairs.
+        //
+        Iterator operator - (SIZE_T num) const
+        {
+            SIZE_T                                count;
+            typename Tree<Pair<Tk, Tv> >::node_t *cur = m_node;
+
+            cur = m_tree->prev(m_node);
+            for (count = 0; count < num; count++)  {
+                cur = m_tree->prev(m_node);
+                if (cur == NULL) {
+                    return Iterator(m_tree, NULL);
+                }
+            }
+            return Iterator(m_tree, cur);
+        }
+
+        // operator == - Equality operator for Map Iterators. Map Iterators are
+        //   considered equal if and only if they both refernce the same
+        //   key/value pair in the same Map.
+        //
+        //  - other (IN): The other Map Iterator to compare against.
+        //
+        //  Return Value:
+        //
+        //    Returns true if the specified Map Iterator is equal to this Map
+        //    Iterator; otherwise returns false.
+        //
+        BOOL operator == (const Iterator &other) const
+        {
+            return ((m_tree == other.m_tree) && (m_node == other.m_node));
+        }
+
+    private:
+        // Private constructor. Only the Map class itself may use this
+        //   constructor. It is used for constructing Iterators which reference
+        //   specific nodes in the internal tree's structure.
+        Iterator (const Tree<Pair<Tk, Tv> > *tree, typename Tree<Pair<Tk, Tv> >::node_t *node)
+        {
+            m_node = node;
+            m_tree = tree;
+        }
+
+        typename Tree<Pair<Tk, Tv> >::node_t *m_node; // Pointer to the node referenced by the Map Iterator.
+        const Tree<Pair<Tk, Tv> >            *m_tree; // Pointer to the tree containing the referenced node.
+
+        // The Map class is a friend of Map Iterators.
+        friend class Map<Tk, Tv>;
+    };
+
+    // begin - Obtains an Iterator referencing the beginning of the Map (i.e.
+    //   the lowest key/value pair currently stored in the Map).
+    //
+    //  Return Value:
+    //
+    //    Returns an Iterator referencing the first key/value pair in the Map.
+    //    If no key/value pairs are currenly stored in the map, returns the
+    //    "NULL" Iterator.
+    //
+    Iterator begin () const
+    {
+        return Iterator(&m_tree, m_tree.begin());
+    }
+
+    // end - Obtains an Iterator referencing the end of the Map. The end of
+    //   the map does not reference an actual key/value pair. Instead it
+    //   represents a "null" key/value pair which signifies the end (i.e. just
+    //   beyond largest key/value pair currently stored in the Map). Also
+    //   known as the "NULL" Iterator.
+    //
+    //  Return Value:
+    //
+    //    Returns the "NULL" Iterator, signifying the end of the Map.
+    //
+    Iterator end () const
+    {
+        return Iterator(&m_tree, NULL);
+    }
+
+    // erase - Erases a key/value pair from the map.
+    //
+    //  - it (IN): Iterator referencing the key/value pair to be erased from
+    //      the map.
+    //
+    //  Return Value:
+    //
+    //    None.
+    //
+    VOID erase (Iterator& it)
+    {
+        m_tree.erase(it.m_node);
+    }
+
+    // erase - Erases a key/value pair from the map.
+    //
+    //  - key (IN): The key corresponding to the key/value pair to be erased
+    //      from the map.
+    //
+    //  Return Value:
+    //
+    //    None.
+    //
+    VOID erase (const Tk &key)
+    {
+        m_tree.erase(Pair<Tk, Tv>(key, Tv()));
+    }
+
+    // find - Finds a key/value pair in the map.
+    //
+    //  - key (IN): The key corresponding to the key/value pair to be found.
+    //
+    //  Return Value:
+    //
+    //    Returns an Iterator referencing the found key/value pair. If no
+    //    key/value pair with the specified key could be found, then the "NULL"
+    //    Iterator is returned.
+    //
+    Iterator find (const Tk &key) const
+    {
+        return Iterator(&m_tree, m_tree.find(Pair<Tk, Tv>(key, Tv())));
+    }
+
+    // insert - Inserts a key/value pair into the map.
+    //
+    //  - key (IN): The key of the key/value pair to be inserted.
+    //
+    //  - data (IN): The value of the key/value pair to be inserted.
+    //
+    //  Return Value:
+    //
+    //    Returns an Iterator referencing the resulting key/value pair after
+    //    if has been inserted into the map.
+    //
+    Iterator insert (const Tk &key, const Tv &data)
+    {
+        return Iterator(&m_tree, m_tree.insert(Pair<Tk, Tv>(key, data)));
+    }
+
+    // reserve - Sets the reserve size of the map. The reserve size is the
+    //   number of key/value pairs for which space should be pre-allocated
+    //   to avoid frequent heap hits when inserting new key/value pairs into
+    //   the map.
+    //
+    //  - count (IN): The number of key/value pairs for which to reserve space
+    //      in advance.
+    //
+    //  Return Value:
+    //
+    //    Returns the reserve size previously in use by the map.
+    //
+    size_t reserve (size_t count)
+    {
+        return m_tree.reserve(count);
+    }
+
+private:
+    // Private data
+    Tree<Pair<Tk, Tv> > m_tree; // The key/value pairs are actually stored in a tree.
+};
diff --git a/development/Win32/vld/src/ntapi.cpp b/development/Win32/vld/src/ntapi.cpp
new file mode 100644 (file)
index 0000000..278d722
--- /dev/null
@@ -0,0 +1,33 @@
+////////////////////////////////////////////////////////////////////////////////
+//  $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
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#define VLDBUILD
+#include "ntapi.h"
+
+// Global function pointers for explicit dynamic linking with NT APIs that can't
+// be load-time linked (there is no import library available for these).
+LdrLoadDll_t        LdrLoadDll;
+RtlAllocateHeap_t   RtlAllocateHeap;
+RtlFreeHeap_t       RtlFreeHeap;
+RtlReAllocateHeap_t RtlReAllocateHeap;
\ No newline at end of file
diff --git a/development/Win32/vld/src/ntapi.h b/development/Win32/vld/src/ntapi.h
new file mode 100644 (file)
index 0000000..26add1e
--- /dev/null
@@ -0,0 +1,58 @@
+////////////////////////////////////////////////////////////////////////////////
+//  $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
+//
+//  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
+
+#ifndef VLDBUILD
+#error \
+"This header should only be included by Visual Leak Detector when building it from source. \
+Applications should never include this header."
+#endif
+
+#include <windows.h>
+
+// Return code type used by LdrLoadDll.
+typedef ULONG NTSTATUS;
+#define   STATUS_SUCCESS 0
+
+// Unicode string structure used by NT APIs.
+typedef struct unicodestring_s {
+    USHORT length;    // Length of the string.
+    USHORT maxlength; // Length of the buffer.
+    PWSTR  buffer;    // The buffer containing the string.
+} unicodestring_t;
+
+// Function pointer types for explicit dynamic linking with functions that can't
+// be load-time linked (no import library is available for these).
+typedef NTSTATUS (__stdcall *LdrLoadDll_t) (LPWSTR, PDWORD, unicodestring_t *, PHANDLE);
+typedef LPVOID (__stdcall *RtlAllocateHeap_t) (HANDLE, DWORD, SIZE_T);
+typedef BOOL (__stdcall *RtlFreeHeap_t) (HANDLE, DWORD, LPVOID);
+typedef LPVOID (__stdcall *RtlReAllocateHeap_t) (HANDLE, DWORD, LPVOID, SIZE_T);
+
+// Provide forward declarations for the NT APIs for any source files that
+// include this header.
+extern LdrLoadDll_t        LdrLoadDll;
+extern RtlAllocateHeap_t   RtlAllocateHeap;
+extern RtlFreeHeap_t       RtlFreeHeap;
+extern RtlReAllocateHeap_t RtlReAllocateHeap;
diff --git a/development/Win32/vld/src/set.h b/development/Win32/vld/src/set.h
new file mode 100644 (file)
index 0000000..cfab1b1
--- /dev/null
@@ -0,0 +1,338 @@
+////////////////////////////////////////////////////////////////////////////////
+//  $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
+//
+//  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
+
+#ifndef VLDBUILD
+#error \
+"This header should only be included by Visual Leak Detector when building it from source. \
+Applications should never include this header."
+#endif
+
+#include "tree.h" // Provides access to the Tree template class.
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//  The Set Template Class
+//
+//  This is a lightweight STL-like set template. It makes use of the Tree class
+//  template to enable fast insert, find, and erase operations.
+//
+//  Note that while this is a STL-like class, it is not a full STL-compliant
+//  implementation of the STL set container. It contains just the bare minimum
+//  functionality required by Visual Leak Detector. Because of its "lightweight"
+//  nature, this set class has a noticeable performance advantage over some
+//  other standard STL set implementations.
+//
+template <typename Tk>
+class Set {
+public:
+    class Iterator {
+    public:
+        // Constructor
+        Iterator ()
+        {
+            // Plainly constructed iterators don't reference anything.
+            m_node = NULL;
+            m_tree = NULL;
+        }
+
+        // operator != - Inequality operator for Set Iterators. Two Set
+        //   Iterators are considered equal if and only if they both reference
+        //   the same key in the same Set.
+        //
+        //  - other (IN): The other Set Iterator to compare against.
+        //
+        //  Return Value:
+        //
+        //    Returns true if the specified Set Iterator is not equal to this
+        //    Set Iterator; otherwise, returns false.
+        //
+        BOOL operator != (const Iterator &other) const
+        {
+            return ((m_tree != other.m_tree) || (m_node != other.m_node));
+        }
+
+        // operator * - Dereference operator for Set Iterators.
+        //
+        //  Note:  The reference returned by this function is "const", so the
+        //    value referenced by the Iterator may not be modified through the
+        //    Iterator. This is a departure from STL iterator behavior.
+        //
+        //    Also, dereferencing an Iterator which does not reference a valid
+        //    value in the Set is undefined and will almost certainly cause a
+        //    crash.
+        //
+        //  Return Value:
+        //
+        //    Returns a const reference to the key in the Map referenced by the
+        //    Iterator.
+        //
+        const Tk& operator * () const
+        {
+            return m_node->key;
+        }
+
+        // operator ++ - Prefix increment operator for Set Iterators. Causes the
+        //   Iterator to reference the in-oder successor of the key currently
+        //   referenced by the Iterator. If the Iterator is currently
+        //   referencing the largest key in the Map, then the resulting Iterator
+        //   will reference the Set's end (the NULL pair).
+        //
+        //  Note: Incrementing an Iterator which does not reference a valid
+        //    key in the Set is undefined and will almost certainly cause a
+        //    crash.
+        //
+        //  Return Value:
+        //
+        //    Returns the Iterator after it has been incremented.
+        // 
+        Iterator& operator ++ (int)
+        {
+            m_node = m_tree->next(m_node);
+            return *this;
+        }
+
+        // operator ++ - Postfix increment operator for Map Iterators. Causes
+        //   the Iterator to reference the in-order successor of the key/value
+        //   pair currently referenced by the Iterator. If the Iterator is
+        //   currently referencing the largest key/value pair in the Map, then
+        //   the resulting Iterator will reference the Map's end (the NULL
+        //   pair).
+        //
+        //  Note: Incrementing an Iterator which does not reference a valid
+        //    key/value pair in the Map is undefined and will almost certainly
+        //    cause a crash.
+        //
+        //  Return Value:
+        //
+        //    Returns the Iterator before it has been incremented.
+        // 
+        Iterator operator ++ ()
+        {
+            typename Tree<Tk>::node_t *cur = m_node;
+
+            m_node = m_tree->next(m_node);
+            return Iterator(m_tree, cur);
+        }
+
+        // operator - - Subtraction operator for Set Iterators. Causes the
+        //   the Iterator to reference a key that is an in-order predecessor of
+        //   the currently refereced key.
+        //
+        //  - num (IN): Number indicating the number of preceding keys to
+        //      decrement the iterator.
+        //
+        //  Return Value:
+        //
+        //    Returns an Iterator referencing the key that precedes the original
+        //    Iterator by "num" keys.
+        //
+        Iterator operator - (SIZE_T num) const
+        {
+            SIZE_T                     count;
+            typename Tree<Tk>::node_t *cur = m_node;
+
+            cur = m_tree->prev(m_node);
+            for (count = 0; count < num; count++)  {
+                cur = m_tree->prev(m_node);
+                if (cur == NULL) {
+                    return Iterator(m_tree, NULL);
+                }
+            }
+            return Iterator(m_tree, cur);
+        }
+
+        // operator == - Equality operator for Set Iterators. Set Iterators are
+        //   considered equal if and only if they both refernce the same
+        //   key in the same Set.
+        //
+        //  - other (IN): The other Set Iterator to compare against.
+        //
+        //  Return Value:
+        //
+        //    Returns true if the specified Set Iterator is equal to this Set
+        //    Iterator; otherwise returns false.
+        //
+        BOOL operator == (const Iterator &other) const
+        {
+            return ((m_tree == other.m_tree) && (m_node == other.m_node));
+        }
+
+    private:
+        // Private constructor. Only the Set class itself may use this
+        //   constructor. It is used for constructing Iterators which reference
+        //   specific nodes in the internal tree's structure.
+        Iterator (const Tree<Tk> *tree, typename Tree<Tk>::node_t *node)
+        {
+            m_node = node;
+            m_tree = tree;
+        }
+
+    protected:
+        typename Tree<Tk>::node_t *m_node; // Pointer to the node referenced by the Set Iterator.
+        const Tree<Tk>            *m_tree; // Pointer to the tree containing the referenced node.
+
+        // The Set class is a friend of Set Iterators.
+        friend class Set<Tk>;
+    };
+
+    // Muterator class - This class provides a mutable Iterator (the regular
+    // Iterators are const Iterators). By dereferencing a Muterator, you get
+    // a modifiable element.
+    //
+    //   Caution: Modifing an element in a way that changes its sorting value
+    //     will corrupt the Set container. Muterators should only be used when
+    //     you are absolutely certain you will not be using it to make a
+    //     modification that changes the sort order of the referenced element.
+    //
+    class Muterator : public Iterator
+    {
+    public:
+        // operator = - Assignment operator for Set Muterators. Can be used to
+        //   copy a Muterator from an existing Iterator, such that the Muterator
+        //   references the same element referenced by the Iterator.
+        Muterator& operator = (const Iterator& other) {
+            *(Iterator*)this = other;
+            return *this;
+        }
+
+        // operator * - Dereference operator for Set Muterators.
+        //
+        //  Note: Dereferencing a Muterator which does not reference a valid
+        //    value in the Set is undefined and will almost certainly cause a
+        //    crash.
+        //
+        //  Return Value:
+        //
+        //    Returns a reference to the key in the Map referenced by the
+        //    Muterator.
+        //
+        Tk& operator * ()
+        {
+            return m_node->key;
+        }
+    };
+
+    // begin - Obtains an Iterator referencing the beginning of the Set (i.e.
+    //   the lowest key currently stored in the Set).
+    //
+    //  Return Value:
+    //
+    //    Returns an Iterator referencing the first key in the Set. If no keys
+    //    are currenly stored in the Set, returns the "NULL" Iterator.
+    //
+    Iterator begin () const
+    {
+        return Iterator(&m_tree, m_tree.begin());
+    }
+
+    // end - Obtains an Iterator referencing the end of the Set. The end of
+    //   the Set does not reference an actual key. Instead it represents a
+    //   "null" key which signifies the end (i.e. just beyond largest key
+    //   currently stored in the Set). Also known as the "NULL" Iterator.
+    //
+    //  Return Value:
+    //
+    //    Returns the "NULL" Iterator, signifying the end of the Set.
+    //
+    Iterator end () const
+    {
+        return Iterator(&m_tree, NULL);
+    }
+
+    // erase - Erases a key from the Set.
+    //
+    //  - it (IN): Iterator referencing the key to be erased from the Set.
+    //
+    //  Return Value:
+    //
+    //    None.
+    //
+    VOID erase (Iterator& it)
+    {
+        m_tree.erase(it.m_node);
+    }
+
+    // erase - Erases a key from the Set.
+    //
+    //  - key (IN): The key to be erased from the Set.
+    //
+    //  Return Value:
+    //
+    //    None.
+    //
+    VOID erase (const Tk &key)
+    {
+        m_tree.erase(key);
+    }
+
+    // find - Finds a key in the Set.
+    //
+    //  - key (IN): The key to be found.
+    //
+    //  Return Value:
+    //
+    //    Returns an Iterator referencing the found key. If the key could not
+    //    be found, then the "NULL" Iterator is returned.
+    //
+    Iterator find (const Tk &key) const
+    {
+        return Iterator(&m_tree, m_tree.find(key));
+    }
+
+    // insert - Inserts a key into the Set.
+    //
+    //  - key (IN): The key to be inserted.
+    //
+    //  Return Value:
+    //
+    //    Returns an Iterator referencing the key after it has been inserted
+    //    into the Set. If an element with an identical key value already exists
+    //    in the Set, then the NULL Iterator is returned.
+    //
+    Iterator insert (const Tk &key)
+    {
+        return Iterator(&m_tree, m_tree.insert(key));
+    }
+
+    // reserve - Sets the reserve size of the Set. The reserve size is the
+    //   number of keys for which space should be pre-allocated to avoid
+    //   frequent heap hits when inserting new keys into the Set.
+    //
+    //  - count (IN): The number of keys for which to reserve space in advance.
+    //
+    //  Return Value:
+    //
+    //    Returns the reserve size previously in use by the Set.
+    //
+    size_t reserve (size_t count)
+    {
+        return m_tree.reserve(count);
+    }
+
+private:
+    // Private data
+    Tree<Tk> m_tree; // The keys are actually stored in a tree.
+};
diff --git a/development/Win32/vld/src/tree.h b/development/Win32/vld/src/tree.h
new file mode 100644 (file)
index 0000000..766104e
--- /dev/null
@@ -0,0 +1,786 @@
+////////////////////////////////////////////////////////////////////////////////
+//  $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
+//
+//  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
+
+#ifndef VLDBUILD
+#error \
+"This header should only be included by Visual Leak Detector when building it from source. \
+Applications should never include this header."
+#endif
+
+#include "vldheap.h" // Provides internal new and delete operators.
+
+#define TREE_DEFAULT_RESERVE 32 // By default, trees reserve enough space, in advance, for this many nodes.
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//  The Tree Template Class
+//
+//    This data structure is the internal data structure behind the lightweight
+//    STL-like container classes. This is a red-black tree which provides for
+//    fast insert, find, and erase operations.
+//
+//    The binary tree nodes are overlaid on top of larger chunks of allocated
+//    memory (called chunks) which are arranged in a simple linked list. This
+//    allows the tree to grow (add nodes) dynamically without incurring a heap
+//    hit each time a new node is added.
+//
+//    The Tree class provides member functions which make it easily adaptable to
+//    an STL-like interface so that it can be used as the backend for STL-like
+//    container classes.
+//
+template <typename T>
+class Tree
+{
+public:
+    // This is a red-black tree.
+    enum color_e {
+        red,
+        black
+    };
+
+    // The node is the basic data structure which the tree is built from.
+    typedef struct node_s {
+        color_e            color;  // The node's color.
+        T                  key;    // The node's value, by which nodes are sorted.
+        union {
+            struct node_s *left;   // For nodes in the tree, the node's left child.
+            struct node_s *next;   // For nodes in the free list, the next node on the free list.
+        };
+        struct node_s     *parent; // The node's parent.
+        struct node_s     *right;  // The node's right child.
+    } node_t;
+
+    // Reserve capacity for the tree is allocated in large chunks with room for
+    // many nodes.
+    typedef struct chunk_s {
+        struct chunk_s *next;  // Pointer to the next node in the chunk list.
+        node_t         *nodes; // Pointer to an array (of variable size) where nodes are stored.
+    } chunk_t;
+
+    // Constructor
+    Tree ()
+    {
+        m_freelist   = NULL;
+        InitializeCriticalSection(&m_lock);
+        m_nil.color  = black;
+        m_nil.key    = T();
+        m_nil.left   = &m_nil;
+        m_nil.parent = &m_nil;
+        m_nil.right  = &m_nil;
+        m_reserve    = TREE_DEFAULT_RESERVE;
+        m_root       = &m_nil;
+        m_store      = NULL;
+        m_storetail  = NULL;
+    }
+
+    // Copy constructor - The sole purpose of this constructor's existence is
+    //   to ensure that trees are not being inadvertently copied.
+    Tree (const Tree& source)
+    {
+        assert(FALSE); // Do not make copies of trees!
+    }
+
+    // Destructor
+    ~Tree ()
+    {
+        chunk_t *cur;
+        chunk_t *temp;
+
+        // Free all the chunks in the chunk list.
+        EnterCriticalSection(&m_lock);
+        cur = m_store;
+        while (cur != NULL) {
+            temp = cur;
+            cur = cur->next;
+            delete [] temp->nodes;
+            delete temp;
+        }
+        LeaveCriticalSection(&m_lock);
+        DeleteCriticalSection(&m_lock);
+    }
+
+    // operator = - Assignment operator. For efficiency, we want to avoid ever
+    //   making copies of Trees (only pointer passing or reference passing
+    //   should be performed). The sole purpose of this assignment operator is
+    //   to ensure that no copying is being done inadvertently.
+    //
+    Tree<T>& operator = (const Tree<T> &other)
+    {
+        // Don't make copies of Trees!
+        assert(FALSE);
+        return *this;
+    }
+
+    // begin - Obtains a pointer to the first node (the node with the smallest
+    //   key value) in the tree.
+    //
+    //  Return Value:
+    //
+    //    Returns a pointer to the first node in the tree.
+    //    
+    typename Tree::node_t* begin () const
+    {
+        node_t *cur;
+
+        EnterCriticalSection(&m_lock);
+        if (m_root == &m_nil) {
+            LeaveCriticalSection(&m_lock);
+            return NULL;
+        }
+
+        cur = m_root;
+        while (cur->left != &m_nil) {
+            cur = cur->left;
+        }
+        LeaveCriticalSection(&m_lock);
+
+        return cur;
+    }
+
+    // erase - Erases the specified node from the tree. Note that this does
+    //   not cause the key associated with the erased node to be freed. The
+    //   caller is responsible for freeing any dynamically allocated memory
+    //   associated with the key.
+    //
+    //  - node (IN): Pointer to the node to erase from the tree.
+    //
+    //  Return Value:
+    //
+    //    None.
+    //
+    VOID erase (typename Tree::node_t *node)
+    {
+        node_t *child;
+        node_t *cur;
+        node_t *erasure;
+        node_t *sibling;
+
+        EnterCriticalSection(&m_lock);
+
+        if ((node->left == &m_nil) || (node->right == &m_nil)) {
+            // The node to be erased has less than two children. It can be directly
+            // removed from the tree.
+            erasure = node;
+        }
+        else {
+            // The node to be erased has two children. It can only be removed
+            // indirectly. The actual node will stay where it is, but it's contents
+            // will be replaced by it's in-order successor's contents. The successor
+            // node will then be erased. Find the successor.
+            erasure = node->right;
+            while (erasure->left != &m_nil) {
+                erasure = erasure->left;
+            }
+        }
+
+        // Select the child node which will replace the node to be erased.
+        if (erasure->left != &m_nil) {
+            child = erasure->left;
+        }
+        else {
+            child = erasure->right;
+        }
+
+        // Replace the node to be erased with the selected child.
+        child->parent = erasure->parent;
+        if (child->parent == &m_nil) {
+            // The root of the tree is being erased. The child becomes root.
+            m_root = child;
+        }
+        else {
+            if (erasure == erasure->parent->left) {
+                erasure->parent->left = child;
+            }
+            else {
+                erasure->parent->right = child;
+            }
+        }
+
+        if (erasure != node) {
+            // The node being erased from the tree is the successor of the actual
+            // node to be erased. Replace the contents of the node to be erased
+            // with the successor's contents.
+            node->key  = erasure->key;
+        }
+
+        if (erasure->color == black) {
+            // The node being erased from the tree is black. Restructuring of the
+            // tree may be needed so that black-height is maintained.
+            cur = child;
+            while ((cur != m_root) && (cur->color == black)) {
+                if (cur == cur->parent->left) {
+                    // Current node is a left child.
+                    sibling = cur->parent->right;
+                    if (sibling->color == red) {
+                        // Sibling is red. Rotate sibling up and color it black.
+                        sibling->color = black;
+                        cur->parent->color = red;
+                        _rotateleft(cur->parent);
+                        sibling = cur->parent->right;
+                    }
+                    if ((sibling->left->color == black) && (sibling->right->color == black)) {
+                        // Both of sibling's children are black. Color sibling red.
+                        sibling->color = red;
+                        cur = cur->parent;
+                    }
+                    else {
+                        // At least one of sibling's children is red.
+                        if (sibling->right->color == black) {
+                            sibling->left->color = black;
+                            sibling->color = red;
+                            _rotateright(sibling);
+                            sibling = cur->parent->right;
+                        }
+                        sibling->color = cur->parent->color;
+                        cur->parent->color = black;
+                        sibling->right->color = black;
+                        _rotateleft(cur->parent);
+                        cur = m_root;
+                    }
+                }
+                else {
+                    // Current node is a right child.
+                    sibling = cur->parent->left;
+                    if (sibling->color == red) {
+                        // Sibling is red. Rotate sibling up and color it black.
+                        sibling->color = black;
+                        cur->parent->color = red;
+                        _rotateright(cur->parent);
+                        sibling = cur->parent->left;
+                    }
+                    if ((sibling->left->color == black) && (sibling->right->color == black)) {
+                        // Both of sibling's children are black. Color sibling red.
+                        sibling->color = red;
+                        cur = cur->parent;
+                    }
+                    else {
+                        // At least one of sibling's children is red.
+                        if (sibling->left->color == black) {
+                            sibling->right->color = black;
+                            sibling->color = red;
+                            _rotateleft(sibling);
+                            sibling = cur->parent->left;
+                        }
+                        sibling->color = cur->parent->color;
+                        cur->parent->color = black;
+                        sibling->left->color = black;
+                        _rotateright(cur->parent);
+                        cur = m_root;
+                    }
+                }
+            }
+            cur->color = black;
+        }
+
+        // Put the erased node onto the free list.
+        erasure->next = m_freelist;
+        m_freelist = erasure;
+
+        LeaveCriticalSection(&m_lock);
+    }
+
+    // erase - Erases the specified key from the tree. Note that this does
+    //   not cause the key associated with the erased node to be freed. The
+    //   caller is responsible for freeing any dynamically allocated memory
+    //   associated with the key.
+    //
+    //  - key (IN): The key to erase from the tree. This value is treated as
+    //      the key for sorting within the tree. It must therefore be of a type
+    //      which supports the "<" operator.
+    //
+    //  Return Value:
+    //
+    //    None.
+    //
+    VOID erase (const T &key)
+    {
+        node_t *node;
+
+        // Find the node to erase.
+        EnterCriticalSection(&m_lock);
+        node = m_root;
+        while (node != &m_nil) {
+            if (node->key < key) {
+                // Go right.
+                node = node->right;
+            }
+            else if (key < node->key) {
+                // Go left.
+                node = node->left;
+            }
+            else {
+                // Found it.
+                erase(node);
+                LeaveCriticalSection(&m_lock);
+                return;
+            }
+        }
+        LeaveCriticalSection(&m_lock);
+
+        // 'key' is not in the tree.
+        return;
+    }
+
+    // find - Obtains a pointer to the node corresponding to the specified key.
+    //
+    //  - key (IN): The value to search for in the tree. This value is treated
+    //      as the key for sorting within the tree. It must therefore be of a
+    //      type which supports the "<" operator.
+    //
+    //  Return Value:
+    //
+    //    Returns a pointer to the node corresponding to the specified key. If
+    //    the key is not in the tree, then "find" returns NULL.
+    //
+    typename Tree::node_t* find (const T &key) const
+    {
+        node_t *cur;
+        
+        EnterCriticalSection(&m_lock);
+        cur = m_root;
+        while (cur != &m_nil) {
+            if (cur->key < key) {
+                // Go right.
+                cur = cur->right;
+            }
+            else if (key < cur->key) {
+                // Go left.
+                cur = cur->left;
+            }
+            else {
+                // Found it.
+                LeaveCriticalSection(&m_lock);
+                return cur;
+            }
+        }
+        LeaveCriticalSection(&m_lock);
+
+        // 'key' is not in the tree.
+        return NULL;
+    }
+
+    // insert - Inserts a new key into the tree.
+    //
+    //  - key (IN): The key to insert into the tree. This value is treated as
+    //      the key for sorting within the tree. It must therefore be of a type
+    //      which supports the "<" operator.
+    //
+    //  Return Value:
+    //
+    //    Returns a pointer to the node corresponding to the newly inserted
+    //    key. If an attempt is made to insert a key which is already in the
+    //    tree, then NULL is returned and the new key is not inserted.
+    //
+    typename Tree::node_t* insert (const T &key)
+    {
+        node_t  *cur;
+        node_t  *node;
+        node_t  *parent;
+        node_t  *uncle;
+
+        EnterCriticalSection(&m_lock);
+
+        // Find the location where the new node should be inserted..
+        cur = m_root;
+        parent = &m_nil;
+        while (cur != &m_nil) {
+            parent = cur;
+            if (cur->key < key) {
+                // Go right.
+                cur = cur->right;
+            }
+            else if (key < cur->key) {
+                // Go left.
+                cur = cur->left;
+            }
+            else {
+                // Keys in the tree must be unique.
+                LeaveCriticalSection(&m_lock);
+                return NULL;
+            }
+        }
+
+        // Obtain a new node from the free list.
+        if (m_freelist == NULL) {
+            // Allocate additional storage.
+            reserve(m_reserve);
+        }
+        node = m_freelist;
+        m_freelist = m_freelist->next;
+
+        // Initialize the new node and insert it.
+        node->color  = red;
+        node->key    = key;
+        node->left   = &m_nil;
+        node->parent = parent;
+        node->right  = &m_nil;
+        if (parent == &m_nil) {
+            // The tree is empty. The new node becomes root.
+            m_root = node;
+        }
+        else {
+            if (parent->key < key) {
+                // New node is a right child.
+                parent->right = node;
+            }
+            else {
+                // New node is a left child.
+                parent->left = node;
+            }
+        }
+
+        // Rebalance and/or adjust the tree, if necessary.
+        cur = node;
+        while (cur->parent->color == red) {
+            // Double-red violation. Rebalancing/adjustment needed.
+            if (cur->parent == cur->parent->parent->left) {
+                // Parent is the left child. Uncle is the right child.
+                uncle = cur->parent->parent->right;
+                if (uncle->color == red) {
+                    // Uncle is red. Recolor.
+                    cur->parent->parent->color = red;
+                    cur->parent->color = black;
+                    uncle->color = black;
+                    cur = cur->parent->parent;
+                }
+                else {
+                    // Uncle is black. Restructure.
+                    if (cur == cur->parent->right) {
+                        cur = cur->parent;
+                        _rotateleft(cur);
+                    }
+                    cur->parent->color = black;
+                    cur->parent->parent->color = red;
+                    _rotateright(cur->parent->parent);
+                }
+            }
+            else {
+                // Parent is the right child. Uncle is the left child.
+                uncle = cur->parent->parent->left;
+                if (uncle->color == red) {
+                    // Uncle is red. Recolor.
+                    cur->parent->parent->color = red;
+                    cur->parent->color = black;
+                    uncle->color = black;
+                    cur = cur->parent->parent;
+                }
+                else {
+                    // Uncle is black. Restructure.
+                    if (cur == cur->parent->left) {
+                        cur = cur->parent;
+                        _rotateright(cur);
+                    }
+                    cur->parent->color = black;
+                    cur->parent->parent->color = red;
+                    _rotateleft(cur->parent->parent);
+                }
+            }
+        }
+
+        // The root node is always colored black.
+        m_root->color = black;
+
+        LeaveCriticalSection(&m_lock);
+
+        return node;        
+    }
+
+    // next - Obtains a pointer to the in-order successor of the specified
+    //   node.
+    //
+    //  - node (IN): Pointer to the node whose in-order successor to retrieve.
+    //
+    //  Return Value:
+    //
+    //    Returns a pointer to the node's in-order successor. If the specified
+    //    node corresponds to the largest value in the tree, then the specified
+    //    node has no successor and "next" will return NULL.
+    //
+    typename Tree::node_t* next (typename Tree::node_t *node) const
+    {
+        node_t* cur;
+
+        if (node == NULL) {
+            return NULL;
+        }
+
+        EnterCriticalSection(&m_lock);
+        if (node->right != &m_nil) {
+            // 'node' has a right child. Successor is the far left node in
+            // the right subtree.
+            cur = node->right;
+            while (cur->left != &m_nil) {
+                cur = cur->left;
+            }
+            LeaveCriticalSection(&m_lock);
+            return cur;
+        }
+        else if (node->parent != &m_nil) {
+            // 'node' has no right child, but does have a parent.
+            if (node == node->parent->left) {
+                // 'node' is a left child; node's parent is successor.
+                LeaveCriticalSection(&m_lock);
+                return node->parent;
+            }
+            else {
+                // 'node' is a right child.
+                cur = node;
+                // Go up the tree until we find a parent to the right.
+                while (cur->parent != &m_nil) {
+                    if (cur == cur->parent->right) {
+                        cur = cur->parent;
+                        continue;
+                    }
+                    else {
+                        LeaveCriticalSection(&m_lock);
+                        return cur->parent;
+                    }
+                }
+
+                // There is no parent greater than 'node'. 'node' is the
+                // maximum node.
+                LeaveCriticalSection(&m_lock);
+                return NULL;
+            }
+        }
+        else {
+            // 'node' is root and root is the maximum node.
+            LeaveCriticalSection(&m_lock);
+            return NULL;
+        }
+    }
+
+    // prev - Obtains a pointer to the in-order predecessor of the specified
+    //   node.
+    //
+    //  - node (IN): Pointer to the node whose in-order predecessor to retrieve.
+    //
+    //  Return Value:
+    //
+    //    Returns a pointer to the node's in-order predecessor. If the specified
+    //    node corresponds to the smallest value in the tree, then the specified
+    //    node has no predecessor and "prev" will return NULL.
+    //
+    typename Tree::node_t* prev (typename Tree::node_t *node) const
+    {
+        node_t* cur;
+
+        if (node == NULL) {
+            return NULL;
+        }
+
+        EnterCriticalSection(&m_lock);
+        if (node->left != &m_nil) {
+            // 'node' has left child. Predecessor is the far right node in the
+            // left subtree.
+            cur = node->left;
+            while (cur->right != &m_nil) {
+                cur = cur->right;
+            }
+            LeaveCriticalSection(&m_lock);
+            return cur;
+        }
+        else if (node->parent != & m_nil) {
+            // 'node' has no left child, but does have a parent.
+            if (node == node->parent->right) {
+                // 'node' is a right child; node's parent is predecessor.
+                LeaveCriticalSection(&m_lock);
+                return node->parent;
+            }
+            else {
+                // 'node is a left child.
+                cur = node;
+                // Go up the tree until we find a parent to the left.
+                while (cur->parent != &m_nil) {
+                    if (cur == cur->parent->left) {
+                        cur = cur->parent;
+                        continue;
+                    }
+                    else {
+                        LeaveCriticalSection(&m_lock);
+                        return cur->parent;
+                    }
+                }
+
+                // There is no parent less than 'node'. 'node' is the minimum
+                // node.
+                LeaveCriticalSection(&m_lock);
+                return NULL;
+            }
+        }
+        else {
+            // 'node' is root and root is the minimum node.
+            LeaveCriticalSection(&m_lock);
+            return NULL;
+        }
+    }
+
+    // reserve - Reserves storage for a number of nodes in advance and/or sets
+    //   the number of nodes for which the tree will automatically reserve
+    //   storage when the tree needs to "grow" to accomodate new values being
+    //   inserted into the tree. If this function is not called to set the
+    //   reserve size to a specific value, then a pre-determined default value
+    //   will be used. If this function is called when the tree currently has
+    //   no reserve storage, then in addition to setting the tree's reserve
+    //   value, it will also cause the tree to immediately reserve the
+    //   specified amount of storage.
+    //
+    //  - count (IN): The number of individual nodes' worth of storage to
+    //      reserve.
+    //
+    //  Return Value:
+    //
+    //    Returns the previously defined reserve value.
+    //
+    UINT32 reserve (UINT32 count)
+    {
+        chunk_t *chunk;
+        UINT32   index;
+        UINT32   oldreserve = m_reserve;
+
+        if (count != m_reserve) {
+            if (count < 1) {
+                // Minimum reserve size is 1.
+                m_reserve = 1;
+            }
+            else {
+                m_reserve = count;
+            }
+        }
+
+        EnterCriticalSection(&m_lock);
+        if (m_freelist == NULL) {
+            // Allocate additional storage.
+            // Link a new chunk into the chunk list.
+            chunk = new Tree::chunk_t;
+            chunk->nodes = new Tree::node_s [m_reserve];
+            chunk->next = NULL;
+            if (m_store == NULL) {
+                m_store = chunk;
+            }
+            else {
+                m_storetail->next = chunk;
+            }
+            m_storetail = chunk;
+
+            // Link the individual nodes together to form a new free list.
+            for (index = 0; index < m_reserve - 1; index++) {
+                chunk->nodes[index].next = &chunk->nodes[index + 1];
+            }
+            chunk->nodes[index].next = NULL;
+            m_freelist = chunk->nodes;
+        }
+        LeaveCriticalSection(&m_lock);
+
+        return oldreserve;
+    }
+
+private:
+    // _rotateleft: Rotates a pair of nodes counter-clockwise so that the parent
+    //   node becomes the left child and the right child becomes the parent.
+    //
+    //  - parent (IN): Pointer to the parent to rotate about.
+    //
+    //  Return Value:
+    //
+    //    None.
+    //
+    VOID _rotateleft (typename Tree::node_t *parent)
+    {
+        node_t *child = parent->right;
+
+        // Reassign the child's left subtree to the parent.
+        parent->right = child->left;
+        if (child->left != &m_nil) {
+            child->left->parent = parent;
+        }
+
+        // Reassign the child/parent relationship.
+        child->parent = parent->parent;
+        if (parent->parent == &m_nil) {
+            // The child becomes the new root node.
+            m_root = child;
+        }
+        else {
+            // Point the grandparent at the child.
+            if (parent == parent->parent->left) {
+                parent->parent->left = child;
+            }
+            else {
+                parent->parent->right = child;
+            }
+        }
+        child->left = parent;
+        parent->parent = child;
+    }
+
+    // _rotateright - Rotates a pair of nodes clockwise so that the parent node
+    //   becomes the right child and the left child becomes the parent.
+    //
+    //  - parent (IN): Pointer to the parent to rotate about.
+    //
+    //  Return Value:
+    //
+    //    None.
+    //
+    VOID _rotateright (typename Tree::node_t *parent)
+    {
+        node_t *child = parent->left;
+
+        // Reassign the child's right subtree to the parent.
+        parent->left = child->right;
+        if (child->right != &m_nil) {
+            child->right->parent = parent;
+        }
+
+        // Reassign the child/parent relationship.
+        child->parent = parent->parent;
+        if (parent->parent == &m_nil) {
+            // The child becomes the new root node.
+            m_root = child;
+        }
+        else {
+            // Point the grandparent at the child.
+            if (parent == parent->parent->left) {
+                parent->parent->left = child;
+            }
+            else {
+                parent->parent->right = child;
+            }
+        }
+        child->right = parent;
+        parent->parent = child;
+    }
+
+    // Private data members.
+    node_t                   *m_freelist;  // Pointer to the list of free nodes (reserve storage).
+    mutable CRITICAL_SECTION  m_lock;      // Protects the tree's integrity against concurrent accesses.
+    node_t                    m_nil;       // The tree's nil node. All leaf nodes point to this.
+    UINT32                    m_reserve;   // The size (in nodes) of the chunks of reserve storage.
+    node_t                   *m_root;      // Pointer to the tree's root node.
+    chunk_t                  *m_store;     // Pointer to the start of the chunk list.
+    chunk_t                  *m_storetail; // Pointer to the end of the chunk list.
+};
diff --git a/development/Win32/vld/src/utility.cpp b/development/Win32/vld/src/utility.cpp
new file mode 100644 (file)
index 0000000..e2fbddd
--- /dev/null
@@ -0,0 +1,781 @@
+////////////////////////////////////////////////////////////////////////////////
+//  $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
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#include <cassert>
+#include <cstdio>
+#include <windows.h>
+#define __out_xcount(x) // Workaround for the specstrings.h bug in the Platform SDK.
+#define DBGHELP_TRANSLATE_TCHAR
+#include <dbghelp.h>    // Provides portable executable (PE) image access functions.
+#define VLDBUILD        // Declares that we are building Visual Leak Detector.
+#include "utility.h"    // Provides various utility functions and macros.
+#include "vldheap.h"    // Provides internal new and delete operators.
+
+// Imported Global Variables
+extern CRITICAL_SECTION imagelock;
+
+// Global variables.
+static BOOL        reportdelay = FALSE;     // If TRUE, we sleep for a bit after calling OutputDebugString to give the debugger time to catch up.
+static FILE       *reportfile = NULL;       // Pointer to the file, if any, to send the memory leak report to.
+static BOOL        reporttodebugger = TRUE; // If TRUE, a copy of the memory leak report will be sent to the debugger for display.
+static encoding_e  reportencoding = ascii;  // Output encoding of the memory leak report.
+
+// dumpmemorya - Dumps a nicely formatted rendition of a region of memory.
+//   Includes both the hex value of each byte and its ASCII equivalent (if
+//   printable).
+//
+//  - address (IN): Pointer to the beginning of the memory region to dump.
+//
+//  - size (IN): The size, in bytes, of the region to dump.
+//
+//  Return Value:
+//
+//    None.
+//
+VOID dumpmemorya (LPCVOID address, SIZE_T size)
+{
+    WCHAR  ascdump [18] = {0};
+    SIZE_T ascindex;
+    BYTE   byte;
+    SIZE_T byteindex;
+    SIZE_T bytesdone;
+    SIZE_T dumplen;
+    WCHAR  formatbuf [BYTEFORMATBUFFERLENGTH];
+    WCHAR  hexdump [HEXDUMPLINELENGTH] = {0};
+    SIZE_T hexindex;
+
+    // Each line of output is 16 bytes.
+    if ((size % 16) == 0) {
+        // No padding needed.
+        dumplen = size;
+    }
+    else {
+        // We'll need to pad the last line out to 16 bytes.
+        dumplen = size + (16 - (size % 16));
+    }
+
+    // For each byte of data, get both the ASCII equivalent (if it is a
+    // printable character) and the hex representation.
+    bytesdone = 0;
+    for (byteindex = 0; byteindex < dumplen; byteindex++) {
+        hexindex = 3 * ((byteindex % 16) + ((byteindex % 16) / 4)); // 3 characters per byte, plus a 3-character space after every 4 bytes.
+        ascindex = (byteindex % 16) + (byteindex % 16) / 8;         // 1 character per byte, plus a 1-character space after every 8 bytes.
+        if (byteindex < size) {
+            byte = ((PBYTE)address)[byteindex];
+            _snwprintf_s(formatbuf, BYTEFORMATBUFFERLENGTH, _TRUNCATE, L"%.2X ", byte);
+            formatbuf[3] = '\0';
+            wcsncpy_s(hexdump + hexindex, HEXDUMPLINELENGTH - hexindex, formatbuf, 4);
+            if (isgraph(byte)) {
+                ascdump[ascindex] = (WCHAR)byte;
+            }
+            else {
+                ascdump[ascindex] = L'.';
+            }
+        }
+        else {
+            // Add padding to fill out the last line to 16 bytes.
+            wcsncpy_s(hexdump + hexindex, HEXDUMPLINELENGTH - hexindex, L"   ", 4);
+            ascdump[ascindex] = L'.';
+        }
+        bytesdone++;
+        if ((bytesdone % 16) == 0) {
+            // Print one line of data for every 16 bytes. Include the
+            // ASCII dump and the hex dump side-by-side.
+            report(L"    %s    %s\n", hexdump, ascdump);
+        }
+        else {
+            if ((bytesdone % 8) == 0) {
+                // Add a spacer in the ASCII dump after every 8 bytes.
+                ascdump[ascindex + 1] = L' ';
+            }
+            if ((bytesdone % 4) == 0) {
+                // Add a spacer in the hex dump after every 4 bytes.
+                wcsncpy_s(hexdump + hexindex + 3, HEXDUMPLINELENGTH - hexindex - 3, L"   ", 4);
+            }
+        }
+    }
+}
+
+// dumpmemoryw - Dumps a nicely formatted rendition of a region of memory.
+//   Includes both the hex value of each byte and its Unicode equivalent.
+//
+//  - address (IN): Pointer to the beginning of the memory region to dump.
+//
+//  - size (IN): The size, in bytes, of the region to dump.
+//
+//  Return Value:
+//
+//    None.
+//
+VOID dumpmemoryw (LPCVOID address, SIZE_T size)
+{
+    BYTE   byte;
+    SIZE_T byteindex;
+    SIZE_T bytesdone;
+    SIZE_T dumplen;
+    WCHAR  formatbuf [BYTEFORMATBUFFERLENGTH];
+    WCHAR  hexdump [HEXDUMPLINELENGTH] = {0};
+    SIZE_T hexindex;
+    WORD   word;
+    WCHAR  unidump [18] = {0};
+    SIZE_T uniindex;
+
+    // Each line of output is 16 bytes.
+    if ((size % 16) == 0) {
+        // No padding needed.
+        dumplen = size;
+    }
+    else {
+        // We'll need to pad the last line out to 16 bytes.
+        dumplen = size + (16 - (size % 16));
+    }
+
+    // For each word of data, get both the Unicode equivalent and the hex
+    // representation.
+    bytesdone = 0;
+    for (byteindex = 0; byteindex < dumplen; byteindex++) {
+        hexindex = 3 * ((byteindex % 16) + ((byteindex % 16) / 4));   // 3 characters per byte, plus a 3-character space after every 4 bytes.
+        uniindex = ((byteindex / 2) % 8) + ((byteindex / 2) % 8) / 8; // 1 character every other byte, plus a 1-character space after every 8 bytes.
+        if (byteindex < size) {
+            byte = ((PBYTE)address)[byteindex];
+            _snwprintf_s(formatbuf, BYTEFORMATBUFFERLENGTH, _TRUNCATE, L"%.2X ", byte);
+            formatbuf[BYTEFORMATBUFFERLENGTH - 1] = '\0';
+            wcsncpy_s(hexdump + hexindex, HEXDUMPLINELENGTH - hexindex, formatbuf, 4);
+            if (((byteindex % 2) == 0) && ((byteindex + 1) < dumplen)) {
+                // On every even byte, print one character.
+                word = ((PWORD)address)[byteindex / 2];
+                if ((word == 0x0000) || (word == 0x0020)) {
+                    unidump[uniindex] = L'.';
+                }
+                else {
+                    unidump[uniindex] = word;
+                }
+            }
+        }
+        else {
+            // Add padding to fill out the last line to 16 bytes.
+            wcsncpy_s(hexdump + hexindex, HEXDUMPLINELENGTH - hexindex, L"   ", 4);
+            unidump[uniindex] = L'.';
+        }
+        bytesdone++;
+        if ((bytesdone % 16) == 0) {
+            // Print one line of data for every 16 bytes. Include the
+            // ASCII dump and the hex dump side-by-side.
+            report(L"    %s    %s\n", hexdump, unidump);
+        }
+        else {
+            if ((bytesdone % 8) == 0) {
+                // Add a spacer in the ASCII dump after every 8 bytes.
+                unidump[uniindex + 1] = L' ';
+            }
+            if ((bytesdone % 4) == 0) {
+                // Add a spacer in the hex dump after every 4 bytes.
+                wcsncpy_s(hexdump + hexindex + 3, HEXDUMPLINELENGTH - hexindex - 3, L"   ", 4);
+            }
+        }
+    }
+}
+
+// findimport - Determines if the specified module imports the named import
+//   from the named exporting module.
+//
+//  - importmodule (IN): Handle (base address) of the module to be searched to
+//      see if it imports the specified import.
+//
+//  - exportmodule (IN): Handle (base address) of the module that exports the
+//      import to be searched for.
+//
+//  - exportmodulename (IN): ANSI string containing the name of the module that
+//      exports the import to be searched for.
+//
+//  - importname (IN): ANSI string containing the name of the import to search
+//      for. May be an integer cast to a string if the import is exported by
+//      ordinal.
+//
+//  Return Value:
+//
+//    Returns TRUE if the module imports to the specified import. Otherwise
+//    returns FALSE.
+//
+BOOL findimport (HMODULE importmodule, HMODULE exportmodule, LPCSTR exportmodulename, LPCSTR importname)
+{
+    IMAGE_THUNK_DATA        *iate;
+    IMAGE_IMPORT_DESCRIPTOR *idte;
+    FARPROC                  import;
+    IMAGE_SECTION_HEADER    *section;
+    ULONG                    size;
+            
+    // Locate the importing module's Import Directory Table (IDT) entry for the
+    // exporting module. The importing module actually can have several IATs --
+    // one for each export module that it imports something from. The IDT entry
+    // gives us the offset of the IAT for the module we are interested in.
+    EnterCriticalSection(&imagelock);
+    idte = (IMAGE_IMPORT_DESCRIPTOR*)ImageDirectoryEntryToDataEx((PVOID)importmodule, TRUE,
+                                                                  IMAGE_DIRECTORY_ENTRY_IMPORT, &size, &section);
+    LeaveCriticalSection(&imagelock);
+    if (idte == NULL) {
+        // This module has no IDT (i.e. it imports nothing).
+        return FALSE;
+    }
+    while (idte->OriginalFirstThunk != 0x0) {
+        if (_stricmp((PCHAR)R2VA(importmodule, idte->Name), exportmodulename) == 0) {
+            // Found the IDT entry for the exporting module.
+            break;
+        }
+        idte++;
+    }
+    if (idte->OriginalFirstThunk == 0x0) {
+        // The importing module does not import anything from the exporting
+        // module.
+        return FALSE;
+    }
+    
+    // Get the *real* address of the import. If we find this address in the IAT,
+    // then we've found that the module does import the named import.
+    import = GetProcAddress(exportmodule, importname);
+    assert(import != NULL); // Perhaps the named export module does not actually export the named import?
+
+    // Locate the import's IAT entry.
+    iate = (IMAGE_THUNK_DATA*)R2VA(importmodule, idte->FirstThunk);
+    while (iate->u1.Function != 0x0) {
+        if (iate->u1.Function == (DWORD_PTR)import) {
+            // Found the IAT entry. The module imports the named import.
+            return TRUE;
+        }
+        iate++;
+    }
+
+    // The module does not import the named import.
+    return FALSE;
+}
+
+// findpatch - Determines if the specified module has been patched to use the
+//   specified replacement.
+//
+//  - importmodule (IN): Handle (base address) of the module to be searched to
+//      see if it imports the specified replacement export.
+//
+//  - exportmodulename (IN): ANSI string containing the name of the module that
+//      normally exports that import that would have been patched to use the
+//      replacement export.
+//
+//  - replacement (IN): Address of the replacement, or destination, function or
+//      variable to search for.
+//
+//  Return Value:
+//
+//    Returns TRUE if the module has been patched to use the specified
+//    replacement export.
+//
+BOOL findpatch (HMODULE importmodule, LPCSTR exportmodulename, LPCVOID replacement)
+{
+    IMAGE_THUNK_DATA        *iate;
+    IMAGE_IMPORT_DESCRIPTOR *idte;
+    IMAGE_SECTION_HEADER    *section;
+    ULONG                    size;
+            
+    // Locate the importing module's Import Directory Table (IDT) entry for the
+    // exporting module. The importing module actually can have several IATs --
+    // one for each export module that it imports something from. The IDT entry
+    // gives us the offset of the IAT for the module we are interested in.
+    EnterCriticalSection(&imagelock);
+    idte = (IMAGE_IMPORT_DESCRIPTOR*)ImageDirectoryEntryToDataEx((PVOID)importmodule, TRUE,
+                                                                  IMAGE_DIRECTORY_ENTRY_IMPORT, &size, &section);
+    LeaveCriticalSection(&imagelock);
+    if (idte == NULL) {
+        // This module has no IDT (i.e. it imports nothing).
+        return FALSE;
+    }
+    while (idte->OriginalFirstThunk != 0x0) {
+        if (_stricmp((PCHAR)R2VA(importmodule, idte->Name), exportmodulename) == 0) {
+            // Found the IDT entry for the exporting module.
+            break;
+        }
+        idte++;
+    }
+    if (idte->OriginalFirstThunk == 0x0) {
+        // The importing module does not import anything from the exporting
+        // module.
+        return FALSE;
+    }
+    
+    // Locate the replacement's IAT entry.
+    iate = (IMAGE_THUNK_DATA*)R2VA(importmodule, idte->FirstThunk);
+    while (iate->u1.Function != 0x0) {
+        if (iate->u1.Function == (DWORD_PTR)replacement) {
+            // Found the IAT entry for the replacement. This patch has been
+            // installed.
+            return TRUE;
+        }
+        iate++;
+    }
+
+    // The module does not import the replacement. The patch has not been
+    // installed.
+    return FALSE;
+}
+
+// insertreportdelay - Sets the report function to sleep for a bit after each
+//   call to OutputDebugString, in order to allow the debugger to catch up.
+//
+//  Return Value:
+//
+//    None.
+//
+VOID insertreportdelay ()
+{
+    reportdelay = TRUE;
+}
+
+// moduleispatched - Checks to see if any of the imports listed in the specified
+//   patch table have been patched into the specified importmodule.
+//
+//  - importmodule (IN): Handle (base address) of the module to be queried to
+//      determine if it has been patched.
+//
+//  - patchtable (IN): An array of patchentry_t structures specifying all of the
+//      import patches to search for.
+//
+//  - tablesize (IN): Size, in entries, of the specified patch table.
+//
+//  Return Value:
+//
+//    Returns TRUE if at least one of the patches listed in the patch table is
+//    installed in the importmodule. Otherwise returns FALSE.
+//
+BOOL moduleispatched (HMODULE importmodule, patchentry_t patchtable [], UINT tablesize)
+{
+    patchentry_t *entry;
+    BOOL          found = FALSE;
+    UINT          index;
+
+    // Loop through the import patch table, individually checking each patch
+    // entry to see if it is installed in the import module. If any patch entry
+    // is installed in the import module, then the module has been patched.
+    for (index = 0; index < tablesize; index++) {
+        entry = &patchtable[index];
+        found = findpatch(importmodule, entry->exportmodulename, entry->replacement);
+        if (found == TRUE) {
+            // Found one of the listed patches installed in the import module.
+            return TRUE;
+        }
+    }
+
+    // No patches listed in the patch table were found in the import module.
+    return FALSE;
+}
+
+// patchimport - Patches all future calls to an imported function, or references
+//   to an imported variable, through to a replacement function or variable.
+//   Patching is done by replacing the import's address in the specified target
+//   module's Import Address Table (IAT) with the address of the replacement
+//   function or variable.
+//
+//  - importmodule (IN): Handle (base address) of the target module for which
+//      calls or references to the import should be patched.
+//
+//  - exportmodule (IN): Handle (base address) of the module that exports the
+//      the function or variable to be patched.
+//
+//  - exportmodulename (IN): ANSI string containing the name of the module that
+//      exports the function or variable to be patched.
+//
+//  - importname (IN): ANSI string containing the name of the imported function
+//      or variable to be patched. May be an integer cast to a string if the
+//      import is exported by ordinal.
+//
+//  - replacement (IN): Address of the function or variable to which future
+//      calls or references should be patched through to. This function or
+//      variable can be thought of as effectively replacing the original import
+//      from the point of view of the module specified by "importmodule".
+//
+//  Return Value:
+//
+//    Returns TRUE if the patch was installed into the import module. If the
+//    import module does not import the specified export, so nothing changed,
+//    then FALSE will be returned.
+//   
+BOOL patchimport (HMODULE importmodule, HMODULE exportmodule, LPCSTR exportmodulename, LPCSTR importname,
+                  LPCVOID replacement)
+{
+    IMAGE_THUNK_DATA        *iate;
+    IMAGE_IMPORT_DESCRIPTOR *idte;
+    FARPROC                  import;
+    DWORD                    protect;
+    IMAGE_SECTION_HEADER    *section;
+    ULONG                    size;
+
+    // Locate the importing module's Import Directory Table (IDT) entry for the
+    // exporting module. The importing module actually can have several IATs --
+    // one for each export module that it imports something from. The IDT entry
+    // gives us the offset of the IAT for the module we are interested in.
+    EnterCriticalSection(&imagelock);
+    idte = (IMAGE_IMPORT_DESCRIPTOR*)ImageDirectoryEntryToDataEx((PVOID)importmodule, TRUE,
+                                                                  IMAGE_DIRECTORY_ENTRY_IMPORT, &size, &section);
+    LeaveCriticalSection(&imagelock);
+    if (idte == NULL) {
+        // This module has no IDT (i.e. it imports nothing).
+        return FALSE;
+    }
+    while (idte->OriginalFirstThunk != 0x0) {
+        if (_stricmp((PCHAR)R2VA(importmodule, idte->Name), exportmodulename) == 0) {
+            // Found the IDT entry for the exporting module.
+            break;
+        }
+        idte++;
+    }
+    if (idte->OriginalFirstThunk == 0x0) {
+        // The importing module does not import anything from the exporting
+        // module.
+        return FALSE;
+    }
+    
+    // Get the *real* address of the import. If we find this address in the IAT,
+    // then we've found the entry that needs to be patched.
+    import = GetProcAddress(exportmodule, importname);
+    assert(import != NULL); // Perhaps the named export module does not actually export the named import?
+
+    // Locate the import's IAT entry.
+    iate = (IMAGE_THUNK_DATA*)R2VA(importmodule, idte->FirstThunk);
+    while (iate->u1.Function != 0x0) {
+        if (iate->u1.Function == (DWORD_PTR)import) {
+            // Found the IAT entry. Overwrite the address stored in the IAT
+            // entry with the address of the replacement. Note that the IAT
+            // entry may be write-protected, so we must first ensure that it is
+            // writable.
+            VirtualProtect(&iate->u1.Function, sizeof(iate->u1.Function), PAGE_READWRITE, &protect);
+            iate->u1.Function = (DWORD_PTR)replacement;
+            VirtualProtect(&iate->u1.Function, sizeof(iate->u1.Function), protect, &protect);
+
+            // The patch has been installed in the import module.
+            return TRUE;
+        }
+        iate++;
+    }
+
+    // The import's IAT entry was not found. The importing module does not
+    // import the specified import.
+    return FALSE;
+}
+
+// patchmodule - Patches all imports listed in the supplied patch table, and
+//   which are imported by the specified module, through to their respective
+//   replacement functions.
+//
+//   Note: If the specified module does not import any of the functions listed
+//     in the patch table, then nothing is changed for the specified module.
+//
+//  - importmodule (IN): Handle (base address) of the target module which is to
+//      have its imports patched.
+//
+//  - patchtable (IN): An array of patchentry_t structures specifying all of the
+//      imports to patch for the specified module.
+//
+//  - tablesize (IN): Size, in entries, of the specified patch table.
+//
+//  Return Value:
+//
+//    Returns TRUE if at least one of the patches listed in the patch table was
+//    installed in the importmodule. Otherwise returns FALSE.
+//
+BOOL patchmodule (HMODULE importmodule, patchentry_t patchtable [], UINT tablesize)
+{
+    patchentry_t *entry;
+    UINT          index;
+    BOOL          patched = FALSE;
+
+    // Loop through the import patch table, individually patching each import
+    // listed in the table.
+    for (index = 0; index < tablesize; index++) {
+        entry = &patchtable[index];
+        if (patchimport(importmodule, (HMODULE)entry->modulebase, entry->exportmodulename, entry->importname,
+                        entry->replacement) == TRUE) {
+            patched = TRUE;
+        }
+    }
+
+    return patched;
+}
+
+// report - Sends a printf-style formatted message to the debugger for display
+//   and/or to a file.
+//
+//   Note: A message longer than MAXREPORTLENGTH characters will be truncated
+//     to MAXREPORTLENGTH.
+//
+//  - format (IN): Specifies a printf-compliant format string containing the
+//      message to be sent to the debugger.
+//
+//  - ... (IN): Arguments to be formatted using the specified format string.
+//
+//  Return Value:
+//
+//    None.
+//
+VOID report (LPCWSTR format, ...)
+{
+    va_list args;
+    size_t  count;
+    CHAR    messagea [MAXREPORTLENGTH + 1];
+    WCHAR   messagew [MAXREPORTLENGTH + 1];
+
+    va_start(args, format);
+    _vsnwprintf_s(messagew, MAXREPORTLENGTH + 1, _TRUNCATE, format, args);
+    va_end(args);
+    messagew[MAXREPORTLENGTH] = L'\0';
+
+    if (reportencoding == unicode) {
+        if (reportfile != NULL) {
+            // Send the report to the previously specified file.
+            fwrite(messagew, sizeof(WCHAR), wcslen(messagew), reportfile);
+        }
+        if (reporttodebugger) {
+            OutputDebugStringW(messagew);
+        }
+    }
+    else {
+        if (wcstombs_s(&count, messagea, MAXREPORTLENGTH + 1, messagew, _TRUNCATE) == -1) {
+            // Failed to convert the Unicode message to ASCII.
+            assert(FALSE);
+            return;
+        }
+        messagea[MAXREPORTLENGTH] = '\0';
+        if (reportfile != NULL) {
+            // Send the report to the previously specified file.
+            fwrite(messagea, sizeof(CHAR), strlen(messagea), reportfile);
+        }
+        if (reporttodebugger) {
+            OutputDebugStringA(messagea);
+        }
+    }
+
+    if (reporttodebugger && (reportdelay == TRUE)) {
+        Sleep(10); // Workaround the Visual Studio 6 bug where debug strings are sometimes lost if they're sent too fast.
+    }
+}
+
+// restoreimport - Restores the IAT entry for an import previously patched via
+//   a call to "patchimport" to the original address of the import.
+//
+//  - importmodule (IN): Handle (base address) of the target module for which
+//      calls or references to the import should be restored.
+//
+//  - exportmodule (IN): Handle (base address) of the module that exports the
+//      function or variable to be patched.
+//
+//  - exportmodulename (IN): ANSI string containing the name of the module that
+//      exports the function or variable to be patched.
+//
+//  - importname (IN): ANSI string containing the name of the imported function
+//      or variable to be restored. May be an integer cast to a string if the
+//      import is exported by ordinal.
+//
+//  - replacement (IN): Address of the function or variable which the import was
+//      previously patched through to via a call to "patchimport".
+//
+//  Return Value:
+//
+//    None.
+//   
+VOID restoreimport (HMODULE importmodule, HMODULE exportmodule, LPCSTR exportmodulename, LPCSTR importname,
+                    LPCVOID replacement)
+{
+    IMAGE_THUNK_DATA        *iate;
+    IMAGE_IMPORT_DESCRIPTOR *idte;
+    FARPROC                  import;
+    DWORD                    protect;
+    IMAGE_SECTION_HEADER    *section;
+    ULONG                    size;
+
+    // Locate the importing module's Import Directory Table (IDT) entry for the
+    // exporting module. The importing module actually can have several IATs --
+    // one for each export module that it imports something from. The IDT entry
+    // gives us the offset of the IAT for the module we are interested in.
+    EnterCriticalSection(&imagelock);
+    idte = (IMAGE_IMPORT_DESCRIPTOR*)ImageDirectoryEntryToDataEx((PVOID)importmodule, TRUE,
+                                                                  IMAGE_DIRECTORY_ENTRY_IMPORT, &size, &section);
+    LeaveCriticalSection(&imagelock);
+    if (idte == NULL) {
+        // This module has no IDT (i.e. it imports nothing).
+        return;
+    }
+    while (idte->OriginalFirstThunk != 0x0) {
+        if (_stricmp((PCHAR)R2VA(importmodule, idte->Name), exportmodulename) == 0) {
+            // Found the IDT entry for the exporting module.
+            break;
+        }
+        idte++;
+    }
+    if (idte->OriginalFirstThunk == 0x0) {
+        // The importing module does not import anything from the exporting
+        // module.
+        return;
+    }
+    
+    // Get the *real* address of the import.
+    import = GetProcAddress(exportmodule, importname);
+    assert(import != NULL); // Perhaps the named export module does not actually export the named import?
+
+    // Locate the import's original IAT entry (it currently has the replacement
+    // address in it).
+    iate = (IMAGE_THUNK_DATA*)R2VA(importmodule, idte->FirstThunk);
+    while (iate->u1.Function != 0x0) {
+        if (iate->u1.Function == (DWORD_PTR)replacement) {
+            // Found the IAT entry. Overwrite the address stored in the IAT
+            // entry with the import's real address. Note that the IAT entry may
+            // be write-protected, so we must first ensure that it is writable.
+            VirtualProtect(&iate->u1.Function, sizeof(iate->u1.Function), PAGE_READWRITE, &protect);
+            iate->u1.Function = (DWORD_PTR)import;
+            VirtualProtect(&iate->u1.Function, sizeof(iate->u1.Function), protect, &protect);
+            break;
+        }
+        iate++;
+    }
+}
+
+// restoremodule - Restores all imports listed in the supplied patch table, and
+//   which are imported by the specified module, to their original functions.
+//
+//   Note: If the specified module does not import any of the functions listed
+//     in the patch table, then nothing is changed for the specified module.
+//
+//  - importmodule (IN): Handle (base address) of the target module which is to
+//      have its imports restored.
+//
+//  - patchtable (IN): Array of patchentry_t structures specifying all of the
+//      imports to restore for the specified module.
+//
+//  - tablesize (IN): Size, in entries, of the specified patch table.
+//
+//  Return Value:
+//
+//    None.
+//
+VOID restoremodule (HMODULE importmodule, patchentry_t patchtable [], UINT tablesize)
+{
+    patchentry_t *entry;
+    UINT          index;
+
+    // Loop through the import patch table, individually restoring each import
+    // listed in the table.
+    for (index = 0; index < tablesize; index++) {
+        entry = &patchtable[index];
+        restoreimport(importmodule, (HMODULE)entry->modulebase, entry->exportmodulename, entry->importname,
+                      entry->replacement);
+    }
+}
+
+// setreportencoding - Sets the output encoding of report messages to either
+//   ASCII (the default) or Unicode.
+//
+//  - encoding (IN): Specifies either "ascii" or "unicode".
+//
+//  Return Value:
+//
+//    None.
+//
+VOID setreportencoding (encoding_e encoding)
+{
+    switch (encoding) {
+    case ascii:
+    case unicode:
+        reportencoding = encoding;
+        break;
+
+    default:
+        assert(FALSE);
+    }
+}
+
+// setreportfile - Sets a destination file to which all report messages should
+//   be sent. If this function is not called to set a destination file, then
+//   report messages will be sent to the debugger instead of to a file.
+//
+//  - file (IN): Pointer to an open file, to which future report messages should
+//      be sent.
+//
+//  - copydebugger (IN): If true, in addition to sending report messages to
+//      the specified file, a copy of each message will also be sent to the
+//      debugger.
+//
+//  Return Value:
+//
+//    None.
+//
+VOID setreportfile (FILE *file, BOOL copydebugger)
+{
+    reportfile = file;
+    reporttodebugger = copydebugger;
+}
+
+// strapp - Appends the specified source string to the specified destination
+//   string. Allocates additional space so that the destination string "grows"
+//   as new strings are appended to it. This function is fairly infrequently
+//   used so efficiency is not a major concern.
+//
+//  - dest (IN/OUT): Address of the destination string. Receives the resulting
+//      combined string after the append operation.
+//
+//  - source (IN): Source string to be appended to the destination string.
+//
+//  Return Value:
+//
+//    None.
+//
+VOID strapp (LPWSTR *dest, LPCWSTR source)
+{
+    SIZE_T length;
+    LPWSTR temp;
+
+    temp = *dest;
+    length = wcslen(*dest) + wcslen(source);
+    *dest = new WCHAR [length + 1];
+    wcsncpy_s(*dest, length + 1, temp, _TRUNCATE);
+    wcsncat_s(*dest, length + 1, source, _TRUNCATE);
+    delete [] temp;
+}
+
+// strtobool - Converts string values (e.g. "yes", "no", "on", "off") to boolean
+//   values.
+//
+//  - s (IN): String value to convert.
+//
+//  Return Value:
+//
+//    Returns TRUE if the string is recognized as a "true" string. Otherwise
+//    returns FALSE.
+//
+BOOL strtobool (LPCWSTR s) {
+    WCHAR *end;
+
+    if ((_wcsicmp(s, L"true") == 0) ||
+        (_wcsicmp(s, L"yes") == 0) ||
+        (_wcsicmp(s, L"on") == 0) ||
+        (wcstol(s, &end, 10) == 1)) {
+        return TRUE;
+    }
+    else {
+        return FALSE;
+    }
+}
diff --git a/development/Win32/vld/src/utility.h b/development/Win32/vld/src/utility.h
new file mode 100644 (file)
index 0000000..2c85b92
--- /dev/null
@@ -0,0 +1,109 @@
+////////////////////////////////////////////////////////////////////////////////
+//  $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
+//
+//  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
+
+#ifndef VLDBUILD
+#error \
+"This header should only be included by Visual Leak Detector when building it from source. \
+Applications should never include this header."
+#endif
+
+#include <cstdio>
+#include <windows.h>
+
+#ifdef _WIN64
+#define ADDRESSFORMAT   L"0x%.16X" // Format string for 64-bit addresses
+#else
+#define ADDRESSFORMAT   L"0x%.8X"  // Format string for 32-bit addresses
+#endif // _WIN64
+#define BOM             0xFEFF     // Unicode byte-order mark.
+#define MAXREPORTLENGTH 511        // Maximum length, in characters, of "report" messages.
+
+// Architecture-specific definitions for x86 and x64
+#if defined(_M_IX86)
+#define SIZEOFPTR 4
+#define X86X64ARCHITECTURE IMAGE_FILE_MACHINE_I386
+#define AXREG Eax
+#define BPREG Ebp
+#define IPREG Eip
+#define SPREG Esp
+#elif defined(_M_X64)
+#define SIZEOFPTR 8
+#define X86X64ARCHITECTURE IMAGE_FILE_MACHINE_AMD64
+#define AXREG Rax
+#define BPREG Rbp
+#define IPREG Rip
+#define SPREG Rsp
+#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.
+#else
+// If you want to retarget Visual Leak Detector to another processor
+// architecture then you'll need to provide an architecture-specific macro to
+// obtain the frame pointer (or other address) which can be used to obtain the
+// return address and stack pointer of the calling frame.
+#error "Visual Leak Detector is not supported on this architecture."
+#endif // _M_IX86 || _M_X64
+
+// Miscellaneous definitions
+#define R2VA(modulebase, rva)  (((PBYTE)modulebase) + rva) // Relative Virtual Address to Virtual Address conversion.
+#define BYTEFORMATBUFFERLENGTH 4
+#define HEXDUMPLINELENGTH      58
+
+// Reports can be encoded as either ASCII or Unicode (UTF-16).
+enum encoding_e {
+    ascii,
+    unicode
+};
+
+// This structure allows us to build a table of APIs which should be patched
+// through to replacement functions provided by VLD.
+typedef struct patchentry_s
+{
+    LPCSTR  exportmodulename; // The name of the module exporting the patched API.
+    LPCSTR  importname;       // The name (or ordinal) of the imported API being patched.
+    SIZE_T  modulebase;       // The base address of the exporting module (filled in at runtime when the modules are loaded).
+    LPCVOID replacement;      // Pointer to the function to which the imported API should be patched through to.
+} patchentry_t;
+
+// Utility functions. See function definitions for details.
+VOID dumpmemorya (LPCVOID address, SIZE_T length);
+VOID dumpmemoryw (LPCVOID address, SIZE_T length);
+BOOL findimport (HMODULE importmodule, HMODULE exportmodule, LPCSTR exportmodulename, LPCSTR importname);
+BOOL findpatch (HMODULE importmodule, LPCSTR exportmodulename, LPCVOID replacement);
+VOID insertreportdelay ();
+BOOL moduleispatched (HMODULE importmodule, patchentry_t patchtable [], UINT tablesize);
+BOOL patchimport (HMODULE importmodule, HMODULE exportmodule, LPCSTR exportmodulename, LPCSTR importname,
+                  LPCVOID replacement);
+BOOL patchmodule (HMODULE importmodule, patchentry_t patchtable [], UINT tablesize);
+VOID report (LPCWSTR format, ...);
+VOID restoreimport (HMODULE importmodule, HMODULE exportmodule, LPCSTR exportmodulename, LPCSTR importname,
+                    LPCVOID replacement);
+VOID restoremodule (HMODULE importmodule, patchentry_t patchtable [], UINT tablesize);
+VOID setreportencoding (encoding_e encoding);
+VOID setreportfile (FILE *file, BOOL copydebugger);
+VOID strapp (LPWSTR *dest, LPCWSTR source);
+BOOL strtobool (LPCWSTR s);
diff --git a/development/Win32/vld/src/vld.cpp b/development/Win32/vld/src/vld.cpp
new file mode 100644 (file)
index 0000000..ffaa43a
--- /dev/null
@@ -0,0 +1,3338 @@
+////////////////////////////////////////////////////////////////////////////////
+//  $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
+//
+//  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 comment(lib, "dbghelp.lib")
+
+#include <cassert>
+#include <cerrno>
+#include <cstdio>
+#include <sys/stat.h>
+#include <windows.h>
+#define __out_xcount(x) // Workaround for the specstrings.h bug in the Platform SDK.
+#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.
+
+#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.
+#define MAXSYMBOLNAMELENGTH 256 // Maximum symbol name length that we will allow. Longer names will be truncated.
+#define MODULESETRESERVE    16  // There are likely to be several modules loaded in the process.
+
+// Imported global variables.
+extern vldblockheader_t *vldblocklist;
+extern HANDLE            vldheap;
+extern CRITICAL_SECTION  vldheaplock;
+
+// Global variables.
+HANDLE           currentprocess; // Pseudo-handle for the current process.
+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);
+
+// 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
+// makes it more convenient to add additional IAT patches.
+patchentry_t VisualLeakDetector::m_patchtable [] = {
+    // Win32 heap APIs.
+    "kernel32.dll", "GetProcAddress",     0x0, _GetProcAddress, // Not heap related, but can be used to obtain pointers to heap functions.
+    "kernel32.dll", "HeapAlloc",          0x0, _RtlAllocateHeap,
+    "kernel32.dll", "HeapCreate",         0x0, _HeapCreate,
+    "kernel32.dll", "HeapDestroy",        0x0, _HeapDestroy,
+    "kernel32.dll", "HeapFree",           0x0, _RtlFreeHeap,
+    "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,
+
+    // 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,
+
+    // NT APIs.
+    "ntdll.dll",    "RtlAllocateHeap",    0x0, _RtlAllocateHeap,
+    "ntdll.dll",    "RtlFreeHeap",        0x0, _RtlFreeHeap,
+    "ntdll.dll",    "RtlReAllocateHeap",  0x0, _RtlReAllocateHeap,
+
+    // COM heap APIs.
+    "ole32.dll",    "CoGetMalloc",        0x0, _CoGetMalloc,
+    "ole32.dll",    "CoTaskMemAlloc",     0x0, _CoTaskMemAlloc,
+    "ole32.dll",    "CoTaskMemRealloc",   0x0, _CoTaskMemRealloc
+};
+
+// Constructor - Initializes private data, loads configuration options, and
+//   attaches Visual Leak Detector to all other modules loaded into the current
+//   process.
+//
+VisualLeakDetector::VisualLeakDetector ()
+{
+    WCHAR      bom = BOM; // Unicode byte-order mark.
+    HMODULE    kernel32;
+    ModuleSet *newmodules;
+    HMODULE    ntdll;
+    LPWSTR     symbolpath;
+
+    // Initialize configuration options and related private data.
+    _wcsnset_s(m_forcedmodulelist, MAXMODULELISTLENGTH, '\0', _TRUNCATE);
+    m_maxdatadump    = 0xffffffff;
+    m_maxtraceframes = 0xffffffff;
+    m_options        = 0x0;
+    m_reportfile     = NULL;
+    wcsncpy_s(m_reportfilepath, MAX_PATH, VLD_DEFAULT_REPORT_FILE_NAME, _TRUNCATE);
+    m_status         = 0x0;
+
+    // Load configuration options.
+    configure();
+    if (m_options & VLD_OPT_VLDOFF) {
+        report(L"Visual Leak Detector is turned off.\n");
+        return;
+    }
+
+    kernel32 = GetModuleHandle(L"kernel32.dll");
+    ntdll = GetModuleHandle(L"ntdll.dll");
+
+    // Initialize global variables.
+    currentprocess    = GetCurrentProcess();
+    currentthread     = GetCurrentThread();
+    InitializeCriticalSection(&imagelock);
+    LdrLoadDll        = (LdrLoadDll_t)GetProcAddress(ntdll, "LdrLoadDll");
+    processheap       = GetProcessHeap();
+    RtlAllocateHeap   = (RtlAllocateHeap_t)GetProcAddress(ntdll, "RtlAllocateHeap");
+    RtlFreeHeap       = (RtlFreeHeap_t)GetProcAddress(ntdll, "RtlFreeHeap");
+    RtlReAllocateHeap = (RtlReAllocateHeap_t)GetProcAddress(ntdll, "RtlReAllocateHeap");
+    InitializeCriticalSection(&stackwalklock);
+    InitializeCriticalSection(&symbollock);
+    vldheap           = HeapCreate(0x0, 0, 0);
+    InitializeCriticalSection(&vldheaplock);
+
+    // Initialize remaining private data.
+    m_heapmap         = new HeapMap;
+    m_heapmap->reserve(HEAPMAPRESERVE);
+    m_imalloc         = NULL;
+    m_leaksfound      = 0;
+    m_loadedmodules   = NULL;
+    InitializeCriticalSection(&m_loaderlock);
+    InitializeCriticalSection(&m_maplock);
+    InitializeCriticalSection(&m_moduleslock);
+    m_selftestfile    = __FILE__;
+    m_selftestline    = 0;
+    m_tlsindex        = TlsAlloc();
+    InitializeCriticalSection(&m_tlslock);
+    m_tlsset          = new TlsSet;
+
+    if (m_options & VLD_OPT_SELF_TEST) {
+        // Self-test mode has been enabled. Intentionally leak a small amount of
+        // memory so that memory leak self-checking can be verified.
+        if (m_options & VLD_OPT_UNICODE_REPORT) {
+            wcsncpy_s(new WCHAR [wcslen(SELFTESTTEXTW) + 1], wcslen(SELFTESTTEXTW) + 1, SELFTESTTEXTW, _TRUNCATE);
+            m_selftestline = __LINE__ - 1;
+        }
+        else {
+            strncpy_s(new CHAR [strlen(SELFTESTTEXTA) + 1], strlen(SELFTESTTEXTA) + 1, SELFTESTTEXTA, _TRUNCATE);
+            m_selftestline = __LINE__ - 1;
+        }
+    }
+    if (m_options & VLD_OPT_START_DISABLED) {
+        // Memory leak detection will initially be disabled.
+        m_status |= VLD_STATUS_NEVER_ENABLED;
+    }
+    if (m_options & VLD_OPT_REPORT_TO_FILE) {
+        // Reporting to file enabled.
+        if (m_options & VLD_OPT_UNICODE_REPORT) {
+            // Unicode data encoding has been enabled. Write the byte-order
+            // mark before anything else gets written to the file. Open the
+            // file for binary writing.
+            if (_wfopen_s(&m_reportfile, m_reportfilepath, L"wb") == EINVAL) {
+                // Couldn't open the file.
+                m_reportfile = NULL;
+            }
+            else {
+                fwrite(&bom, sizeof(WCHAR), 1, m_reportfile);
+                setreportencoding(unicode);
+            }
+        }
+        else {
+            // Open the file in text mode for ASCII output.
+            if (_wfopen_s(&m_reportfile, m_reportfilepath, L"w") == EINVAL) {
+                // Couldn't open the file.
+                m_reportfile = NULL;
+            }
+            else {
+                setreportencoding(ascii);
+            }
+        }
+        if (m_reportfile == NULL) {
+            report(L"WARNING: Visual Leak Detector: Couldn't open report file for writing: %s\n"
+                   L"  The report will be sent to the debugger instead.\n", m_reportfilepath);
+        }
+        else {
+            // Set the "report" function to write to the file.
+            setreportfile(m_reportfile, m_options & VLD_OPT_REPORT_TO_DEBUGGER);
+        }
+    }
+    if (m_options & VLD_OPT_SLOW_DEBUGGER_DUMP) {
+        // Insert a slight delay between messages sent to the debugger for
+        // output. (For working around a bug in VC6 where data sent to the
+        // debugger gets lost if it's sent too fast).
+        insertreportdelay();
+    }
+
+    // This is highly unlikely to happen, but just in case, check to be sure
+    // we got a valid TLS index.
+    if (m_tlsindex == TLS_OUT_OF_INDEXES) {
+        report(L"ERROR: Visual Leak Detector could not be installed because thread local"
+               L"  storage could not be allocated.");
+        return;
+    }
+
+    // Initialize the symbol handler. We use it for obtaining source file/line
+    // number information and function names for the memory leak report.
+    symbolpath = buildsymbolsearchpath();
+    SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
+    if (!SymInitializeW(currentprocess, symbolpath, FALSE)) {
+        report(L"WARNING: Visual Leak Detector: The symbol handler failed to initialize (error=%lu).\n"
+               L"    File and function names will probably not be available in call stacks.\n", GetLastError());
+    }
+    delete [] symbolpath;
+
+    // Patch into kernel32.dll's calls to LdrLoadDll so that VLD can
+    // dynamically attach to new modules loaded during runtime.
+    patchimport(kernel32, ntdll, "ntdll.dll", "LdrLoadDll", _LdrLoadDll);
+
+    // Attach Visual Leak Detector to every module loaded in the process.
+    newmodules = new ModuleSet;
+    newmodules->reserve(MODULESETRESERVE);
+    EnumerateLoadedModulesW64(currentprocess, addloadedmodule, newmodules);
+    attachtoloadedmodules(newmodules);
+    m_loadedmodules = newmodules;
+    m_status |= VLD_STATUS_INSTALLED;
+
+    report(L"Visual Leak Detector Version " VLDVERSION L" installed.\n");
+    if (m_status & VLD_STATUS_FORCE_REPORT_TO_FILE) {
+        // The report is being forced to a file. Let the human know why.
+        report(L"NOTE: Visual Leak Detector: Unicode-encoded reporting has been enabled, but the\n"
+               L"  debugger is the only selected report destination. The debugger cannot display\n"
+               L"  Unicode characters, so the report will also be sent to a file. If no file has\n"
+               L"  been specified, the default file name is \"" VLD_DEFAULT_REPORT_FILE_NAME L"\".\n");
+
+    }
+    reportconfig();
+}
+
+// Destructor - Detaches Visual Leak Detector from all modules loaded in the
+//   process, frees internally allocated resources, and generates the memory
+//   leak report.
+//
+VisualLeakDetector::~VisualLeakDetector ()
+{
+    BlockMap::Iterator   blockit;
+    BlockMap            *blockmap;
+    size_t               count;
+    DWORD                exitcode;
+    vldblockheader_t    *header;
+    HANDLE               heap;
+    HeapMap::Iterator    heapit;
+    SIZE_T               internalleaks = 0;
+    const char          *leakfile = NULL;
+    WCHAR                leakfilew [MAX_PATH];
+    int                  leakline = 0;
+    ModuleSet::Iterator  moduleit;
+    SIZE_T               sleepcount;
+    HANDLE               thread;
+    BOOL                 threadsactive= FALSE;
+    TlsSet::Iterator     tlsit;
+
+    if (m_options & VLD_OPT_VLDOFF) {
+        // VLD has been turned off.
+        return;
+    }
+
+    if (m_status & VLD_STATUS_INSTALLED) {
+        // Detach Visual Leak Detector from all previously attached modules.
+        EnumerateLoadedModulesW64(currentprocess, detachfrommodule, NULL);
+
+        // 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) {
+            if ((*tlsit)->threadid == GetCurrentThreadId()) {
+                // Don't wait for the current thread to exit.
+                continue;
+            }
+
+            sleepcount = 0;
+            thread = OpenThread(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");
+                    }
+                }
+            }
+        }
+        LeaveCriticalSection(&m_tlslock);
+
+        if (m_status & VLD_STATUS_NEVER_ENABLED) {
+            // Visual Leak Detector started with leak detection disabled and
+            // it was never enabled at runtime. A lot of good that does.
+            report(L"WARNING: Visual Leak Detector: Memory leak detection was never enabled.\n");
+        }
+        else {
+            // Generate a memory leak report for each heap in the process.
+            for (heapit = m_heapmap->begin(); heapit != m_heapmap->end(); ++heapit) {
+                heap = (*heapit).first;
+                reportleaks(heap);
+            }
+
+            // Show a summary.
+            if (m_leaksfound == 0) {
+                report(L"No memory leaks detected.\n");
+            }
+            else {
+                report(L"Visual Leak Detector detected %lu memory leak", m_leaksfound);
+                report((m_leaksfound > 1) ? L"s.\n" : L".\n");
+            }
+        }
+
+        // Free resources used by the symbol handler.
+        if (!SymCleanup(currentprocess)) {
+            report(L"WARNING: Visual Leak Detector: The symbol handler failed to deallocate resources (error=%lu).\n",
+                   GetLastError());
+        }
+
+        // Free internally allocated resources used by the heapmap and blockmap.
+        for (heapit = m_heapmap->begin(); heapit != m_heapmap->end(); ++heapit) {
+            blockmap = &(*heapit).second->blockmap;
+            for (blockit = blockmap->begin(); blockit != blockmap->end(); ++blockit) {
+                delete (*blockit).second->callstack;
+                delete (*blockit).second;
+            }
+            delete blockmap;
+        }
+        delete m_heapmap;
+
+        // Free internally allocated resources used by the loaded module set.
+        for (moduleit = m_loadedmodules->begin(); moduleit != m_loadedmodules->end(); ++moduleit) {
+            delete (*moduleit).name;
+            delete (*moduleit).path;
+        }
+        delete m_loadedmodules;
+
+        // Free internally allocated resources used for thread local storage.
+        for (tlsit = m_tlsset->begin(); tlsit != m_tlsset->end(); ++tlsit) {
+            delete *tlsit;
+        }
+        delete m_tlsset;
+
+        // Do a memory leak self-check.
+        header = vldblocklist;
+        while (header) {
+            // Doh! VLD still has an internally allocated block!
+            // This won't ever actually happen, right guys?... guys?
+            internalleaks++;
+            leakfile = header->file;
+            leakline = header->line;
+            mbstowcs_s(&count, leakfilew, MAX_PATH, leakfile, _TRUNCATE);
+            report(L"ERROR: Visual Leak Detector: Detected a memory leak internal to Visual Leak Detector!!\n");
+            report(L"---------- Block %ld at " ADDRESSFORMAT L": %u bytes ----------\n", header->serialnumber,
+                   VLDBLOCKDATA(header), header->size);
+            report(L"  Call Stack:\n");
+            report(L"    %s (%d): Full call stack not available.\n", leakfilew, leakline);
+            if (m_maxdatadump != 0) {
+                report(L"  Data:\n");
+                if (m_options & VLD_OPT_UNICODE_REPORT) {
+                    dumpmemoryw(VLDBLOCKDATA(header), (m_maxdatadump < header->size) ? m_maxdatadump : header->size);
+                }
+                else {
+                    dumpmemorya(VLDBLOCKDATA(header), (m_maxdatadump < header->size) ? m_maxdatadump : header->size);
+                }
+            }
+            report(L"\n");
+            header = header->next;
+        }
+        if (m_options & VLD_OPT_SELF_TEST) {
+            if ((internalleaks == 1) && (strcmp(leakfile, m_selftestfile) == 0) && (leakline == m_selftestline)) {
+                report(L"Visual Leak Detector passed the memory leak self-test.\n");
+            }
+            else {
+                report(L"ERROR: Visual Leak Detector: Failed the memory leak self-test.\n");
+            }
+        }
+
+        if (threadsactive == TRUE) {
+            report(L"WARNING: Visual Leak Detector: Some threads appear to have not terminated normally.\n"
+                L"  This could cause inaccurate leak detection results, including false positives.\n");
+        }
+        report(L"Visual Leak Detector is now exiting.\n");
+    }
+    else {
+        // VLD failed to load properly.
+        delete m_heapmap;
+        delete m_tlsset;
+    }
+    HeapDestroy(vldheap);
+
+    DeleteCriticalSection(&imagelock);
+    DeleteCriticalSection(&m_loaderlock);
+    DeleteCriticalSection(&m_maplock);
+    DeleteCriticalSection(&m_moduleslock);
+    DeleteCriticalSection(&stackwalklock);
+    DeleteCriticalSection(&symbollock);
+    DeleteCriticalSection(&vldheaplock);
+
+    if (m_tlsindex != TLS_OUT_OF_INDEXES) {
+        TlsFree(m_tlsindex);
+    }
+
+    if (m_reportfile != NULL) {
+        fclose(m_reportfile);
+    }
+}
+
+// _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.
+//
+//  - imalloc (IN): Address of a pointer to receive the address of VLD's
+//      implementation of the IMalloc interface.
+//
+//  Return Value:
+//
+//    Always returns S_OK.
+//
+HRESULT VisualLeakDetector::_CoGetMalloc (DWORD context, LPMALLOC *imalloc)
+{
+    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);
+    }
+
+    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)
+{
+    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;
+    }
+
+    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");
+    }
+
+    // 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;
+}
+
+// _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.
+//
+//  Return Value:
+//
+//    Returns the value returned from CoTaskMemRealloc.
+//
+LPVOID VisualLeakDetector::_CoTaskMemRealloc (LPVOID mem, ULONG size)
+{
+    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;
+    }
+
+    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;
+}
+
+// _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.
+//
+//  Return Value:
+//
+//    Returns the value returned by _calloc_dbg.
+//
+void* VisualLeakDetector::_crt80d__calloc_dbg (size_t num, size_t size, int type, const char *file, int line)
+{
+    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;
+
+    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 (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");
+    }
+
+    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
+    block = pcrt80d__calloc_dbg(num, size, type, file, line);
+
+    // Reset thread local flags and variables for the next allocation.
+    tls->addrfp = 0x0;
+    tls->flags &= ~VLD_TLS_CRTALLOC;
+
+    return block;
+}
+
+// _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();
+
+    // _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 (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");
+    }
+
+    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
+    block = pcrt80d__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;
+}
+
+// _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.
+//
+//  Return Value:
+//
+//    Returns the value returned by _realloc_dbg.
+//
+void* VisualLeakDetector::_crt80d__realloc_dbg (void *mem, size_t size, int type, const char *file, int line)
+{
+    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;
+
+    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 (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");
+    }
+
+    // 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;
+}
+
+// _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.
+//
+//  - 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 debug scalar new operator.
+//
+void* VisualLeakDetector::_crt80d__scalar_new_dbg (unsigned int size, int type, const char *file, int line)
+{
+    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;
+
+    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 (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");
+    }
+
+    // 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;
+}
+
+// _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.
+//
+//  Return Value:
+//
+//    Returns the value returned by the CRT debug vector new operator.
+//
+void* VisualLeakDetector::_crt80d__vector_new_dbg (unsigned int size, int type, const char *file, int line)
+{
+    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;
+
+    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 (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");
+    }
+
+    // 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;
+}
+
+// _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.
+//
+//  - 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 valued returned from calloc.
+//
+void* VisualLeakDetector::_crt80d_calloc (size_t num, size_t size)
+{
+    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;
+    }
+
+    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");
+    }
+
+    // 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;
+}
+
+// _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.
+//
+//  - size (IN): The size, in bytes, of the memory block to be allocated.
+//
+//  Return Value:
+//
+//    Returns the valued returned from malloc.
+//
+void* VisualLeakDetector::_crt80d_malloc (size_t size)
+{
+    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;
+    }
+
+    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");
+    }
+
+    // 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;
+}
+
+// _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.
+//
+//  - mem (IN): Pointer to the memory block to reallocate.
+//
+//  - size (IN): Size of the memory block to reallocate.
+//
+//  Return Value:
+//
+//    Returns the value returned from realloc.
+//
+void* VisualLeakDetector::_crt80d_realloc (void *mem, size_t size)
+{
+    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;
+
+    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 (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");
+    }
+
+    // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
+    block = pcrt80d_realloc(mem, size);
+
+    // Reset thread local flags and variables for the next allocation.
+    tls->addrfp = 0x0;
+    tls->flags &= ~VLD_TLS_CRTALLOC;
+
+    return block;
+}
+
+// _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.
+//
+//  Return Value:
+//
+//    Returns the value returned by the CRT scalar new operator.
+//
+void* VisualLeakDetector::_crt80d_scalar_new (unsigned int size)
+{
+    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 (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");
+    }
+
+    // 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.
+//
+//  - size (IN): The size, in bytes, of the memory block to be allocated.
+//
+//  Return Value:
+//
+//    Returns the value returned by the CRT vector new operator.
+//
+void* VisualLeakDetector::_crt80d_vector_new (unsigned int size)
+{
+    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 (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");
+    }
+
+    // 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;
+}
+
+// _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.
+//
+//  - 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.
+//
+//  - 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 _calloc_dbg.
+//
+void* VisualLeakDetector::_crtd__calloc_dbg (size_t num, size_t size, int type, const char *file, int line)
+{
+    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;
+
+    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_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");
+    }
+
+    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
+    block = pcrtd__calloc_dbg(num, size, type, file, line);
+
+    // Reset thread local flags and variables for the next allocation.
+    tls->addrfp = 0x0;
+    tls->flags &= ~VLD_TLS_CRTALLOC;
+
+    return block;
+}
+
+// _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.
+//
+//  - 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::_crtd__malloc_dbg (size_t size, int type, const char *file, int line)
+{
+    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;
+
+    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_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");
+    }
+
+    // Do the allocation. The block will be mapped by _RtlAllocateHeap.
+    block = pcrtd__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;
+}
+
+// _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.
+//
+//  - 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.
+//
+//  Return Value:
+//
+//    Returns the value returned by _realloc_dbg.
+//
+void* VisualLeakDetector::_crtd__realloc_dbg (void *mem, size_t size, int type, const char *file, int line)
+{
+    void    *block;
+    SIZE_T   fp;
+    HMODULE  msvcrtd;
+    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.
+        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);
+
+    // Reset thread local flags and variables for the next allocation.
+    tls->addrfp = 0x0;
+    tls->flags &= ~VLD_TLS_CRTALLOC;
+
+    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
+//   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 the CRT debug scalar new operator.
+//
+void* VisualLeakDetector::_crtd__scalar_new_dbg (unsigned int size, int type, const char *file, int line)
+{
+    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.
+    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);
+
+    // Reset thread local flags and variables for the next allocation.
+    tls->addrfp = 0x0;
+    tls->flags &= ~VLD_TLS_CRTALLOC;
+
+    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.
+//
+//  - 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 valued returned from calloc.
+//
+void* VisualLeakDetector::_crtd_calloc (size_t num, size_t size)
+{
+    void    *block;
+    SIZE_T   fp;
+    HMODULE  msvcrtd;
+    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;
+    }
+
+    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);
+
+    // Reset thread local flags and variables for the next allocation.
+    tls->addrfp = 0x0;
+    tls->flags &= ~VLD_TLS_CRTALLOC;
+
+    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
+//   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 valued returned from malloc.
+//
+void* VisualLeakDetector::_crtd_malloc (size_t size)
+{
+    void    *block;
+    SIZE_T   fp;
+    HMODULE  msvcrtd;
+    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;
+    }
+
+    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 _RtlAllocateHeap.
+    block = pcrtd_malloc(size);
+
+    // Reset thread local flags and variables for the next allocation.
+    tls->addrfp = 0x0;
+    tls->flags &= ~VLD_TLS_CRTALLOC;
+
+    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.
+//
+//  - mem (IN): Pointer to the memory block to reallocate.
+//
+//  - size (IN): Size of the memory block to reallocate.
+//
+//  Return Value:
+//
+//    Returns the value returned from realloc.
+//
+void* VisualLeakDetector::_crtd_realloc (void *mem, size_t size)
+{
+    void    *block;
+    SIZE_T   fp;
+    HMODULE  msvcrtd;
+    tls_t   *tls = vld.gettls();
+
+    // 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_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 _RtlReAllocateHeap.
+    block = pcrtd_realloc(mem, size);
+
+    // Reset thread local flags and variables for the next allocation.
+    tls->addrfp = 0x0;
+    tls->flags &= ~VLD_TLS_CRTALLOC;
+
+    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.
+//
+//  - size (IN): The size, in bytes, of the memory block to be allocated.
+//
+//  Return Value:
+//
+//    Returns the value returned by the CRT scalar new operator.
+//
+void* VisualLeakDetector::_crtd_scalar_new (unsigned int size)
+{
+    void    *block;
+    SIZE_T   fp;
+    HMODULE  msvcrtd;
+    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 (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 tha allocation. The block will be mapped by _RtlAllocateHeap.
+    block = pcrtd_scalar_new(size);
+
+    // Reset thread local flags and variables for the next allocation.
+    tls->addrfp = 0x0;
+    tls->flags &= ~VLD_TLS_CRTALLOC;
+
+    return block;
+}
+
+// _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
+//   function is returned instead of the real address. Otherwise, this 
+//   function is just a wrapper around the real GetProcAddress.
+//
+//  - module (IN): Handle (base address) of the module from which to retrieve
+//      the address of an exported function.
+//
+//  - procname (IN): ANSI string containing the name of the exported function
+//      whose address is to be retrieved.
+//
+//  Return Value:
+//
+//    Returns a pointer to the requested function, or VLD's replacement for
+//    the function, if there is a replacement function.
+//
+FARPROC VisualLeakDetector::_GetProcAddress (HMODULE module, LPCSTR procname)
+{
+    patchentry_t *entry;
+    UINT          index;
+    UINT          tablesize = sizeof(vld.m_patchtable) / sizeof(patchentry_t);
+
+    // See if there is an entry in the patch table that matches the requested
+    // function.
+    for (index = 0; index < tablesize; index++) {
+        entry = &vld.m_patchtable[index];
+        if ((entry->modulebase == 0x0) || ((HMODULE)entry->modulebase != module)) {
+            // This patch table entry is for a different module.
+            continue;
+        }
+
+        // This patch table entry is for the specified module. If the requested
+        // import's name matches the entry's import name (or ordinal), then
+        // return the address of the replacement instead of the address of the
+        // actual import.
+        if ((SIZE_T)entry->importname < (SIZE_T)vld.m_vldbase) {
+            // This entry's import name is not a valid pointer to data in
+            // vld.dll. It must be an ordinal value.
+            if ((UINT)entry->importname == (UINT)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;
+    }
+
+    GetPrivateProfileString(L"Options", L"StartDisabled", L"", buffer, BSIZE, inipath);
+    if (strtobool(buffer) == TRUE) {
+        m_options |= VLD_OPT_START_DISABLED;
+    }
+
+    GetPrivateProfileString(L"Options", L"TraceInternalFrames", L"", buffer, BSIZE, inipath);
+    if (strtobool(buffer) == TRUE) {
+        m_options |= VLD_OPT_TRACE_INTERNAL_FRAMES;
+    }
+
+    // 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;
+    }
+
+    // Read the force-include module list.
+    GetPrivateProfileString(L"Options", L"ForceIncludeModules", L"", m_forcedmodulelist, MAXMODULELISTLENGTH, inipath);
+    _wcslwr_s(m_forcedmodulelist, MAXMODULELISTLENGTH);
+
+    // 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;
+    }
+
+    // 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;
+    }
+}
+
+// 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).
+//
+//  - 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;
+}
+
+// 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::DidAlloc.
+//
+INT VisualLeakDetector::DidAlloc (LPVOID mem)
+{
+    assert(m_imalloc != NULL);
+    return m_imalloc->DidAlloc(mem);
+}
+
+// enabled - Determines if memory leak detection is enabled for the current
+//   thread.
+//
+//  Return Value:
+//
+//    Returns true if Visual Leak Detector is enabled for the current thread.
+//    Otherwise, returns false.
+//
+BOOL VisualLeakDetector::enabled ()
+{
+    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;
+    }
+
+    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;
+        }
+    }
+
+    return ((tls->flags & VLD_TLS_ENABLED) != 0);
+}
+
+// eraseduplicates - Erases, from the block maps, blocks that appear to be
+//   duplicate leaks of an already identified leak.
+//
+//  - element (IN): BlockMap Iterator referencing the block of which to search
+//      for duplicates.
+//
+//  Return Value:
+//
+//    Returns the number of duplicate blocks erased from the block map.
+//
+SIZE_T VisualLeakDetector::eraseduplicates (const BlockMap::Iterator &element)
+{
+    BlockMap::Iterator  blockit;
+    BlockMap           *blockmap;
+    blockinfo_t        *elementinfo;
+    SIZE_T              erased = 0;
+    HeapMap::Iterator   heapit;
+    blockinfo_t        *info;
+    BlockMap::Iterator  previt;
+
+    elementinfo = (*element).second;
+
+    // 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++;
+            }
+        }
+    }
+
+    return erased;
+}
+
+// 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.
+//
+//  Return Value:
+//
+//    None.
+//
+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 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);
+}
+
+// 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);
+
+    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();
+
+        // Add this thread's TLS to the TlsSet.
+        EnterCriticalSection(&m_tlslock);
+        m_tlsset->insert(tls);
+        LeaveCriticalSection(&m_tlslock);
+    }
+
+    return tls;
+}
+
+// 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();
+}
+
+// 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.
+//
+//  - 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:
+//
+//    None.
+//
+VOID VisualLeakDetector::mapblock (HANDLE heap, LPCVOID mem, SIZE_T size, SIZE_T framepointer, BOOL crtalloc)
+{
+    blockinfo_t        *blockinfo;
+    BlockMap::Iterator  blockit;
+    BlockMap           *blockmap;
+    HeapMap::Iterator   heapit;
+    static SIZE_T       serialnumber = 0;
+
+    // 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);
+    }
+    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;
+    }
+    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);
+}
+
+// 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.
+//
+//  - heap (IN): Handle to the newly created heap.
+//
+//  Return Value:
+//
+//    None.
+//
+VOID VisualLeakDetector::mapheap (HANDLE heap)
+{
+    heapinfo_t        *heapinfo;
+    HeapMap::Iterator  heapit;
+
+    // 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);
+    }
+    LeaveCriticalSection(&m_maplock);
+}
+
+// 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.
+//
+//  - object (IN): Address of a pointer to receive the requested interface
+//      pointer.
+//
+//  Return Value:
+//
+//    Returns the value returned by the system implementation of
+//    IMalloc::QueryInterface.
+//
+HRESULT VisualLeakDetector::QueryInterface (REFIID iid, LPVOID *object)
+{
+    assert(m_imalloc != NULL);
+    return m_imalloc->QueryInterface(iid, object);
+}
+
+// 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.
+//
+//  - size (IN): Size, in bytes, of the memory block to reallocate.
+//
+//  Return Value:
+//
+//    Returns the value returned by the system implementation of
+//    IMalloc::Realloc.
+//
+LPVOID VisualLeakDetector::Realloc (LPVOID mem, 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 _RtlReAllocateHeap.
+    assert(m_imalloc != NULL);
+    block = m_imalloc->Realloc(mem, 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.
+//
+//  Return Value:
+//
+//    Returns the value returned by the system implementation of
+//    IMalloc::Release.
+//
+ULONG VisualLeakDetector::Release ()
+{
+    assert(m_imalloc != NULL);
+    return m_imalloc->Release();
+}
+
+// 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.
+//
+//  - 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)
+{
+    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);
+
+    // 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;
+}
+
+// reportconfig - Generates a brief report summarizing Visual Leak Detector's
+//   configuration, as loaded from the vld.ini file.
+//
+//  Return Value:
+//
+//    None.
+//
+VOID VisualLeakDetector::reportconfig ()
+{
+    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");
+    }
+}
+
+// reportleaks - Generates a memory leak report for the specified heap.
+//
+//  - heap (IN): Handle to the heap for which to generate a memory leak
+//      report.
+//
+//  Return Value:
+//
+//    None.
+//
+VOID VisualLeakDetector::reportleaks (HANDLE heap)
+{
+    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);
+}
+
+// unmapblock - Tracks memory blocks that are freed. Unmaps the specified block
+//   from the block's information, relinquishing internally allocated resources.
+//
+//  - heap (IN): Handle to the heap to which this block is being freed.
+//
+//  - mem (IN): Pointer to the memory block being freed.
+//
+//  Return Value:
+//
+//    None.
+//
+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:
+//
+//    None.
+//
+VOID VisualLeakDetector::unmapheap (HANDLE heap)
+{
+    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);
+}
diff --git a/development/Win32/vld/src/vldapi.cpp b/development/Win32/vld/src/vldapi.cpp
new file mode 100644 (file)
index 0000000..9ff15e5
--- /dev/null
@@ -0,0 +1,69 @@
+////////////////////////////////////////////////////////////////////////////////
+//  $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
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#define VLDBUILD     // Declares that we are building Visual Leak Detector.
+#include "vldint.h"  // Provides access to the Visual Leak Detector internals.
+#include "vldheap.h" // Provides internal new and delete operators.
+
+// Imported global variables.
+extern VisualLeakDetector vld;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Visual Leak Detector APIs - see vldapi.h for each function's details.
+//
+
+extern "C" __declspec(dllexport) void VLDDisable ()
+{
+    tls_t *tls;
+
+    if (vld.m_options & VLD_OPT_VLDOFF) {
+        // VLD has been turned off.
+        return;
+    }
+
+    // Disable memory leak detection for the current thread. There are two flags
+    // because if neither flag is set, it means that we are in the default or
+    // "starting" state, which could be either enabled or disabled depending on
+    // the configuration.
+    tls = vld.gettls();
+    tls->flags &= ~VLD_TLS_ENABLED;
+    tls->flags |= VLD_TLS_DISABLED;
+}
+
+extern "C" __declspec(dllexport) void VLDEnable ()
+{
+    tls_t *tls;
+
+    if (vld.m_options & VLD_OPT_VLDOFF) {
+        // VLD has been turned off.
+        return;
+    }
+
+    // Enable memory leak detection for the current thread.
+    tls = vld.gettls();
+    tls->flags &= ~VLD_TLS_DISABLED;
+    tls->flags |= VLD_TLS_ENABLED;
+    vld.m_status &= ~VLD_STATUS_NEVER_ENABLED;
+}
diff --git a/development/Win32/vld/src/vldheap.cpp b/development/Win32/vld/src/vldheap.cpp
new file mode 100644 (file)
index 0000000..cb2d139
--- /dev/null
@@ -0,0 +1,213 @@
+////////////////////////////////////////////////////////////////////////////////
+//  $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
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#include <cassert>
+#define VLDBUILD     // Declares that we are building Visual Leak Detector.
+#include "ntapi.h"   // Provides access to NT APIs.
+#include "vldheap.h" // Provides access to VLD's internal heap data structures.
+#undef new           // Do not map "new" to VLD's new operator in this file
+
+// Global variables.
+vldblockheader_t *vldblocklist = NULL; // List of internally allocated blocks on VLD's private heap.
+HANDLE            vldheap;             // VLD's private heap.
+CRITICAL_SECTION  vldheaplock;         // Serializes access to VLD's private heap.
+
+// Local helper functions.
+static inline void vlddelete (void *block);
+static inline void* vldnew (unsigned int size, const char *file, int line);
+
+// scalar delete operator - Delete operator used to free internally used memory
+//   back to VLD's private heap.
+//
+//  - block (IN): Pointer to the scalar memory block to free.
+//
+//  Return Value:
+//
+//    None.
+//
+void operator delete (void *block)
+{
+    vlddelete(block);
+}
+
+// vector delete operator - Delete operator used to free internally used memory
+//   back to VLD's private heap.
+//
+//  - block (IN): Pointer to the vector memory block to free.
+//
+//  Return Value:
+//
+//    None.
+//
+void operator delete [] (void *block)
+{
+    vlddelete(block);
+}
+
+// scalar delete operator - Delete operator used to free memory partially
+//   allocated by new in the event that the corresponding new operator throws
+//   an exception.
+//
+//  Note: This version of the delete operator should never be called directly.
+//    The compiler automatically generates calls to this function as needed.
+//
+void operator delete (void *block, const char *, int)
+{
+    vlddelete(block);
+}
+
+// vector delete operator - Delete operator used to free memory partially
+//   allocated by new in the event that the corresponding new operator throws
+//   an exception.
+//
+//  Note: This version of the delete operator should never be called directly.
+//    The compiler automatically generates calls to this function as needed.
+//
+void operator delete [] (void *block, const char *, int)
+{
+    vlddelete(block);
+}
+
+// scalar new operator - New operator used to allocate a scalar memory block
+//   from VLD's private heap.
+//
+//  - size (IN): Size 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:
+//
+//    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)
+{
+    return vldnew(size, file, line);
+}
+
+// vector new operator - New operator used to allocate a vector memory block
+//   from VLD's private heap.
+//
+//  - size (IN): Size 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:
+//
+//    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)
+{
+    return vldnew(size, file, line);
+}
+
+// vlddelete - Local helper function that actually frees memory back to VLD's
+//   private heap.
+//
+//  - block (IN): Pointer to a memory block being freed.
+//
+//  Return Value:
+//
+//    None.
+//
+void vlddelete (void *block)
+{
+    BOOL              freed;
+    vldblockheader_t *header = VLDBLOCKHEADER((LPVOID)block);
+
+    // Unlink the block from the block list.
+    EnterCriticalSection(&vldheaplock);
+    if (header->prev) {
+        header->prev->next = header->next;
+    }
+    else {
+        vldblocklist = header->next;
+    }
+
+    if (header->next) {
+        header->next->prev = header->prev;
+    }
+    LeaveCriticalSection(&vldheaplock);
+
+    // Free the block.
+    freed = RtlFreeHeap(vldheap, 0x0, header);
+    assert(freed != FALSE);
+}
+
+// vldnew - Local helper function that actually allocates memory from VLD's
+//   private heap. Prepends a header, which is used for bookeeping information
+//   that allows VLD to detect and report internal memory leaks, to the returned
+//   block, but the header is transparent to the caller because the returned
+//   pointer points to the useable section of memory requested by the caller, it
+//   does not point to the block header.
+//
+//  - size (IN): Size of the memory block to be allocated.
+//
+//  - file (IN): Name of the file that called the new operator.
+//
+//  - line (IN): Line, in the above file, at which the new operator was called.
+//
+//  Return Value:
+//
+//    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)
+{
+    vldblockheader_t *header = (vldblockheader_t*)RtlAllocateHeap(vldheap, 0x0, size + sizeof(vldblockheader_t));
+    static SIZE_T     serialnumber = 0;
+
+    if (header == NULL) {
+        // Out of memory.
+        return NULL;
+    }
+
+    // Fill in the block's header information.
+    header->file         = file;
+    header->line         = line;
+    header->serialnumber = serialnumber++;
+    header->size         = size;
+
+    // Link the block into the block list.
+    EnterCriticalSection(&vldheaplock);
+    header->next         = vldblocklist;
+    if (header->next != NULL) {
+        header->next->prev = header;
+    }
+    header->prev         = NULL;
+    vldblocklist         = header;
+    LeaveCriticalSection(&vldheaplock);
+
+    // Return a pointer to the beginning of the data section of the block.
+    return (void*)VLDBLOCKDATA(header);
+}
\ No newline at end of file
diff --git a/development/Win32/vld/src/vldheap.h b/development/Win32/vld/src/vldheap.h
new file mode 100644 (file)
index 0000000..ccbc076
--- /dev/null
@@ -0,0 +1,95 @@
+////////////////////////////////////////////////////////////////////////////////
+//  $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
+//
+//  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
+
+#ifndef VLDBUILD
+#error \
+"This header should only be included by Visual Leak Detector when building it from source. \
+Applications should never include this header."
+#endif
+
+#include <windows.h>
+
+#define GAPSIZE 4
+
+// Memory block header structure used internally by the debug CRT. All blocks
+// allocated by the CRT are allocated from the CRT heap and, in debug mode, they
+// have this header prepended to them (there's also a trailer appended at the
+// end, but we're not interested in that).
+typedef struct crtdbgblockheader_s
+{
+    struct crtblockheader_s *next;          // Pointer to the next block in the list of blocks allocated from the CRT heap.
+    struct crtblockheader_s *prev;          // Pointer to the previous block in the list of blocks allocated from the CRT heap.
+    char                    *file;          // Source file where this block was allocated.
+    int                      line;          // Line of code, within the above file, where this block was allocated.
+#ifdef _WIN64
+    int                      use;           // This block's "use type": see below.
+    size_t                   size;          // Size of the data portion of the block.
+#else
+    size_t                   size;          // Size of the data portion of the block.
+    int                      use;           // This block's "use type":
+#endif // _WIN64
+#define CRT_USE_FREE     0                  //   This block has been freed.
+#define CRT_USE_NORMAL   1                  //   This is a normal (user) block.
+#define CRT_USE_INTERNAL 2                  //   This block is used internally by the CRT.
+#define CRT_USE_IGNORE   3                  //   This block is a specially tagged block that is ignored during some debug error checking.
+#define CRT_USE_CLIENT   4                  //   This block is a specially tagged block with special use defined by the user application.
+    long                     request;       // This block's "request" number. Basically a serial number.
+    unsigned char            gap [GAPSIZE]; // No-man's land buffer zone, for buffer overrun/underrun checking.
+} crtdbgblockheader_t;
+
+// Macro to strip off any sub-type information stored in a block's "use type".
+#define CRT_USE_TYPE(use) (use & 0xFFFF)
+
+// Memory block header structure used internally by VLD. All internally
+// allocated blocks are allocated from VLD's private heap and have this header
+// prepended to them.
+typedef struct vldblockheader_s
+{
+    struct vldblockheader_s *next;          // Pointer to the next block in the list of internally allocated blocks.
+    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                   serialnumber;  // Each block is assigned a unique serial number, starting from zero.
+} vldblockheader_t;
+
+// Data-to-Header and Header-to-Data conversion
+#define CRTDBGBLOCKHEADER(d) (crtdbgblockheader_t*)(((PBYTE)d) - sizeof(crtdbgblockheader_t))
+#define CRTDBGBLOCKDATA(h) (LPVOID)(((PBYTE)h) + sizeof(crtdbgblockheader_t))
+#define VLDBLOCKHEADER(d) (vldblockheader_t*)(((PBYTE)d) - sizeof(vldblockheader_t))
+#define VLDBLOCKDATA(h) (LPVOID)(((PBYTE)h) + sizeof(vldblockheader_t))
+
+// new and delete operators for allocating from VLD's private heap.
+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);
+
+// All calls to the new operator from within VLD are mapped to the version of
+// new that allocates from VLD's private heap.
+#define new new(__FILE__, __LINE__)
diff --git a/development/Win32/vld/src/vldint.h b/development/Win32/vld/src/vldint.h
new file mode 100644 (file)
index 0000000..ed87293
--- /dev/null
@@ -0,0 +1,263 @@
+////////////////////////////////////////////////////////////////////////////////
+//  $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
+//
+//  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
+
+#ifndef VLDBUILD
+#error \
+"This header should only be included by Visual Leak Detector when building it from source. \
+Applications should never include this header."
+#endif
+
+#include <cstdio>
+#include <windows.h>
+#include "callstack.h" // Provides a custom class for handling call stacks.
+#include "map.h"       // Provides a custom STL-like map template.
+#include "ntapi.h"     // Provides access to NT APIs.
+#include "set.h"       // Provides a custom STL-like set template.
+#include "utility.h"   // Provides miscellaneous utility functions.
+
+#define MAXMODULELISTLENGTH 512     // Maximum module list length, in characters.
+#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"
+
+// The Visual Leak Detector APIs.
+extern "C" __declspec(dllexport) void VLDDisable ();
+extern "C" __declspec(dllexport) void VLDEnable ();
+
+// 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
+// block.
+typedef struct blockinfo_s {
+    CallStack *callstack;
+    SIZE_T     serialnumber;
+    SIZE_T     size;
+} blockinfo_t;
+
+// BlockMaps map memory blocks (via their addresses) to blockinfo_t structures.
+typedef Map<LPCVOID, blockinfo_t*> BlockMap;
+
+// Information about each heap in the process is kept in this map. Primarily
+// this is used for mapping heaps to all of the blocks allocated from those
+// heaps.
+typedef struct heapinfo_s {
+    BlockMap blockmap;   // Map of all blocks allocated from this heap.
+    UINT32   flags;      // Heap status flags:
+#define VLD_HEAP_CRT 0x1 //   If set, this heap is a CRT heap (i.e. the CRT uses it for new/malloc).
+} heapinfo_t;
+
+// HeapMaps map heaps (via their handles) to BlockMaps.
+typedef Map<HANDLE, heapinfo_t*> HeapMap;
+
+// This structure stores information, primarily the virtual address range, about
+// a given module and can be used with the Set template because it supports the
+// '<' operator (sorts by virtual address range).
+typedef struct moduleinfo_s {
+    BOOL operator < (const struct moduleinfo_s &other) const
+    {
+        if (addrhigh < other.addrlow) {
+            return TRUE;
+        }
+        else {
+            return FALSE;
+        }
+    }
+
+    SIZE_T addrhigh;                 // Highest address within the module's virtual address space (i.e. base + size).
+    SIZE_T addrlow;                  // Lowest address within the module's virtual address space (i.e. base address).
+    UINT32 flags;                    // Module flags:
+#define VLD_MODULE_EXCLUDED      0x1 //   If set, this module is excluded from leak detection.
+#define VLD_MODULE_SYMBOLSLOADED 0x2 //   If set, this module's debug symbols have been loaded.
+    LPCSTR name;                     // The module's name (e.g. "kernel32.dll").
+    LPCSTR path;                     // The fully qualified path from where the module was loaded.
+} moduleinfo_t;
+
+// ModuleSets store information about modules loaded in the process.
+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
+// detection status (enabled or disabled) and the address that initiated the
+// current allocation is stored here.
+typedef struct tls_s {
+    SIZE_T addrfp;           // Frame pointer at the first call that entered VLD's code for the current allocation.
+    UINT32 flags;            // Thread-local status flags:
+#define VLD_TLS_CRTALLOC 0x1 //   If set, the current allocation is a CRT allocation.
+#define VLD_TLS_DISABLED 0x2 //   If set, memory leak detection is disabled for the current thread.
+#define VLD_TLS_ENABLED  0x4 //   If set, memory leak detection is enabled for the current thread.
+    DWORD  threadid;         // Thread ID of the thread that owns this TLS structure.
+} tls_t;
+
+// The TlsSet allows VLD to keep track of all thread local storage structures
+// allocated in the process.
+typedef Set<tls_t*> TlsSet;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// The VisualLeakDetector Class
+//
+//   One global instance of this class is instantiated. Upon construction it
+//   patches the import address table (IAT) of every other module loaded in the
+//   process (see the "patchimport" utility function) to allow key Windows heap
+//   APIs to be patched through to, or redirected to, functions provided by VLD.
+//   Patching the IATs in this manner allows VLD to be made aware of all
+//   relevant heap activity, making it possible for VLD to detect and trace
+//   memory leaks.
+//
+//   The one global instance of this class is constructed within the context of
+//   the process' main thread during process initialization and is destroyed in
+//   the same context during process termination.
+//
+//   When the VisualLeakDetector object is destroyed, it consults its internal
+//   datastructures, looking for any memory that has not been freed. A memory
+//   leak report is then generated, indicating any memory leaks that may have
+//   been identified.
+//
+//   This class is derived from IMalloc so that it can provide an implementation
+//   of the IMalloc COM interface in order to support detection of COM-based
+//   memory leaks. However, this implementation of IMalloc is actually just a
+//   thin wrapper around the system's implementation of IMalloc.
+//
+class VisualLeakDetector : public IMalloc
+{
+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 ();
+    HRESULT __stdcall QueryInterface (REFIID iid, LPVOID *object);
+    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);
+    LPWSTR buildsymbolsearchpath ();
+    VOID configure ();
+    static BOOL __stdcall detachfrommodule (PCWSTR modulepath, DWORD64 modulebase, ULONG modulesize, PVOID context);
+    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);
+
+    // 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.
+    SIZE_T               m_leaksfound;        // Total number of leaks found.
+    ModuleSet           *m_loadedmodules;     // Contains information about all modules loaded in the process.
+    CRITICAL_SECTION     m_loaderlock;        // Serializes the attachment of newly loaded modules.
+    CRITICAL_SECTION     m_maplock;           // Serializes access to the heap and block maps.
+    SIZE_T               m_maxdatadump;       // Maximum number of user-data bytes to dump for each leaked block.
+    UINT32               m_maxtraceframes;    // Maximum number of frames per stack trace for each leaked block.
+    CRITICAL_SECTION     m_moduleslock;       // Protects accesses to the "loaded modules" ModuleSet.
+    UINT32               m_options;           // Configuration options:
+#define VLD_OPT_AGGREGATE_DUPLICATES    0x1   //   If set, aggregate duplicate leaks in the leak report.
+#define VLD_OPT_MODULE_LIST_INCLUDE     0x2   //   If set, modules in the module list are included, all others are excluded.
+#define VLD_OPT_REPORT_TO_DEBUGGER      0x4   //   If set, the memory leak report is sent to the debugger.
+#define VLD_OPT_REPORT_TO_FILE          0x8   //   If set, the memory leak report is sent to a file.
+#define VLD_OPT_SAFE_STACK_WALK         0x10  //   If set, the stack is walked using the "safe" method (StackWalk64).
+#define VLD_OPT_SELF_TEST               0x20  //   If set, peform a self-test to verify memory leak self-checking.
+#define VLD_OPT_SLOW_DEBUGGER_DUMP      0x40  //   If set, inserts a slight delay between sending output to the debugger.
+#define VLD_OPT_START_DISABLED          0x80  //   If set, memory leak detection will initially disabled.
+#define VLD_OPT_TRACE_INTERNAL_FRAMES   0x100 //   If set, include useless frames (e.g. internal to VLD) in call stacks.
+#define VLD_OPT_UNICODE_REPORT          0x200 //   If set, the leak report will be encoded UTF-16 instead of ASCII.
+#define VLD_OPT_VLDOFF                  0x400 //   If set, VLD will be completely deactivated. It will not attach to any modules.
+    static patchentry_t  m_patchtable [];     // Table of imports patched for attaching VLD to other modules.
+    FILE                *m_reportfile;        // File where the memory leak report may be sent to.
+    WCHAR                m_reportfilepath [MAX_PATH]; // Full path and name of file to send memory leak report to.
+    const char          *m_selftestfile;      // Filename where the memory leak self-test block is leaked.
+    int                  m_selftestline;      // Line number where the memory leak self-test block is leaked.
+    UINT32               m_status;            // Status flags:
+#define VLD_STATUS_DBGHELPLINKED        0x1   //   If set, the explicit dynamic link to the Debug Help Library succeeded.
+#define VLD_STATUS_INSTALLED            0x2   //   If set, VLD was successfully installed.
+#define VLD_STATUS_NEVER_ENABLED        0x4   //   If set, VLD started disabled, and has not yet been manually enabled.
+#define VLD_STATUS_FORCE_REPORT_TO_FILE 0x8   //   If set, the leak report is being forced to a file.
+    DWORD                m_tlsindex;          // Thread-local storage index.
+    CRITICAL_SECTION     m_tlslock;           // Protects accesses to the Set of TLS structures.
+    TlsSet              *m_tlsset;            // Set of all all thread-local storage structres for the process.
+    HMODULE              m_vldbase;           // Visual Leak Detector's own module handle (base address).
+
+    // The Visual Leak Detector APIs are our friends.
+    friend __declspec(dllexport) void VLDDisable ();
+    friend __declspec(dllexport) void VLDEnable ();
+};
+
+// Configuration option default values
+#define VLD_DEFAULT_MAX_DATA_DUMP    0xffffffff
+#define VLD_DEFAULT_MAX_TRACE_FRAMES 0xffffffff
+#define VLD_DEFAULT_REPORT_FILE_NAME L".\\memory_leak_report.txt"
diff --git a/development/Win32/vld/vld.ini b/development/Win32/vld/vld.ini
new file mode 100644 (file)
index 0000000..0029ef0
--- /dev/null
@@ -0,0 +1,156 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\r
+;;  $Id: vld.ini,v 1.7 2006/11/18 03:12:35 dmouldin Exp $\r
+;;\r
+;;  Visual Leak Detector - Initialization/Configuration File\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
+; Any options left blank or not present will revert to their default values.\r
+[Options]\r
+\r
+; The main on/off switch. If off, Visual Leak Detector will be completely\r
+; disabled. It will do nothing but print a message to the debugger indicating\r
+; that it has been turned off.\r
+;\r
+;  Valid Values: on, off\r
+;  Default: on\r
+;\r
+VLD = on\r
+\r
+; If yes, duplicate leaks (those that are identical) are not shown individually.\r
+; Only the first such leak is shown, along with a number indicating the total\r
+; number of duplicate leaks.\r
+;\r
+;   Valid Values: yes, no\r
+;   Default: no\r
+;\r
+AggregateDuplicates = no\r
+\r
+; Lists any additional modules to be included in memory leak detection. This can\r
+; be useful for checking for memory leaks in debug builds of 3rd party modules\r
+; which can not be easily rebuilt with '#include "vld.h"'. This option should be\r
+; used only if absolutely necessary and only if you really know what you are\r
+; doing.\r
+;\r
+;   CAUTION: Avoid listing any modules that link with the release CRT libraries.\r
+;     Only modules that link with the debug CRT libraries should be listed here.\r
+;     Doing otherwise might result in false memory leak reports or even crashes.\r
+;\r
+;   Valid Values: Any list containing module names (i.e. names of EXEs or DLLs).\r
+;   Default: None.\r
+;\r
+ForceIncludeModules =\r
+\r
+; Maximum number of data bytes to display for each leaked block. If zero, then\r
+; the data dump is completely suppressed and only call stacks are shown.\r
+; Limiting this to a low number can be useful if any of the leaked blocks are\r
+; very large and cause unnecessary clutter in the memory leak report.\r
+;\r
+;   Value Values: 0 - 4294967295\r
+;   Default: 4294967295\r
+;\r
+MaxDataDump = \r
+\r
+; Maximum number of call stack frames to trace back during leak detection.\r
+; Limiting this to a low number can reduce the CPU utilization overhead imposed\r
+; by memory leak detection, especially when using the slower "safe" stack\r
+; walking method (see StackWalkMethod below).\r
+;\r
+;   Valid Values: 1 - 4294967295\r
+;   Default: 4294967295\r
+;\r
+MaxTraceFrames = \r
+\r
+; Sets the type of encoding to use for the generated memory leak report. This\r
+; option is really only useful in conjuction with sending the report to a file.\r
+; Sending a Unicode encoded report to the debugger is not useful because the\r
+; debugger cannot display Unicode characters. Using Unicode encoding might be\r
+; useful if the data contained in leaked blocks is likely to consist of Unicode\r
+; text.\r
+;\r
+;   Valid Values: ascii, unicode\r
+;   Default: ascii\r
+;\r
+ReportEncoding = ascii\r
+\r
+; Sets the report file destination, if reporting to file is enabled. A relative\r
+; path may be specified and is considered relative to the process' working\r
+; directory.\r
+;\r
+;   Valid Values: Any valid path and filename.\r
+;   Default: .\memory_leak_report.txt\r
+;\r
+ReportFile = \r
+\r
+; Sets the report destination to either a file, the debugger, or both. If\r
+; reporting to file is enabled, the report is sent to the file specified by the\r
+; ReportFile option.\r
+;\r
+;   Valid Values: debugger, file, both\r
+;   Default: debugger\r
+;\r
+ReportTo = debugger\r
+\r
+; Turns on or off a self-test mode which is used to verify that VLD is able to\r
+; detect memory leaks in itself. Intended to be used for debugging VLD itself,\r
+; not for debugging other programs.\r
+;\r
+;   Valid Values: on, off\r
+;   Default: off\r
+;\r
+SelfTest = off\r
+\r
+; Selects the method to be used for walking the stack to obtain stack traces for\r
+; allocated memory blocks. The "fast" method may not always be able to\r
+; successfully trace completely through all call stacks. In such cases, the\r
+; "safe" method may prove to more reliably obtain the full stack trace. The\r
+; disadvantage is that the "safe" method is significantly slower than the "fast"\r
+; method and will probably result in very noticeable performance degradation of\r
+; the program being debugged.\r
+;\r
+;   Valid Values: fast, safe\r
+;   Default: fast\r
+; \r
+StackWalkMethod = fast\r
+\r
+; Determines whether memory leak detection should be initially enabled for all\r
+; threads, or whether it should be initially disabled for all threads. If set\r
+; to "yes", then any threads requiring memory leak detection to be enabled will\r
+; need to call VLDEnable at some point to enable leak detection for those\r
+; threads.\r
+;\r
+;   Valid Values: yes, no\r
+;   Default: no\r
+;\r
+StartDisabled = no\r
+\r
+; Determines whether or not all frames, including frames internal to the heap,\r
+; are traced. There will always be a number of frames internal to Visual Leak\r
+; Detector and C/C++ or Win32 heap APIs that aren't generally useful for\r
+; determining the cause of a leak. Normally these frames are skipped during the\r
+; stack trace, which somewhat reduces the time spent tracing and amount of data\r
+; collected and stored in memory. Including all frames in the stack trace, all\r
+; the way down into VLD's own code can, however, be useful for debugging VLD\r
+; itself.\r
+;\r
+;   Valid Values: yes, no\r
+;   Default: no\r
+;\r
+TraceInternalFrames = no\r