]> git.lyx.org Git - lyx.git/blob - development/Win32/vld/src/vld.cpp
add leak tool for msvc 'Visual Leak Detection' 1.9f: original files
[lyx.git] / development / Win32 / vld / src / vld.cpp
1 ////////////////////////////////////////////////////////////////////////////////
2 //  $Id: vld.cpp,v 1.69 2006/11/18 05:07:04 dmouldin Exp $
3 //
4 //  Visual Leak Detector - VisualLeakDetector Class Implementation
5 //  Copyright (c) 2005-2006 Dan Moulding
6 //
7 //  This library is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU Lesser General Public
9 //  License as published by the Free Software Foundation; either
10 //  version 2.1 of the License, or (at your option) any later version.
11 //
12 //  This library is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 //  Lesser General Public License for more details.
16 //
17 //  You should have received a copy of the GNU Lesser General Public
18 //  License along with this library; if not, write to the Free Software
19 //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 //
21 //  See COPYING.txt for the full terms of the GNU Lesser General Public License.
22 //
23 ////////////////////////////////////////////////////////////////////////////////
24
25 #pragma comment(lib, "dbghelp.lib")
26
27 #include <cassert>
28 #include <cerrno>
29 #include <cstdio>
30 #include <sys/stat.h>
31 #include <windows.h>
32 #define __out_xcount(x) // Workaround for the specstrings.h bug in the Platform SDK.
33 #define DBGHELP_TRANSLATE_TCHAR
34 #include <dbghelp.h>    // Provides symbol handling services.
35 #define VLDBUILD        // Declares that we are building Visual Leak Detector.
36 #include "callstack.h"  // Provides a class for handling call stacks.
37 #include "map.h"        // Provides a lightweight STL-like map template.
38 #include "ntapi.h"      // Provides access to NT APIs.
39 #include "set.h"        // Provides a lightweight STL-like set template.
40 #include "utility.h"    // Provides various utility functions.
41 #include "vldheap.h"    // Provides internal new and delete operators.
42 #include "vldint.h"     // Provides access to the Visual Leak Detector internals.
43
44 #define BLOCKMAPRESERVE     64  // This should strike a balance between memory use and a desire to minimize heap hits.
45 #define HEAPMAPRESERVE      2   // Usually there won't be more than a few heaps in the process, so this should be small.
46 #define MAXSYMBOLNAMELENGTH 256 // Maximum symbol name length that we will allow. Longer names will be truncated.
47 #define MODULESETRESERVE    16  // There are likely to be several modules loaded in the process.
48
49 // Imported global variables.
50 extern vldblockheader_t *vldblocklist;
51 extern HANDLE            vldheap;
52 extern CRITICAL_SECTION  vldheaplock;
53
54 // Global variables.
55 HANDLE           currentprocess; // Pseudo-handle for the current process.
56 HANDLE           currentthread;  // Pseudo-handle for the current thread.
57 CRITICAL_SECTION imagelock;      // Serializes calls to the Debug Help Library PE image access APIs.
58 HANDLE           processheap;    // Handle to the process's heap (COM allocations come from here).
59 CRITICAL_SECTION stackwalklock;  // Serializes calls to StackWalk64 from the Debug Help Library.
60 CRITICAL_SECTION symbollock;     // Serializes calls to the Debug Help Library symbold handling APIs.
61
62 // Function pointer types for explicit dynamic linking with functions listed in
63 // the import patch table.
64 typedef void* (__cdecl *_calloc_dbg_t) (size_t, size_t, int, const char*, int);
65 typedef void* (__cdecl *_malloc_dbg_t) (size_t, int, const char *, int);
66 typedef void* (__cdecl *_realloc_dbg_t) (void *, size_t, int, const char *, int);
67 typedef void* (__cdecl *calloc_t) (size_t, size_t);
68 typedef HRESULT (__stdcall *CoGetMalloc_t) (DWORD, LPMALLOC *);
69 typedef LPVOID (__stdcall *CoTaskMemAlloc_t) (ULONG);
70 typedef LPVOID (__stdcall *CoTaskMemRealloc_t) (LPVOID, ULONG);
71 typedef void* (__cdecl *crt_new_dbg_t) (unsigned int, int, const char *, int);
72 typedef void* (__cdecl *malloc_t) (size_t);
73 typedef void* (__cdecl *mfc_new_dbg_t) (unsigned int, const char *, int);
74 typedef void* (__cdecl *new_t) (unsigned int);
75 typedef void* (__cdecl *realloc_t) (void *, size_t);
76
77 // Global function pointers for explicit dynamic linking with functions listed
78 // in the import patch table. Using explicit dynamic linking minimizes VLD's
79 // footprint by loading only modules that are actually used. These pointers will
80 // be linked to the real functions the first time they are used.
81 static CoGetMalloc_t      pCoGetMalloc            = NULL;
82 static CoTaskMemAlloc_t   pCoTaskMemAlloc         = NULL;
83 static CoTaskMemRealloc_t pCoTaskMemRealloc       = NULL;
84 static _calloc_dbg_t      pcrt80d__calloc_dbg     = NULL;
85 static _malloc_dbg_t      pcrt80d__malloc_dbg     = NULL;
86 static _realloc_dbg_t     pcrt80d__realloc_dbg    = NULL;
87 static crt_new_dbg_t      pcrt80d__scalar_new_dbg = NULL;
88 static crt_new_dbg_t      pcrt80d__vector_new_dbg = NULL;
89 static calloc_t           pcrt80d_calloc          = NULL;
90 static malloc_t           pcrt80d_malloc          = NULL;
91 static realloc_t          pcrt80d_realloc         = NULL;
92 static new_t              pcrt80d_scalar_new      = NULL;
93 static new_t              pcrt80d_vector_new      = NULL;
94 static _calloc_dbg_t      pcrtd__calloc_dbg       = NULL;
95 static _malloc_dbg_t      pcrtd__malloc_dbg       = NULL;
96 static _realloc_dbg_t     pcrtd__realloc_dbg      = NULL;
97 static crt_new_dbg_t      pcrtd__scalar_new_dbg   = NULL;
98 static calloc_t           pcrtd_calloc            = NULL;
99 static malloc_t           pcrtd_malloc            = NULL;
100 static realloc_t          pcrtd_realloc           = NULL;
101 static new_t              pcrtd_scalar_new        = NULL;
102 static mfc_new_dbg_t      pmfc42d__scalar_new_dbg = NULL;
103 static new_t              pmfc42d_scalar_new      = NULL;
104 static mfc_new_dbg_t      pmfc80d__scalar_new_dbg = NULL;
105 static mfc_new_dbg_t      pmfc80d__vector_new_dbg = NULL;
106 static new_t              pmfc80d_scalar_new      = NULL;
107 static new_t              pmfc80d_vector_new      = NULL;
108
109 // The one and only VisualLeakDetector object instance.
110 __declspec(dllexport) VisualLeakDetector vld;
111
112 // The import patch table: lists the heap-related API imports that VLD patches
113 // through to replacement functions provided by VLD. Having this table simply
114 // makes it more convenient to add additional IAT patches.
115 patchentry_t VisualLeakDetector::m_patchtable [] = {
116     // Win32 heap APIs.
117     "kernel32.dll", "GetProcAddress",     0x0, _GetProcAddress, // Not heap related, but can be used to obtain pointers to heap functions.
118     "kernel32.dll", "HeapAlloc",          0x0, _RtlAllocateHeap,
119     "kernel32.dll", "HeapCreate",         0x0, _HeapCreate,
120     "kernel32.dll", "HeapDestroy",        0x0, _HeapDestroy,
121     "kernel32.dll", "HeapFree",           0x0, _RtlFreeHeap,
122     "kernel32.dll", "HeapReAlloc",        0x0, _RtlReAllocateHeap,
123
124     // MFC new operators (exported by ordinal).
125     "mfc42d.dll",   (LPCSTR)714,          0x0, _mfc42d__scalar_new_dbg,
126     "mfc42d.dll",   (LPCSTR)711,          0x0, _mfc42d_scalar_new,
127     // XXX MFC 7.x DLL new operators still need to be added to this
128     //   table, but I don't know their ordinals.
129     "mfc80d.dll",   (LPCSTR)895,          0x0, _mfc80d__scalar_new_dbg,
130     "mfc80d.dll",   (LPCSTR)269,          0x0, _mfc80d__vector_new_dbg,
131     "mfc80d.dll",   (LPCSTR)893,          0x0, _mfc80d_scalar_new,
132     "mfc80d.dll",   (LPCSTR)267,          0x0, _mfc80d_vector_new,
133
134     // CRT new operators and heap APIs.
135     "msvcr80d.dll", "_calloc_dbg",        0x0, _crt80d__calloc_dbg,
136     "msvcr80d.dll", "_malloc_dbg",        0x0, _crt80d__malloc_dbg,
137     "msvcr80d.dll", "_realloc_dbg",       0x0, _crt80d__realloc_dbg,
138     "msvcr80d.dll", "??2@YAPAXIHPBDH@Z",  0x0, _crt80d__scalar_new_dbg,
139     "msvcr80d.dll", "??_U@YAPAXIHPBDH@Z", 0x0, _crt80d__vector_new_dbg,
140     "msvcr80d.dll", "calloc",             0x0, _crt80d_calloc,
141     "msvcr80d.dll", "malloc",             0x0, _crt80d_malloc,
142     "msvcr80d.dll", "realloc",            0x0, _crt80d_realloc,
143     "msvcr80d.dll", "??2@YAPAXI@Z",       0x0, _crt80d_scalar_new,
144     "msvcr80d.dll", "??_U@YAPAXI@Z",      0x0, _crt80d_vector_new,
145     "msvcrtd.dll",  "_calloc_dbg",        0x0, _crtd__calloc_dbg,
146     "msvcrtd.dll",  "_malloc_dbg",        0x0, _crtd__malloc_dbg,
147     "msvcrtd.dll",  "??2@YAPAXIHPBDH@Z",  0x0, _crtd__scalar_new_dbg,
148     "msvcrtd.dll",  "_realloc_dbg",       0x0, _crtd__realloc_dbg,
149     "msvcrtd.dll",  "calloc",             0x0, _crtd_calloc,
150     "msvcrtd.dll",  "malloc",             0x0, _crtd_malloc,
151     "msvcrtd.dll",  "realloc",            0x0, _crtd_realloc,
152     "msvcrtd.dll",  "??2@YAPAXI@Z",       0x0, _crtd_scalar_new,
153
154     // NT APIs.
155     "ntdll.dll",    "RtlAllocateHeap",    0x0, _RtlAllocateHeap,
156     "ntdll.dll",    "RtlFreeHeap",        0x0, _RtlFreeHeap,
157     "ntdll.dll",    "RtlReAllocateHeap",  0x0, _RtlReAllocateHeap,
158
159     // COM heap APIs.
160     "ole32.dll",    "CoGetMalloc",        0x0, _CoGetMalloc,
161     "ole32.dll",    "CoTaskMemAlloc",     0x0, _CoTaskMemAlloc,
162     "ole32.dll",    "CoTaskMemRealloc",   0x0, _CoTaskMemRealloc
163 };
164
165 // Constructor - Initializes private data, loads configuration options, and
166 //   attaches Visual Leak Detector to all other modules loaded into the current
167 //   process.
168 //
169 VisualLeakDetector::VisualLeakDetector ()
170 {
171     WCHAR      bom = BOM; // Unicode byte-order mark.
172     HMODULE    kernel32;
173     ModuleSet *newmodules;
174     HMODULE    ntdll;
175     LPWSTR     symbolpath;
176
177     // Initialize configuration options and related private data.
178     _wcsnset_s(m_forcedmodulelist, MAXMODULELISTLENGTH, '\0', _TRUNCATE);
179     m_maxdatadump    = 0xffffffff;
180     m_maxtraceframes = 0xffffffff;
181     m_options        = 0x0;
182     m_reportfile     = NULL;
183     wcsncpy_s(m_reportfilepath, MAX_PATH, VLD_DEFAULT_REPORT_FILE_NAME, _TRUNCATE);
184     m_status         = 0x0;
185
186     // Load configuration options.
187     configure();
188     if (m_options & VLD_OPT_VLDOFF) {
189         report(L"Visual Leak Detector is turned off.\n");
190         return;
191     }
192
193     kernel32 = GetModuleHandle(L"kernel32.dll");
194     ntdll = GetModuleHandle(L"ntdll.dll");
195
196     // Initialize global variables.
197     currentprocess    = GetCurrentProcess();
198     currentthread     = GetCurrentThread();
199     InitializeCriticalSection(&imagelock);
200     LdrLoadDll        = (LdrLoadDll_t)GetProcAddress(ntdll, "LdrLoadDll");
201     processheap       = GetProcessHeap();
202     RtlAllocateHeap   = (RtlAllocateHeap_t)GetProcAddress(ntdll, "RtlAllocateHeap");
203     RtlFreeHeap       = (RtlFreeHeap_t)GetProcAddress(ntdll, "RtlFreeHeap");
204     RtlReAllocateHeap = (RtlReAllocateHeap_t)GetProcAddress(ntdll, "RtlReAllocateHeap");
205     InitializeCriticalSection(&stackwalklock);
206     InitializeCriticalSection(&symbollock);
207     vldheap           = HeapCreate(0x0, 0, 0);
208     InitializeCriticalSection(&vldheaplock);
209
210     // Initialize remaining private data.
211     m_heapmap         = new HeapMap;
212     m_heapmap->reserve(HEAPMAPRESERVE);
213     m_imalloc         = NULL;
214     m_leaksfound      = 0;
215     m_loadedmodules   = NULL;
216     InitializeCriticalSection(&m_loaderlock);
217     InitializeCriticalSection(&m_maplock);
218     InitializeCriticalSection(&m_moduleslock);
219     m_selftestfile    = __FILE__;
220     m_selftestline    = 0;
221     m_tlsindex        = TlsAlloc();
222     InitializeCriticalSection(&m_tlslock);
223     m_tlsset          = new TlsSet;
224
225     if (m_options & VLD_OPT_SELF_TEST) {
226         // Self-test mode has been enabled. Intentionally leak a small amount of
227         // memory so that memory leak self-checking can be verified.
228         if (m_options & VLD_OPT_UNICODE_REPORT) {
229             wcsncpy_s(new WCHAR [wcslen(SELFTESTTEXTW) + 1], wcslen(SELFTESTTEXTW) + 1, SELFTESTTEXTW, _TRUNCATE);
230             m_selftestline = __LINE__ - 1;
231         }
232         else {
233             strncpy_s(new CHAR [strlen(SELFTESTTEXTA) + 1], strlen(SELFTESTTEXTA) + 1, SELFTESTTEXTA, _TRUNCATE);
234             m_selftestline = __LINE__ - 1;
235         }
236     }
237     if (m_options & VLD_OPT_START_DISABLED) {
238         // Memory leak detection will initially be disabled.
239         m_status |= VLD_STATUS_NEVER_ENABLED;
240     }
241     if (m_options & VLD_OPT_REPORT_TO_FILE) {
242         // Reporting to file enabled.
243         if (m_options & VLD_OPT_UNICODE_REPORT) {
244             // Unicode data encoding has been enabled. Write the byte-order
245             // mark before anything else gets written to the file. Open the
246             // file for binary writing.
247             if (_wfopen_s(&m_reportfile, m_reportfilepath, L"wb") == EINVAL) {
248                 // Couldn't open the file.
249                 m_reportfile = NULL;
250             }
251             else {
252                 fwrite(&bom, sizeof(WCHAR), 1, m_reportfile);
253                 setreportencoding(unicode);
254             }
255         }
256         else {
257             // Open the file in text mode for ASCII output.
258             if (_wfopen_s(&m_reportfile, m_reportfilepath, L"w") == EINVAL) {
259                 // Couldn't open the file.
260                 m_reportfile = NULL;
261             }
262             else {
263                 setreportencoding(ascii);
264             }
265         }
266         if (m_reportfile == NULL) {
267             report(L"WARNING: Visual Leak Detector: Couldn't open report file for writing: %s\n"
268                    L"  The report will be sent to the debugger instead.\n", m_reportfilepath);
269         }
270         else {
271             // Set the "report" function to write to the file.
272             setreportfile(m_reportfile, m_options & VLD_OPT_REPORT_TO_DEBUGGER);
273         }
274     }
275     if (m_options & VLD_OPT_SLOW_DEBUGGER_DUMP) {
276         // Insert a slight delay between messages sent to the debugger for
277         // output. (For working around a bug in VC6 where data sent to the
278         // debugger gets lost if it's sent too fast).
279         insertreportdelay();
280     }
281
282     // This is highly unlikely to happen, but just in case, check to be sure
283     // we got a valid TLS index.
284     if (m_tlsindex == TLS_OUT_OF_INDEXES) {
285         report(L"ERROR: Visual Leak Detector could not be installed because thread local"
286                L"  storage could not be allocated.");
287         return;
288     }
289
290     // Initialize the symbol handler. We use it for obtaining source file/line
291     // number information and function names for the memory leak report.
292     symbolpath = buildsymbolsearchpath();
293     SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
294     if (!SymInitializeW(currentprocess, symbolpath, FALSE)) {
295         report(L"WARNING: Visual Leak Detector: The symbol handler failed to initialize (error=%lu).\n"
296                L"    File and function names will probably not be available in call stacks.\n", GetLastError());
297     }
298     delete [] symbolpath;
299
300     // Patch into kernel32.dll's calls to LdrLoadDll so that VLD can
301     // dynamically attach to new modules loaded during runtime.
302     patchimport(kernel32, ntdll, "ntdll.dll", "LdrLoadDll", _LdrLoadDll);
303
304     // Attach Visual Leak Detector to every module loaded in the process.
305     newmodules = new ModuleSet;
306     newmodules->reserve(MODULESETRESERVE);
307     EnumerateLoadedModulesW64(currentprocess, addloadedmodule, newmodules);
308     attachtoloadedmodules(newmodules);
309     m_loadedmodules = newmodules;
310     m_status |= VLD_STATUS_INSTALLED;
311
312     report(L"Visual Leak Detector Version " VLDVERSION L" installed.\n");
313     if (m_status & VLD_STATUS_FORCE_REPORT_TO_FILE) {
314         // The report is being forced to a file. Let the human know why.
315         report(L"NOTE: Visual Leak Detector: Unicode-encoded reporting has been enabled, but the\n"
316                L"  debugger is the only selected report destination. The debugger cannot display\n"
317                L"  Unicode characters, so the report will also be sent to a file. If no file has\n"
318                L"  been specified, the default file name is \"" VLD_DEFAULT_REPORT_FILE_NAME L"\".\n");
319
320     }
321     reportconfig();
322 }
323
324 // Destructor - Detaches Visual Leak Detector from all modules loaded in the
325 //   process, frees internally allocated resources, and generates the memory
326 //   leak report.
327 //
328 VisualLeakDetector::~VisualLeakDetector ()
329 {
330     BlockMap::Iterator   blockit;
331     BlockMap            *blockmap;
332     size_t               count;
333     DWORD                exitcode;
334     vldblockheader_t    *header;
335     HANDLE               heap;
336     HeapMap::Iterator    heapit;
337     SIZE_T               internalleaks = 0;
338     const char          *leakfile = NULL;
339     WCHAR                leakfilew [MAX_PATH];
340     int                  leakline = 0;
341     ModuleSet::Iterator  moduleit;
342     SIZE_T               sleepcount;
343     HANDLE               thread;
344     BOOL                 threadsactive= FALSE;
345     TlsSet::Iterator     tlsit;
346
347     if (m_options & VLD_OPT_VLDOFF) {
348         // VLD has been turned off.
349         return;
350     }
351
352     if (m_status & VLD_STATUS_INSTALLED) {
353         // Detach Visual Leak Detector from all previously attached modules.
354         EnumerateLoadedModulesW64(currentprocess, detachfrommodule, NULL);
355
356         // See if any threads that have ever entered VLD's code are still active.
357         EnterCriticalSection(&m_tlslock);
358         for (tlsit = m_tlsset->begin(); tlsit != m_tlsset->end(); ++tlsit) {
359             if ((*tlsit)->threadid == GetCurrentThreadId()) {
360                 // Don't wait for the current thread to exit.
361                 continue;
362             }
363
364             sleepcount = 0;
365             thread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, (*tlsit)->threadid);
366             if (thread == NULL) {
367                 // Couldn't query this thread. We'll assume that it exited.
368                 continue; // XXX should we check GetLastError()?
369             }
370             while (GetExitCodeThread(thread, &exitcode) == TRUE) {
371                 if (exitcode != STILL_ACTIVE) {
372                     // This thread exited.
373                     break;
374                 }
375                 else {
376                     // There is still at least one other thread running. The CRT
377                     // will stomp it dead when it cleans up, which is not a
378                     // graceful way for a thread to go down. Warn about this,
379                     // and wait until the thread has exited so that we know it
380                     // can't still be off running somewhere in VLD's code.
381                     threadsactive = TRUE;
382                     Sleep(100);
383                     sleepcount++;
384                     if ((sleepcount % 100) == 0) {
385                         // Just in case this takes a long time, let the human
386                         // know we are still here and alive.
387                         report(L"Visual Leak Detector: Waiting for threads to terminate...\n");
388                     }
389                 }
390             }
391         }
392         LeaveCriticalSection(&m_tlslock);
393
394         if (m_status & VLD_STATUS_NEVER_ENABLED) {
395             // Visual Leak Detector started with leak detection disabled and
396             // it was never enabled at runtime. A lot of good that does.
397             report(L"WARNING: Visual Leak Detector: Memory leak detection was never enabled.\n");
398         }
399         else {
400             // Generate a memory leak report for each heap in the process.
401             for (heapit = m_heapmap->begin(); heapit != m_heapmap->end(); ++heapit) {
402                 heap = (*heapit).first;
403                 reportleaks(heap);
404             }
405
406             // Show a summary.
407             if (m_leaksfound == 0) {
408                 report(L"No memory leaks detected.\n");
409             }
410             else {
411                 report(L"Visual Leak Detector detected %lu memory leak", m_leaksfound);
412                 report((m_leaksfound > 1) ? L"s.\n" : L".\n");
413             }
414         }
415
416         // Free resources used by the symbol handler.
417         if (!SymCleanup(currentprocess)) {
418             report(L"WARNING: Visual Leak Detector: The symbol handler failed to deallocate resources (error=%lu).\n",
419                    GetLastError());
420         }
421
422         // Free internally allocated resources used by the heapmap and blockmap.
423         for (heapit = m_heapmap->begin(); heapit != m_heapmap->end(); ++heapit) {
424             blockmap = &(*heapit).second->blockmap;
425             for (blockit = blockmap->begin(); blockit != blockmap->end(); ++blockit) {
426                 delete (*blockit).second->callstack;
427                 delete (*blockit).second;
428             }
429             delete blockmap;
430         }
431         delete m_heapmap;
432
433         // Free internally allocated resources used by the loaded module set.
434         for (moduleit = m_loadedmodules->begin(); moduleit != m_loadedmodules->end(); ++moduleit) {
435             delete (*moduleit).name;
436             delete (*moduleit).path;
437         }
438         delete m_loadedmodules;
439
440         // Free internally allocated resources used for thread local storage.
441         for (tlsit = m_tlsset->begin(); tlsit != m_tlsset->end(); ++tlsit) {
442             delete *tlsit;
443         }
444         delete m_tlsset;
445
446         // Do a memory leak self-check.
447         header = vldblocklist;
448         while (header) {
449             // Doh! VLD still has an internally allocated block!
450             // This won't ever actually happen, right guys?... guys?
451             internalleaks++;
452             leakfile = header->file;
453             leakline = header->line;
454             mbstowcs_s(&count, leakfilew, MAX_PATH, leakfile, _TRUNCATE);
455             report(L"ERROR: Visual Leak Detector: Detected a memory leak internal to Visual Leak Detector!!\n");
456             report(L"---------- Block %ld at " ADDRESSFORMAT L": %u bytes ----------\n", header->serialnumber,
457                    VLDBLOCKDATA(header), header->size);
458             report(L"  Call Stack:\n");
459             report(L"    %s (%d): Full call stack not available.\n", leakfilew, leakline);
460             if (m_maxdatadump != 0) {
461                 report(L"  Data:\n");
462                 if (m_options & VLD_OPT_UNICODE_REPORT) {
463                     dumpmemoryw(VLDBLOCKDATA(header), (m_maxdatadump < header->size) ? m_maxdatadump : header->size);
464                 }
465                 else {
466                     dumpmemorya(VLDBLOCKDATA(header), (m_maxdatadump < header->size) ? m_maxdatadump : header->size);
467                 }
468             }
469             report(L"\n");
470             header = header->next;
471         }
472         if (m_options & VLD_OPT_SELF_TEST) {
473             if ((internalleaks == 1) && (strcmp(leakfile, m_selftestfile) == 0) && (leakline == m_selftestline)) {
474                 report(L"Visual Leak Detector passed the memory leak self-test.\n");
475             }
476             else {
477                 report(L"ERROR: Visual Leak Detector: Failed the memory leak self-test.\n");
478             }
479         }
480
481         if (threadsactive == TRUE) {
482             report(L"WARNING: Visual Leak Detector: Some threads appear to have not terminated normally.\n"
483                 L"  This could cause inaccurate leak detection results, including false positives.\n");
484         }
485         report(L"Visual Leak Detector is now exiting.\n");
486     }
487     else {
488         // VLD failed to load properly.
489         delete m_heapmap;
490         delete m_tlsset;
491     }
492     HeapDestroy(vldheap);
493
494     DeleteCriticalSection(&imagelock);
495     DeleteCriticalSection(&m_loaderlock);
496     DeleteCriticalSection(&m_maplock);
497     DeleteCriticalSection(&m_moduleslock);
498     DeleteCriticalSection(&stackwalklock);
499     DeleteCriticalSection(&symbollock);
500     DeleteCriticalSection(&vldheaplock);
501
502     if (m_tlsindex != TLS_OUT_OF_INDEXES) {
503         TlsFree(m_tlsindex);
504     }
505
506     if (m_reportfile != NULL) {
507         fclose(m_reportfile);
508     }
509 }
510
511 // _CoGetMalloc - Calls to CoGetMalloc are patched through to this function.
512 //   This function returns a pointer to Visual Leak Detector's implementation
513 //   of the IMalloc interface, instead of returning a pointer to the system
514 //   implementation. This allows VLD's implementation of the IMalloc interface
515 //   (which is basically a thin wrapper around the system implementation) to be
516 //   invoked in place of the system implementation.
517 //
518 //  - context (IN): Reserved; value must be 1.
519 //
520 //  - imalloc (IN): Address of a pointer to receive the address of VLD's
521 //      implementation of the IMalloc interface.
522 //
523 //  Return Value:
524 //
525 //    Always returns S_OK.
526 //
527 HRESULT VisualLeakDetector::_CoGetMalloc (DWORD context, LPMALLOC *imalloc)
528 {
529     HMODULE ole32;
530
531     *imalloc = (LPMALLOC)&vld;
532
533     if (pCoGetMalloc == NULL) {
534         // This is the first call to this function. Link to the real
535         // CoGetMalloc and get a pointer to the system implementation of the
536         // IMalloc interface.
537         ole32 = GetModuleHandle(L"ole32.dll");
538         pCoGetMalloc = (CoGetMalloc_t)GetProcAddress(ole32, "CoGetMalloc");
539         pCoGetMalloc(context, &vld.m_imalloc);
540     }
541
542     return S_OK;
543 }
544
545 // _CoTaskMemAlloc - Calls to CoTaskMemAlloc are patched through to this
546 //   function. This function is just a wrapper around the real CoTaskMemAlloc
547 //   that sets appropriate flags to be consulted when the memory is actually
548 //   allocated by RtlAllocateHeap.
549 //
550 //  - size (IN): Size of the memory block to allocate.
551 //
552 //  Return Value:
553 //
554 //    Returns the value returned from CoTaskMemAlloc.
555 //
556 LPVOID VisualLeakDetector::_CoTaskMemAlloc (ULONG size)
557 {
558     LPVOID   block;
559     SIZE_T   fp;
560     HMODULE  ole32;
561     tls_t   *tls = vld.gettls();
562
563     if (tls->addrfp == 0x0) {
564         // This is the first call to enter VLD for the current allocation.
565         // Record the current frame pointer.
566         FRAMEPOINTER(fp);
567         tls->addrfp = fp;
568     }
569
570     if (pCoTaskMemAlloc == NULL) {
571         // This is the first call to this function. Link to the real
572         // CoTaskMemAlloc.
573         ole32 = GetModuleHandle(L"ole32.dll");
574         pCoTaskMemAlloc = (CoTaskMemAlloc_t)GetProcAddress(ole32, "CoTaskMemAlloc");
575     }
576
577     // Do the allocation. The block will be mapped by _RtlAllocateHeap.
578     block = pCoTaskMemAlloc(size);
579
580     // Reset thread local flags and variables for the next allocation.
581     tls->addrfp = 0x0;
582     tls->flags &= ~VLD_TLS_CRTALLOC;
583     
584     return block;
585 }
586
587 // _CoTaskMemRealloc - Calls to CoTaskMemRealloc are patched through to this
588 //   function. This function is just a wrapper around the real CoTaskMemRealloc
589 //   that sets appropriate flags to be consulted when the memory is actually
590 //   allocated by RtlAllocateHeap.
591 //
592 //  - mem (IN): Pointer to the memory block to reallocate.
593 //
594 //  - size (IN): Size, in bytes, of the block to reallocate.
595 //
596 //  Return Value:
597 //
598 //    Returns the value returned from CoTaskMemRealloc.
599 //
600 LPVOID VisualLeakDetector::_CoTaskMemRealloc (LPVOID mem, ULONG size)
601 {
602     LPVOID   block;
603     SIZE_T   fp;
604     HMODULE  ole32;
605     tls_t   *tls = vld.gettls();
606
607     if (tls->addrfp == 0x0) {
608         // This is the first call to enter VLD for the current allocation.
609         // Record the current frame pointer.
610         FRAMEPOINTER(fp);
611         tls->addrfp = fp;
612     }
613
614     if (pCoTaskMemRealloc == NULL) {
615         // This is the first call to this function. Link to the real
616         // CoTaskMemRealloc.
617         ole32 = GetModuleHandle(L"ole32.dll");
618         pCoTaskMemRealloc = (CoTaskMemRealloc_t)GetProcAddress(ole32, "CoTaskMemRealloc");
619     }
620
621     // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
622     block = pCoTaskMemRealloc(mem, size);
623
624     // Reset thread local flags and variables for the next allocation.
625     tls->addrfp = 0x0;
626     tls->flags &= ~VLD_TLS_CRTALLOC;
627
628     return block;
629 }
630
631 // _crt80d__calloc_dbg - Calls to _calloc_dbg from msvcr80d.dll are patched
632 //   through to this function. This function is just a wrapper around the real
633 //   _calloc_dbg that sets appropriate flags to be consulted when the memory is
634 //   actually allocated by RtlAllocateHeap.
635 //
636 //  - size (IN): The size, in bytes, of the memory block to be allocated.
637 //
638 //  - type (IN): The CRT "use type" of the block to be allocated.
639 //
640 //  - file (IN): The name of the file from which this function is being called.
641 //
642 //  - line (IN): The line number, in the above file, at which this function is
643 //      being called.
644 //
645 //  Return Value:
646 //
647 //    Returns the value returned by _calloc_dbg.
648 //
649 void* VisualLeakDetector::_crt80d__calloc_dbg (size_t num, size_t size, int type, const char *file, int line)
650 {
651     void    *block;
652     SIZE_T   fp;
653     HMODULE  msvcr80d;
654     tls_t   *tls = vld.gettls();
655
656     // _malloc_dbg is a CRT function and allocates from the CRT heap.
657     tls->flags |= VLD_TLS_CRTALLOC;
658
659     if (tls->addrfp == 0x0) {
660         // This is the first call to enter VLD for the current allocation.
661         // Record the current frame pointer.
662         FRAMEPOINTER(fp);
663         tls->addrfp = fp;
664     }
665
666     if (pcrt80d__calloc_dbg == NULL) {
667         // This is the first call to this function. Link to the real
668         // _malloc_dbg.
669         msvcr80d = GetModuleHandle(L"msvcr80d.dll");
670         pcrt80d__calloc_dbg = (_calloc_dbg_t)GetProcAddress(msvcr80d, "_calloc_dbg");
671     }
672
673     // Do the allocation. The block will be mapped by _RtlAllocateHeap.
674     block = pcrt80d__calloc_dbg(num, size, type, file, line);
675
676     // Reset thread local flags and variables for the next allocation.
677     tls->addrfp = 0x0;
678     tls->flags &= ~VLD_TLS_CRTALLOC;
679
680     return block;
681 }
682
683 // _crt80d__malloc_dbg - Calls to _malloc_dbg from msvcr80d.dll are patched
684 //   through to this function. This function is just a wrapper around the real
685 //   _malloc_dbg that sets appropriate flags to be consulted when the memory is
686 //   actually allocated by RtlAllocateHeap.
687 //
688 //  - size (IN): The size, in bytes, of the memory block to be allocated.
689 //
690 //  - type (IN): The CRT "use type" of the block to be allocated.
691 //
692 //  - file (IN): The name of the file from which this function is being called.
693 //
694 //  - line (IN): The line number, in the above file, at which this function is
695 //      being called.
696 //
697 //  Return Value:
698 //
699 //    Returns the value returned by _malloc_dbg.
700 //
701 void* VisualLeakDetector::_crt80d__malloc_dbg (size_t size, int type, const char *file, int line)
702 {
703     void    *block;
704     SIZE_T   fp;
705     HMODULE  msvcr80d;
706     tls_t   *tls = vld.gettls();
707
708     // _malloc_dbg is a CRT function and allocates from the CRT heap.
709     tls->flags |= VLD_TLS_CRTALLOC;
710
711     if (tls->addrfp == 0x0) {
712         // This is the first call to enter VLD for the current allocation.
713         // Record the current frame pointer.
714         FRAMEPOINTER(fp);
715         tls->addrfp = fp;
716     }
717
718     if (pcrt80d__malloc_dbg == NULL) {
719         // This is the first call to this function. Link to the real
720         // _malloc_dbg.
721         msvcr80d = GetModuleHandle(L"msvcr80d.dll");
722         pcrt80d__malloc_dbg = (_malloc_dbg_t)GetProcAddress(msvcr80d, "_malloc_dbg");
723     }
724
725     // Do the allocation. The block will be mapped by _RtlAllocateHeap.
726     block = pcrt80d__malloc_dbg(size, type, file, line);
727
728     // Reset thread local flags and variables for the next allocation.
729     tls->addrfp = 0x0;
730     tls->flags &= ~VLD_TLS_CRTALLOC;
731
732     return block;
733 }
734
735 // _crt80d__realloc_dbg - Calls to _realloc_dbg from msvcr80d.dll are patched
736 //   through to this function. This function is just a wrapper around the real
737 //   _realloc_dbg that sets appropriate flags to be consulted when the memory is
738 //   actually allocated by RtlAllocateHeap.
739 //
740 //  - mem (IN): Pointer to the memory block to be reallocated.
741 //
742 //  - size (IN): The size of the memory block to reallocate.
743 //
744 //  - type (IN): The CRT "use type" of the block to be reallocated.
745 //
746 //  - file (IN): The name of the file from which this function is being called.
747 //
748 //  - line (IN): The line number, in the above filel, at which this function is
749 //      being called.
750 //
751 //  Return Value:
752 //
753 //    Returns the value returned by _realloc_dbg.
754 //
755 void* VisualLeakDetector::_crt80d__realloc_dbg (void *mem, size_t size, int type, const char *file, int line)
756 {
757     void    *block;
758     SIZE_T   fp;
759     HMODULE  msvcr80d;
760     tls_t   *tls = vld.gettls();
761
762     // _realloc_dbg is a CRT function and allocates from the CRT heap.
763     tls->flags |= VLD_TLS_CRTALLOC;
764
765     if (tls->addrfp == 0x0) {
766         // This is the first call to enter VLD for the current allocation.
767         // Record the current frame pointer.
768         FRAMEPOINTER(fp);
769         tls->addrfp = fp;
770     }
771
772     if (pcrt80d__realloc_dbg == NULL) {
773         // This is the first call to this function. Link to the real
774         // _realloc_dbg.
775         msvcr80d = GetModuleHandle(L"msvcr80d.dll");
776         pcrt80d__realloc_dbg = (_realloc_dbg_t)GetProcAddress(msvcr80d, "_realloc_dbg");
777     }
778
779     // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
780     block = pcrt80d__realloc_dbg(mem, size, type, file, line);
781
782     // Reset thread local flags and variables for the next allocation.
783     tls->addrfp = 0x0;
784     tls->flags &= ~VLD_TLS_CRTALLOC;
785
786     return block;
787 }
788
789 // _crt80d__scalar_new_dbg - Calls to the CRT's debug scalar new operator from
790 //   msvcr80d.dll are patched through to this function. This function is just a
791 //   wrapper around the real CRT debug scalar new operator that sets appropriate
792 //   flags to be consulted when the memory is actually allocated by
793 //   RtlAllocateHeap.
794 //
795 //  - size (IN): The size, in bytes, of the memory block to be allocated.
796 //
797 //  - type (IN): The CRT "use type" of the block to be allocated.
798 //
799 //  - file (IN): The name of the file from which this function is being called.
800 //
801 //  - line (IN): The line number, in the above file, at which this function is
802 //      being called.
803 //
804 //  Return Value:
805 //
806 //    Returns the value returned by the CRT debug scalar new operator.
807 //
808 void* VisualLeakDetector::_crt80d__scalar_new_dbg (unsigned int size, int type, const char *file, int line)
809 {
810     void    *block;
811     SIZE_T   fp;
812     HMODULE  msvcr80d;
813     tls_t   *tls = vld.gettls();
814
815     // The debug new operator is a CRT function and allocates from the CRT heap.
816     tls->flags |= VLD_TLS_CRTALLOC;
817
818     if (tls->addrfp == 0x0) {
819         // This is the first call to enter VLD for the current allocation.
820         // Record the current frame pointer.
821         FRAMEPOINTER(fp);
822         tls->addrfp = fp;
823     }
824
825     if (pcrt80d__scalar_new_dbg == NULL) {
826         // This is the first call to this function. Link to the real CRT debug
827         // new operator.
828         msvcr80d = GetModuleHandle(L"msvcr80d.dll");
829         pcrt80d__scalar_new_dbg = (crt_new_dbg_t)GetProcAddress(msvcr80d, "??2@YAPAXIHPBDH@Z");
830     }
831
832     // Do the allocation. The block will be mapped by _RtlAllocateHeap.
833     block = pcrt80d__scalar_new_dbg(size, type, file, line);
834
835     // Reset thread local flags and variables for the next allocation.
836     tls->addrfp = 0x0;
837     tls->flags &= ~VLD_TLS_CRTALLOC;
838
839     return block;
840 }
841
842 // _crt80d__vector_new_dbg - Calls to the CRT's debug vector new operator from
843 //   msvcr80d.dll are patched through to this function. This function is just a
844 //   wrapper around the real CRT debug vector new operator that sets appropriate
845 //   flags to be consulted when the memory is actually allocated by
846 //   RtlAllocateHeap.
847 //
848 //  - size (IN): The size, in bytes, of the memory block to be allocated.
849 //
850 //  - type (IN): The CRT "use type" of the block to be allocated.
851 //
852 //  - file (IN): The name of the file from which this function is being called.
853 //
854 //  - line (IN): The line number, in the above file, at which this function is
855 //      being called.
856 //
857 //  Return Value:
858 //
859 //    Returns the value returned by the CRT debug vector new operator.
860 //
861 void* VisualLeakDetector::_crt80d__vector_new_dbg (unsigned int size, int type, const char *file, int line)
862 {
863     void    *block;
864     SIZE_T   fp;
865     HMODULE  msvcr80d;
866     tls_t   *tls = vld.gettls();
867
868     // The debug new operator is a CRT function and allocates from the CRT heap.
869     tls->flags |= VLD_TLS_CRTALLOC;
870
871     if (tls->addrfp == 0x0) {
872         // This is the first call to enter VLD for the current allocation.
873         // Record the current frame pointer.
874         FRAMEPOINTER(fp);
875         tls->addrfp = fp;
876     }
877
878     if (pcrt80d__vector_new_dbg == NULL) {
879         // This is the first call to this function. Link to the real CRT debug
880         // new operator.
881         msvcr80d = GetModuleHandle(L"msvcr80d.dll");
882         pcrt80d__vector_new_dbg = (crt_new_dbg_t)GetProcAddress(msvcr80d, "??_U@YAPAXIHPBDH@Z");
883     }
884
885     // Do the allocation. The block will be mapped by _RtlAllocateHeap.
886     block = pcrt80d__vector_new_dbg(size, type, file, line);
887
888     // Reset thread local flags and variables for the next allocation.
889     tls->addrfp = 0x0;
890     tls->flags &= ~VLD_TLS_CRTALLOC;
891
892     return block;
893 }
894
895 // _crt80d_calloc - Calls to calloc from msvcr80d.dll are patched through to
896 //   this function. This function is just a wrapper around the real calloc that
897 //   sets appropriate flags to be consulted when the memory is actually
898 //   allocated by RtlAllocateHeap.
899 //
900 //  - num (IN): The number of blocks, of size 'size', to be allocated.
901 //
902 //  - size (IN): The size, in bytes, of the memory block to be allocated.
903 //
904 //  Return Value:
905 //
906 //    Returns the valued returned from calloc.
907 //
908 void* VisualLeakDetector::_crt80d_calloc (size_t num, size_t size)
909 {
910     void    *block;
911     SIZE_T   fp;
912     HMODULE  msvcr80d;
913     tls_t   *tls = vld.gettls();
914
915     // malloc is a CRT function and allocates from the CRT heap.
916     tls->flags |= VLD_TLS_CRTALLOC;
917
918     if (tls->addrfp == 0x0) {
919         // This is the first call to enter VLD for the current allocation.
920         // Record the current frame pointer.
921         FRAMEPOINTER(fp);
922         tls->addrfp = fp;
923     }
924
925     if (pcrt80d_calloc == NULL) {
926         // This is the first call to this function. Link to the real malloc.
927         msvcr80d = GetModuleHandle(L"msvcr80d.dll");
928         pcrt80d_calloc = (calloc_t)GetProcAddress(msvcr80d, "calloc");
929     }
930
931     // Do the allocation. The block will be mapped by _RtlAllocateHeap.
932     block = pcrt80d_calloc(num, size);
933
934     // Reset thread local flags and variables for the next allocation.
935     tls->addrfp = 0x0;
936     tls->flags &= ~VLD_TLS_CRTALLOC;
937
938     return block;
939 }
940
941 // _crt80d_malloc - Calls to malloc from msvcr80d.dll are patched through to
942 //   this function. This function is just a wrapper around the real malloc that
943 //   sets appropriate flags to be consulted when the memory is actually
944 //   allocated by RtlAllocateHeap.
945 //
946 //  - size (IN): The size, in bytes, of the memory block to be allocated.
947 //
948 //  Return Value:
949 //
950 //    Returns the valued returned from malloc.
951 //
952 void* VisualLeakDetector::_crt80d_malloc (size_t size)
953 {
954     void    *block;
955     SIZE_T   fp;
956     HMODULE  msvcr80d;
957     tls_t   *tls = vld.gettls();
958
959     // malloc is a CRT function and allocates from the CRT heap.
960     tls->flags |= VLD_TLS_CRTALLOC;
961
962     if (tls->addrfp == 0x0) {
963         // This is the first call to enter VLD for the current allocation.
964         // Record the current frame pointer.
965         FRAMEPOINTER(fp);
966         tls->addrfp = fp;
967     }
968
969     if (pcrt80d_malloc == NULL) {
970         // This is the first call to this function. Link to the real malloc.
971         msvcr80d = GetModuleHandle(L"msvcr80d.dll");
972         pcrt80d_malloc = (malloc_t)GetProcAddress(msvcr80d, "malloc");
973     }
974
975     // Do the allocation. The block will be mapped by _RtlAllocateHeap.
976     block = pcrt80d_malloc(size);
977
978     // Reset thread local flags and variables for the next allocation.
979     tls->addrfp = 0x0;
980     tls->flags &= ~VLD_TLS_CRTALLOC;
981
982     return block;
983 }
984
985 // _crt80d_realloc - Calls to realloc from msvcr80d.dll are patched through to
986 //   this function. This function is just a wrapper around the real realloc that
987 //   sets appropriate flags to be consulted when the memory is actually
988 //   allocated by RtlAllocateHeap.
989 //
990 //  - mem (IN): Pointer to the memory block to reallocate.
991 //
992 //  - size (IN): Size of the memory block to reallocate.
993 //
994 //  Return Value:
995 //
996 //    Returns the value returned from realloc.
997 //
998 void* VisualLeakDetector::_crt80d_realloc (void *mem, size_t size)
999 {
1000     void    *block;
1001     SIZE_T   fp;
1002     HMODULE  msvcr80d;
1003     tls_t   *tls = vld.gettls();
1004
1005     // realloc is a CRT function and allocates from the CRT heap.
1006     tls->flags |= VLD_TLS_CRTALLOC;
1007
1008     if (tls->addrfp == 0x0) {
1009         // This is the first call to enter VLD for the current allocation.
1010         // Record the current frame pointer.
1011         FRAMEPOINTER(fp);
1012         tls->addrfp = fp;
1013     }
1014
1015     if (pcrt80d_realloc == NULL) {
1016         // This is the first call to this function. Link to the real realloc.
1017         msvcr80d = GetModuleHandle(L"msvcr80d.dll");
1018         pcrt80d_realloc = (realloc_t)GetProcAddress(msvcr80d, "realloc");
1019     }
1020
1021     // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
1022     block = pcrt80d_realloc(mem, size);
1023
1024     // Reset thread local flags and variables for the next allocation.
1025     tls->addrfp = 0x0;
1026     tls->flags &= ~VLD_TLS_CRTALLOC;
1027
1028     return block;
1029 }
1030
1031 // _crt80d_scalar_new - Calls to the CRT's scalar new operator from msvcr80d.dll
1032 //   are patched through to this function. This function is just a wrapper
1033 //   around the real CRT scalar new operator that sets appropriate flags to be
1034 //   consulted when the memory is actually allocated by RtlAllocateHeap.
1035 //
1036 //  - size (IN): The size, in bytes, of the memory block to be allocated.
1037 //
1038 //  Return Value:
1039 //
1040 //    Returns the value returned by the CRT scalar new operator.
1041 //
1042 void* VisualLeakDetector::_crt80d_scalar_new (unsigned int size)
1043 {
1044     void    *block;
1045     SIZE_T   fp;
1046     HMODULE  msvcr80d;
1047     tls_t   *tls = vld.gettls();
1048
1049     // The new operator is a CRT function and allocates from the CRT heap.
1050     tls->flags |= VLD_TLS_CRTALLOC;
1051
1052     if (tls->addrfp == 0x0) {
1053         // This is the first call to enter VLD for the current allocation.
1054         // Record the current frame pointer.
1055         FRAMEPOINTER(fp);
1056         tls->addrfp = fp;
1057     }
1058
1059     if (pcrt80d_scalar_new == NULL) {
1060         // This is the first call to this function. Link to the real CRT new
1061         // operator.
1062         msvcr80d = GetModuleHandle(L"msvcr80d.dll");
1063         pcrt80d_scalar_new = (new_t)GetProcAddress(msvcr80d, "??2@YAPAXI@Z");
1064     }
1065
1066     // Do tha allocation. The block will be mapped by _RtlAllocateHeap.
1067     block = pcrt80d_scalar_new(size);
1068
1069     // Reset thread local flags and variables for the next allocation.
1070     tls->addrfp = 0x0;
1071     tls->flags &= ~VLD_TLS_CRTALLOC;
1072
1073     return block;
1074 }
1075
1076 // _crt80d_vector_new - Calls to the CRT's vector new operator from msvcr80d.dll
1077 //   are patched through to this function. This function is just a wrapper
1078 //   around the real CRT vector new operator that sets appropriate flags to be
1079 //   consulted when the memory is actually allocated by RtlAllocateHeap.
1080 //
1081 //  - size (IN): The size, in bytes, of the memory block to be allocated.
1082 //
1083 //  Return Value:
1084 //
1085 //    Returns the value returned by the CRT vector new operator.
1086 //
1087 void* VisualLeakDetector::_crt80d_vector_new (unsigned int size)
1088 {
1089     void    *block;
1090     SIZE_T   fp;
1091     HMODULE  msvcr80d;
1092     tls_t   *tls = vld.gettls();
1093
1094     // The new operator is a CRT function and allocates from the CRT heap.
1095     tls->flags |= VLD_TLS_CRTALLOC;
1096
1097     if (tls->addrfp == 0x0) {
1098         // This is the first call to enter VLD for the current allocation.
1099         // Record the current frame pointer.
1100         FRAMEPOINTER(fp);
1101         tls->addrfp = fp;
1102     }
1103
1104     if (pcrt80d_vector_new == NULL) {
1105         // This is the first call to this function. Link to the real CRT new
1106         // operator.
1107         msvcr80d = GetModuleHandle(L"msvcr80d.dll");
1108         pcrt80d_vector_new = (new_t)GetProcAddress(msvcr80d, "??_U@YAPAXI@Z");
1109     }
1110
1111     // Do tha allocation. The block will be mapped by _RtlAllocateHeap.
1112     block = pcrt80d_vector_new(size);
1113
1114     // Reset thread local flags and variables for the next allocation.
1115     tls->addrfp = 0x0;
1116     tls->flags &= ~VLD_TLS_CRTALLOC;
1117
1118     return block;
1119 }
1120
1121 // _crtd__calloc_dbg - Calls to _calloc_dbg from msvcrtd.dll are patched through
1122 //   to this function. This function is just a wrapper around the real
1123 //   _calloc_dbg that sets appropriate flags to be consulted when the memory is
1124 //   actually allocated by RtlAllocateHeap.
1125 //
1126 //  - num (IN): The number of blocks, of size 'size', to be allocated.
1127 //
1128 //  - size (IN): The size, in bytes, of the memory block to be allocated.
1129 //
1130 //  - type (IN): The CRT "use type" of the block to be allocated.
1131 //
1132 //  - file (IN): The name of the file from which this function is being called.
1133 //
1134 //  - line (IN): The line number, in the above file, at which this function is
1135 //      being called.
1136 //
1137 //  Return Value:
1138 //
1139 //    Returns the value returned by _calloc_dbg.
1140 //
1141 void* VisualLeakDetector::_crtd__calloc_dbg (size_t num, size_t size, int type, const char *file, int line)
1142 {
1143     void    *block;
1144     SIZE_T   fp;
1145     HMODULE  msvcrtd;
1146     tls_t   *tls = vld.gettls();
1147
1148     // _malloc_dbg is a CRT function and allocates from the CRT heap.
1149     tls->flags |= VLD_TLS_CRTALLOC;
1150
1151     if (tls->addrfp == 0x0) {
1152         // This is the first call to enter VLD for the current allocation.
1153         // Record the current frame pointer.
1154         FRAMEPOINTER(fp);
1155         tls->addrfp = fp;
1156     }
1157
1158     if (pcrtd__calloc_dbg == NULL) {
1159         // This is the first call to this function. Link to the real
1160         // _malloc_dbg.
1161         msvcrtd = GetModuleHandle(L"msvcrtd.dll");
1162         pcrtd__calloc_dbg = (_calloc_dbg_t)GetProcAddress(msvcrtd, "_calloc_dbg");
1163     }
1164
1165     // Do the allocation. The block will be mapped by _RtlAllocateHeap.
1166     block = pcrtd__calloc_dbg(num, size, type, file, line);
1167
1168     // Reset thread local flags and variables for the next allocation.
1169     tls->addrfp = 0x0;
1170     tls->flags &= ~VLD_TLS_CRTALLOC;
1171
1172     return block;
1173 }
1174
1175 // _crtd__malloc_dbg - Calls to _malloc_dbg from msvcrtd.dll are patched through
1176 //   to this function. This function is just a wrapper around the real
1177 //   _malloc_dbg that sets appropriate flags to be consulted when the memory is
1178 //   actually allocated by RtlAllocateHeap.
1179 //
1180 //  - size (IN): The size, in bytes, of the memory block to be allocated.
1181 //
1182 //  - type (IN): The CRT "use type" of the block to be allocated.
1183 //
1184 //  - file (IN): The name of the file from which this function is being called.
1185 //
1186 //  - line (IN): The line number, in the above file, at which this function is
1187 //      being called.
1188 //
1189 //  Return Value:
1190 //
1191 //    Returns the value returned by _malloc_dbg.
1192 //
1193 void* VisualLeakDetector::_crtd__malloc_dbg (size_t size, int type, const char *file, int line)
1194 {
1195     void    *block;
1196     SIZE_T   fp;
1197     HMODULE  msvcrtd;
1198     tls_t   *tls = vld.gettls();
1199
1200     // _malloc_dbg is a CRT function and allocates from the CRT heap.
1201     tls->flags |= VLD_TLS_CRTALLOC;
1202
1203     if (tls->addrfp == 0x0) {
1204         // This is the first call to enter VLD for the current allocation.
1205         // Record the current frame pointer.
1206         FRAMEPOINTER(fp);
1207         tls->addrfp = fp;
1208     }
1209
1210     if (pcrtd__malloc_dbg == NULL) {
1211         // This is the first call to this function. Link to the real
1212         // _malloc_dbg.
1213         msvcrtd = GetModuleHandle(L"msvcrtd.dll");
1214         pcrtd__malloc_dbg = (_malloc_dbg_t)GetProcAddress(msvcrtd, "_malloc_dbg");
1215     }
1216
1217     // Do the allocation. The block will be mapped by _RtlAllocateHeap.
1218     block = pcrtd__malloc_dbg(size, type, file, line);
1219
1220     // Reset thread local flags and variables for the next allocation.
1221     tls->addrfp = 0x0;
1222     tls->flags &= ~VLD_TLS_CRTALLOC;
1223
1224     return block;
1225 }
1226
1227 // _crtd__realloc_dbg - Calls to _realloc_dbg from msvcrtd.dll are patched
1228 //   through to this function. This function is just a wrapper around the real
1229 //   _realloc_dbg that sets appropriate flags to be consulted when the memory is
1230 //   actually allocated by RtlAllocateHeap.
1231 //
1232 //  - mem (IN): Pointer to the memory block to be reallocated.
1233 //
1234 //  - size (IN): The size of the memory block to reallocate.
1235 //
1236 //  - type (IN): The CRT "use type" of the block to be reallocated.
1237 //
1238 //  - file (IN): The name of the file from which this function is being called.
1239 //
1240 //  - line (IN): The line number, in the above filel, at which this function is
1241 //      being called.
1242 //
1243 //  Return Value:
1244 //
1245 //    Returns the value returned by _realloc_dbg.
1246 //
1247 void* VisualLeakDetector::_crtd__realloc_dbg (void *mem, size_t size, int type, const char *file, int line)
1248 {
1249     void    *block;
1250     SIZE_T   fp;
1251     HMODULE  msvcrtd;
1252     tls_t   *tls = vld.gettls();
1253
1254     // _realloc_dbg is a CRT function and allocates from the CRT heap.
1255     tls->flags |= VLD_TLS_CRTALLOC;
1256
1257     if (tls->addrfp == 0x0) {
1258         // This is the first call to enter VLD for the current allocation.
1259         // Record the current frame pointer.
1260         FRAMEPOINTER(fp);
1261         tls->addrfp = fp;
1262     }
1263
1264     if (pcrtd__realloc_dbg == NULL) {
1265         // This is the first call to this function. Link to the real
1266         // _realloc_dbg.
1267         msvcrtd = GetModuleHandle(L"msvcrtd.dll");
1268         pcrtd__realloc_dbg = (_realloc_dbg_t)GetProcAddress(msvcrtd, "_realloc_dbg");
1269     }
1270
1271     // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
1272     block = pcrtd__realloc_dbg(mem, size, type, file, line);
1273
1274     // Reset thread local flags and variables for the next allocation.
1275     tls->addrfp = 0x0;
1276     tls->flags &= ~VLD_TLS_CRTALLOC;
1277
1278     return block;
1279 }
1280
1281 // _crtd__scalar_new_dbg - Calls to the CRT's debug scalar new operator from
1282 //   msvcrtd.dll are patched through to this function. This function is just a
1283 //   wrapper around the real CRT debug scalar new operator that sets appropriate
1284 //   flags to be consulted when the memory is actually allocated by
1285 //   RtlAllocateHeap.
1286 //
1287 //  - size (IN): The size, in bytes, of the memory block to be allocated.
1288 //
1289 //  - type (IN): The CRT "use type" of the block to be allocated.
1290 //
1291 //  - file (IN): The name of the file from which this function is being called.
1292 //
1293 //  - line (IN): The line number, in the above file, at which this function is
1294 //      being called.
1295 //
1296 //  Return Value:
1297 //
1298 //    Returns the value returned by the CRT debug scalar new operator.
1299 //
1300 void* VisualLeakDetector::_crtd__scalar_new_dbg (unsigned int size, int type, const char *file, int line)
1301 {
1302     void    *block;
1303     SIZE_T   fp;
1304     HMODULE  msvcrtd;
1305     tls_t   *tls = vld.gettls();
1306
1307     // The debug new operator is a CRT function and allocates from the CRT heap.
1308     tls->flags |= VLD_TLS_CRTALLOC;
1309
1310     if (tls->addrfp == 0x0) {
1311         // This is the first call to enter VLD for the current allocation.
1312         // Record the current frame pointer.
1313         FRAMEPOINTER(fp);
1314         tls->addrfp = fp;
1315     }
1316
1317     if (pcrtd__scalar_new_dbg == NULL) {
1318         // This is the first call to this function. Link to the real CRT debug
1319         // new operator.
1320         msvcrtd = GetModuleHandle(L"msvcrtd.dll");
1321         pcrtd__scalar_new_dbg = (crt_new_dbg_t)GetProcAddress(msvcrtd, "??2@YAPAXIHPBDH@Z");
1322     }
1323
1324     // Do the allocation. The block will be mapped by _RtlAllocateHeap.
1325     block = pcrtd__scalar_new_dbg(size, type, file, line);
1326
1327     // Reset thread local flags and variables for the next allocation.
1328     tls->addrfp = 0x0;
1329     tls->flags &= ~VLD_TLS_CRTALLOC;
1330
1331     return block;
1332 }
1333
1334 // _crtd_calloc - Calls to calloc from msvcrtd.dll are patched through to this
1335 //   function. This function is just a wrapper around the real calloc that sets
1336 //   appropriate flags to be consulted when the memory is actually allocated by
1337 //   RtlAllocateHeap.
1338 //
1339 //  - num (IN): The number of blocks, of size 'size', to be allocated.
1340 //
1341 //  - size (IN): The size, in bytes, of the memory block to be allocated.
1342 //
1343 //  Return Value:
1344 //
1345 //    Returns the valued returned from calloc.
1346 //
1347 void* VisualLeakDetector::_crtd_calloc (size_t num, size_t size)
1348 {
1349     void    *block;
1350     SIZE_T   fp;
1351     HMODULE  msvcrtd;
1352     tls_t   *tls = vld.gettls();
1353
1354     // malloc is a CRT function and allocates from the CRT heap.
1355     tls->flags |= VLD_TLS_CRTALLOC;
1356
1357     if (tls->addrfp == 0x0) {
1358         // This is the first call to enter VLD for the current allocation.
1359         // Record the current frame pointer.
1360         FRAMEPOINTER(fp);
1361         tls->addrfp = fp;
1362     }
1363
1364     if (pcrtd_calloc == NULL) {
1365         // This is the first call to this function. Link to the real malloc.
1366         msvcrtd = GetModuleHandle(L"msvcrtd.dll");
1367         pcrtd_calloc = (calloc_t)GetProcAddress(msvcrtd, "calloc");
1368     }
1369
1370     // Do the allocation. The block will be mapped by _RtlAllocateHeap.
1371     block = pcrtd_calloc(num, size);
1372
1373     // Reset thread local flags and variables for the next allocation.
1374     tls->addrfp = 0x0;
1375     tls->flags &= ~VLD_TLS_CRTALLOC;
1376
1377     return block;
1378 }
1379
1380 // _crtd_malloc - Calls to malloc from msvcrtd.dll are patched through to this
1381 //   function. This function is just a wrapper around the real malloc that sets
1382 //   appropriate flags to be consulted when the memory is actually allocated by
1383 //   RtlAllocateHeap.
1384 //
1385 //  - size (IN): The size, in bytes, of the memory block to be allocated.
1386 //
1387 //  Return Value:
1388 //
1389 //    Returns the valued returned from malloc.
1390 //
1391 void* VisualLeakDetector::_crtd_malloc (size_t size)
1392 {
1393     void    *block;
1394     SIZE_T   fp;
1395     HMODULE  msvcrtd;
1396     tls_t   *tls = vld.gettls();
1397
1398     // malloc is a CRT function and allocates from the CRT heap.
1399     tls->flags |= VLD_TLS_CRTALLOC;
1400
1401     if (tls->addrfp == 0x0) {
1402         // This is the first call to enter VLD for the current allocation.
1403         // Record the current frame pointer.
1404         FRAMEPOINTER(fp);
1405         tls->addrfp = fp;
1406     }
1407
1408     if (pcrtd_malloc == NULL) {
1409         // This is the first call to this function. Link to the real malloc.
1410         msvcrtd = GetModuleHandle(L"msvcrtd.dll");
1411         pcrtd_malloc = (malloc_t)GetProcAddress(msvcrtd, "malloc");
1412     }
1413
1414     // Do the allocation. The block will be mapped by _RtlAllocateHeap.
1415     block = pcrtd_malloc(size);
1416
1417     // Reset thread local flags and variables for the next allocation.
1418     tls->addrfp = 0x0;
1419     tls->flags &= ~VLD_TLS_CRTALLOC;
1420
1421     return block;
1422 }
1423
1424 // _crtd_realloc - Calls to realloc from msvcrtd.dll are patched through to this
1425 //   function. This function is just a wrapper around the real realloc that sets
1426 //   appropriate flags to be consulted when the memory is actually allocated by
1427 //   RtlAllocateHeap.
1428 //
1429 //  - mem (IN): Pointer to the memory block to reallocate.
1430 //
1431 //  - size (IN): Size of the memory block to reallocate.
1432 //
1433 //  Return Value:
1434 //
1435 //    Returns the value returned from realloc.
1436 //
1437 void* VisualLeakDetector::_crtd_realloc (void *mem, size_t size)
1438 {
1439     void    *block;
1440     SIZE_T   fp;
1441     HMODULE  msvcrtd;
1442     tls_t   *tls = vld.gettls();
1443
1444     // realloc is a CRT function and allocates from the CRT heap.
1445     tls->flags |= VLD_TLS_CRTALLOC;
1446
1447     if (tls->addrfp == 0x0) {
1448         // This is the first call to enter VLD for the current allocation.
1449         // Record the current frame pointer.
1450         FRAMEPOINTER(fp);
1451         tls->addrfp = fp;
1452     }
1453
1454     if (pcrtd_realloc == NULL) {
1455         // This is the first call to this function. Link to the real realloc.
1456         msvcrtd = GetModuleHandle(L"msvcrtd.dll");
1457         pcrtd_realloc = (realloc_t)GetProcAddress(msvcrtd, "realloc");
1458     }
1459
1460     // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
1461     block = pcrtd_realloc(mem, size);
1462
1463     // Reset thread local flags and variables for the next allocation.
1464     tls->addrfp = 0x0;
1465     tls->flags &= ~VLD_TLS_CRTALLOC;
1466
1467     return block;
1468 }
1469
1470 // _crtd_scalar_new - Calls to the CRT's scalar new operator from msvcrtd.dll
1471 //   are patched through to this function. This function is just a wrapper
1472 //   around the real CRT scalar new operator that sets appropriate flags to be
1473 //   consulted when the memory is actually allocated by RtlAllocateHeap.
1474 //
1475 //  - size (IN): The size, in bytes, of the memory block to be allocated.
1476 //
1477 //  Return Value:
1478 //
1479 //    Returns the value returned by the CRT scalar new operator.
1480 //
1481 void* VisualLeakDetector::_crtd_scalar_new (unsigned int size)
1482 {
1483     void    *block;
1484     SIZE_T   fp;
1485     HMODULE  msvcrtd;
1486     tls_t   *tls = vld.gettls();
1487
1488     // The new operator is a CRT function and allocates from the CRT heap.
1489     tls->flags |= VLD_TLS_CRTALLOC;
1490
1491     if (tls->addrfp == 0x0) {
1492         // This is the first call to enter VLD for the current allocation.
1493         // Record the current frame pointer.
1494         FRAMEPOINTER(fp);
1495         tls->addrfp = fp;
1496     }
1497
1498     if (pcrtd_scalar_new == NULL) {
1499         // This is the first call to this function. Link to the real CRT new
1500         // operator.
1501         msvcrtd = GetModuleHandle(L"msvcrtd.dll");
1502         pcrtd_scalar_new = (new_t)GetProcAddress(msvcrtd, "??2@YAPAXI@Z");
1503     }
1504
1505     // Do tha allocation. The block will be mapped by _RtlAllocateHeap.
1506     block = pcrtd_scalar_new(size);
1507
1508     // Reset thread local flags and variables for the next allocation.
1509     tls->addrfp = 0x0;
1510     tls->flags &= ~VLD_TLS_CRTALLOC;
1511
1512     return block;
1513 }
1514
1515 // _GetProcAddress - Calls to GetProcAddress are patched through to this
1516 //   function. If the requested function is a function that has been patched
1517 //   through to one of VLD's handlers, then the address of VLD's handler
1518 //   function is returned instead of the real address. Otherwise, this 
1519 //   function is just a wrapper around the real GetProcAddress.
1520 //
1521 //  - module (IN): Handle (base address) of the module from which to retrieve
1522 //      the address of an exported function.
1523 //
1524 //  - procname (IN): ANSI string containing the name of the exported function
1525 //      whose address is to be retrieved.
1526 //
1527 //  Return Value:
1528 //
1529 //    Returns a pointer to the requested function, or VLD's replacement for
1530 //    the function, if there is a replacement function.
1531 //
1532 FARPROC VisualLeakDetector::_GetProcAddress (HMODULE module, LPCSTR procname)
1533 {
1534     patchentry_t *entry;
1535     UINT          index;
1536     UINT          tablesize = sizeof(vld.m_patchtable) / sizeof(patchentry_t);
1537
1538     // See if there is an entry in the patch table that matches the requested
1539     // function.
1540     for (index = 0; index < tablesize; index++) {
1541         entry = &vld.m_patchtable[index];
1542         if ((entry->modulebase == 0x0) || ((HMODULE)entry->modulebase != module)) {
1543             // This patch table entry is for a different module.
1544             continue;
1545         }
1546
1547         // This patch table entry is for the specified module. If the requested
1548         // import's name matches the entry's import name (or ordinal), then
1549         // return the address of the replacement instead of the address of the
1550         // actual import.
1551         if ((SIZE_T)entry->importname < (SIZE_T)vld.m_vldbase) {
1552             // This entry's import name is not a valid pointer to data in
1553             // vld.dll. It must be an ordinal value.
1554             if ((UINT)entry->importname == (UINT)procname) {
1555                 return (FARPROC)entry->replacement;
1556             }
1557         }
1558         else {
1559             if (strcmp(entry->importname, procname) == 0) {
1560                 return (FARPROC)entry->replacement;
1561             }
1562         }
1563     }
1564
1565     // The requested function is not a patched function. Just return the real
1566     // address of the requested function.
1567     return GetProcAddress(module, procname);
1568 }
1569
1570 // _HeapCreate - Calls to HeapCreate are patched through to this function. This
1571 //   function is just a wrapper around the real HeapCreate that calls VLD's heap
1572 //   creation tracking function after the heap has been created.
1573 //
1574 //  - options (IN): Heap options.
1575 //
1576 //  - initsize (IN): Initial size of the heap.
1577 //
1578 //  - maxsize (IN): Maximum size of the heap.
1579 //
1580 //  Return Value:
1581 //
1582 //    Returns the value returned by HeapCreate.
1583 //
1584 HANDLE VisualLeakDetector::_HeapCreate (DWORD options, SIZE_T initsize, SIZE_T maxsize)
1585 {
1586     DWORD64            displacement;
1587     SIZE_T             fp;
1588     SYMBOL_INFO       *functioninfo;
1589     HANDLE             heap;
1590     HeapMap::Iterator  heapit;
1591     SIZE_T             ra;
1592     BYTE               symbolbuffer [sizeof(SYMBOL_INFO) + (MAXSYMBOLNAMELENGTH * sizeof(WCHAR)) - 1] = { 0 };
1593     BOOL               symfound;
1594
1595     // Get the return address within the calling function.
1596     FRAMEPOINTER(fp);
1597     ra = *((SIZE_T*)fp + 1);
1598
1599     // Create the heap.
1600     heap = HeapCreate(options, initsize, maxsize);
1601
1602     // Map the created heap handle to a new block map.
1603     vld.mapheap(heap);
1604
1605     // Try to get the name of the function containing the return address.
1606     functioninfo = (SYMBOL_INFO*)&symbolbuffer;
1607     functioninfo->SizeOfStruct = sizeof(SYMBOL_INFO);
1608     functioninfo->MaxNameLen = MAXSYMBOLNAMELENGTH;
1609     EnterCriticalSection(&symbollock);
1610     symfound = SymFromAddrW(currentprocess, ra, &displacement, functioninfo);
1611     LeaveCriticalSection(&symbollock);
1612     if (symfound == TRUE) {
1613         if (wcscmp(L"_heap_init", functioninfo->Name) == 0) {
1614             // HeapCreate was called by _heap_init. This is a static CRT heap.
1615             EnterCriticalSection(&vld.m_maplock);
1616             heapit = vld.m_heapmap->find(heap);
1617             assert(heapit != vld.m_heapmap->end());
1618             (*heapit).second->flags |= VLD_HEAP_CRT;
1619             LeaveCriticalSection(&vld.m_maplock);
1620         }
1621     }
1622
1623     return heap;
1624 }
1625
1626 // _HeapDestroy - Calls to HeapDestroy are patched through to this function.
1627 //   This function is just a wrapper around the real HeapDestroy that calls
1628 //   VLD's heap destruction tracking function after the heap has been destroyed.
1629 //
1630 //  - heap (IN): Handle to the heap to be destroyed.
1631 //
1632 //  Return Value:
1633 //
1634 //    Returns the valued returned by HeapDestroy.
1635 //
1636 BOOL VisualLeakDetector::_HeapDestroy (HANDLE heap)
1637 {
1638     // After this heap is destroyed, the heap's address space will be unmapped
1639     // from the process's address space. So, we'd better generate a leak report
1640     // for this heap now, while we can still read from the memory blocks
1641     // allocated to it.
1642     vld.reportleaks(heap);
1643
1644     vld.unmapheap(heap);
1645
1646     return HeapDestroy(heap);
1647 }
1648
1649 // _LdrLoadDll - Calls to LdrLoadDll are patched through to this function. This
1650 //   function invokes the real LdrLoadDll and then re-attaches VLD to all
1651 //   modules loaded in the process after loading of the new DLL is complete.
1652 //   All modules must be re-enumerated because the explicit load of the
1653 //   specified module may result in the implicit load of one or more additional
1654 //   modules which are dependencies of the specified module.
1655 //
1656 //  - searchpath (IN): The path to use for searching for the specified module to
1657 //      be loaded.
1658 //
1659 //  - flags (IN): Pointer to action flags.
1660 //
1661 //  - modulename (IN): Pointer to a unicodestring_t structure specifying the
1662 //      name of the module to be loaded.
1663 //
1664 //  - modulehandle (OUT): Address of a HANDLE to receive the newly loaded
1665 //      module's handle.
1666 //
1667 //  Return Value:
1668 //
1669 //    Returns the value returned by LdrLoadDll.
1670 //
1671 NTSTATUS VisualLeakDetector::_LdrLoadDll (LPWSTR searchpath, PDWORD flags, unicodestring_t *modulename,
1672                                           PHANDLE modulehandle)
1673 {
1674     ModuleSet::Iterator  moduleit;
1675     ModuleSet           *newmodules;
1676     ModuleSet           *oldmodules;
1677     NTSTATUS             status;
1678
1679     // Load the DLL.
1680     status = LdrLoadDll(searchpath, flags, modulename, modulehandle);
1681     
1682     if (STATUS_SUCCESS == status) {
1683         // Create a new set of all loaded modules, including any newly loaded
1684         // modules.
1685         newmodules = new ModuleSet;
1686         newmodules->reserve(MODULESETRESERVE);
1687         EnterCriticalSection(&vld.m_loaderlock);
1688         EnumerateLoadedModulesW64(currentprocess, addloadedmodule, newmodules);
1689         LeaveCriticalSection(&vld.m_loaderlock);
1690
1691         // Attach to all modules included in the set.
1692         vld.attachtoloadedmodules(newmodules);
1693
1694         // Start using the new set of loaded modules.
1695         EnterCriticalSection(&vld.m_moduleslock);
1696         oldmodules = vld.m_loadedmodules;
1697         vld.m_loadedmodules = newmodules;
1698         LeaveCriticalSection(&vld.m_moduleslock);
1699
1700         // Free resources used by the old module list.
1701         for (moduleit = oldmodules->begin(); moduleit != oldmodules->end(); ++moduleit) {
1702             delete (*moduleit).name;
1703             delete (*moduleit).path;
1704         }
1705         delete oldmodules;
1706     }
1707
1708     return status;
1709 }
1710
1711 // _mfc42d__scalar_new_dbg - Calls to the MFC debug scalar new operator from
1712 //   mfc42d.dll are patched through to this function. This function is just a
1713 //   wrapper around the real MFC debug scalar new operator that sets appropriate
1714 //   flags to be consulted when the memory is actually allocated by
1715 //   RtlAllocateHeap.
1716 //
1717 //  - size (IN): The size, in bytes, of the memory block to be allocated.
1718 //
1719 //  - file (IN): The name of the file from which this function is being called.
1720 //
1721 //  - line (IN): The line number, in the above file, at which this function is
1722 //      being called.
1723 //
1724 //  Return Value:
1725 //
1726 //    Returns the value returned by the MFC debug scalar new operator.
1727 //
1728 void* VisualLeakDetector::_mfc42d__scalar_new_dbg (unsigned int size, const char *file, int line)
1729 {
1730     void    *block;
1731     SIZE_T   fp;
1732     HMODULE  mfc42d;
1733     tls_t   *tls = vld.gettls();
1734
1735     // The MFC new operators are CRT-based and allocate from the CRT heap.
1736     tls->flags |= VLD_TLS_CRTALLOC;
1737
1738     if (tls->addrfp == 0x0) {
1739         // This is the first call to enter VLD for the current allocation.
1740         // Record the current frame pointer.
1741         FRAMEPOINTER(fp);
1742         tls->addrfp = fp;
1743     }
1744
1745     if (pmfc42d__scalar_new_dbg == NULL) {
1746         // This is the first call to this function. Link to the real MFC debug
1747         // new operator.
1748         mfc42d = GetModuleHandle(L"mfc42d.dll");
1749         pmfc42d__scalar_new_dbg = (mfc_new_dbg_t)GetProcAddress(mfc42d, (LPCSTR)714);
1750     }
1751
1752     // Do the allocation. The block will be mapped by _RtlAllocateHeap.
1753     block = pmfc42d__scalar_new_dbg(size, file, line);
1754
1755     // Reset thread local flags and variables for the next allocation.
1756     tls->addrfp = 0x0;
1757     tls->flags &= ~VLD_TLS_CRTALLOC;
1758
1759     return block;
1760 }
1761
1762 // _mfc42d_scalar_new - Calls to the MFC scalar new operator from mfc42d.dll are
1763 //   patched through to this function. This function is just a wrapper around
1764 //   the real MFC scalar new operator that sets appropriate flags to be
1765 //   consulted when the memory is actually allocated by RtlAllocateHeap.
1766 //
1767 //  - size (IN): The size, in bytes, of the memory block to be allocated.
1768 //
1769 //  Return Value:
1770 //
1771 //    Returns the value returned by the MFC scalar new operator.
1772 //
1773 void* VisualLeakDetector::_mfc42d_scalar_new (unsigned int size)
1774 {
1775     void    *block;
1776     SIZE_T   fp;
1777     HMODULE  mfc42d;
1778     tls_t   *tls = vld.gettls();
1779
1780     // The MFC new operators are CRT-based and allocate from the CRT heap.
1781     tls->flags |= VLD_TLS_CRTALLOC;
1782
1783     if (tls->addrfp == 0x0) {
1784         // This is the first call to enter VLD for the current allocation.
1785         // Record the current frame pointer.
1786         FRAMEPOINTER(fp);
1787         tls->addrfp = fp;
1788     }
1789
1790     if (pmfc42d_scalar_new == NULL) {
1791         // This is the first call to this function. Link to the real MFC new
1792         // operator.
1793         mfc42d = GetModuleHandle(L"mfc42d.dll");
1794         pmfc42d_scalar_new = (new_t)GetProcAddress(mfc42d, (LPCSTR)711);
1795     }
1796
1797     // Do the allocation. The block will be mapped by _RtlAllocateHeap.
1798     block = pmfc42d_scalar_new(size);
1799
1800     // Reset thread local flags and variables for the next allocation.
1801     tls->addrfp = 0x0;
1802     tls->flags &= ~VLD_TLS_CRTALLOC;
1803
1804     return block;
1805 }
1806
1807 // _mfc80d__scalar_new_dbg - Calls to the MFC debug scalar new operator from
1808 //   mfc80d.dll are patched through to this function. This function is just a
1809 //   wrapper around the real MFC debug scalar new operator that sets appropriate
1810 //   flags to be consulted when the memory is actually allocated by
1811 //   RtlAllocateHeap.
1812 //
1813 //  - size (IN): The size, in bytes, of the memory block to be allocated.
1814 //
1815 //  - file (IN): The name of the file from which this function is being called.
1816 //
1817 //  - line (IN): The line number, in the above file, at which this function is
1818 //      being called.
1819 //
1820 //  Return Value:
1821 //
1822 //    Returns the value returned by the MFC debug scalar new operator.
1823 //
1824 void* VisualLeakDetector::_mfc80d__scalar_new_dbg (unsigned int size, const char *file, int line)
1825 {
1826     void    *block;
1827     SIZE_T   fp;
1828     HMODULE  mfc80d;
1829     tls_t   *tls = vld.gettls();
1830
1831     // The MFC new operators are CRT-based and allocate from the CRT heap.
1832     tls->flags |= VLD_TLS_CRTALLOC;
1833
1834     if (tls->addrfp == 0x0) {
1835         // This is the first call to enter VLD for the current allocation.
1836         // Record the current frame pointer.
1837         FRAMEPOINTER(fp);
1838         tls->addrfp = fp;
1839     }
1840
1841     if (pmfc80d__scalar_new_dbg == NULL) {
1842         // This is the first call to this function. Link to the real MFC debug
1843         // new operator.
1844         mfc80d = GetModuleHandle(L"mfc80d.dll");
1845         pmfc80d__scalar_new_dbg = (mfc_new_dbg_t)GetProcAddress(mfc80d, (LPCSTR)895);
1846     }
1847
1848     // Do the allocation. The block will be mapped by _RtlAllocateHeap.
1849     block = pmfc80d__scalar_new_dbg(size, file, line);
1850
1851     // Reset thread local flags and variables for the next allocation.
1852     tls->addrfp = 0x0;
1853     tls->flags &= ~VLD_TLS_CRTALLOC;
1854
1855     return block;
1856 }
1857
1858 // _mfc80d__vector_new_dbg - Calls to the MFC debug vector new operator from
1859 //   mfc80d.dll are patched through to this function. This function is just a
1860 //   wrapper around the real MFC debug vector new operator that sets appropriate
1861 //   flags to be consulted when the memory is actually allocated by
1862 //   RtlAllocateHeap.
1863 //
1864 //  - size (IN): The size, in bytes, of the memory block to be allocated.
1865 //
1866 //  - file (IN): The name of the file from which this function is being called.
1867 //
1868 //  - line (IN): The line number, in the above file, at which this function is
1869 //      being called.
1870 //
1871 //  Return Value:
1872 //
1873 //    Returns the value returned by the MFC debug vector new operator.
1874 //
1875 void* VisualLeakDetector::_mfc80d__vector_new_dbg (unsigned int size, const char *file, int line)
1876 {
1877     void    *block;
1878     SIZE_T   fp;
1879     HMODULE  mfc80d;
1880     tls_t   *tls = vld.gettls();
1881
1882     // The MFC new operators are CRT-based and allocate from the CRT heap.
1883     tls->flags |= VLD_TLS_CRTALLOC;
1884
1885     if (tls->addrfp == 0x0) {
1886         // This is the first call to enter VLD for the current allocation.
1887         // Record the current frame pointer.
1888         FRAMEPOINTER(fp);
1889         tls->addrfp = fp;
1890     }
1891
1892     if (pmfc80d__vector_new_dbg == NULL) {
1893         // This is the first call to this function. Link to the real MFC debug
1894         // new operator.
1895         mfc80d = GetModuleHandle(L"mfc80d.dll");
1896         pmfc80d__vector_new_dbg = (mfc_new_dbg_t)GetProcAddress(mfc80d, (LPCSTR)269);
1897     }
1898
1899     // Do the allocation. The block will be mapped by _RtlAllocateHeap.
1900     block = pmfc80d__vector_new_dbg(size, file, line);
1901
1902     // Reset thread local flags and variables for the next allocation.
1903     tls->addrfp = 0x0;
1904     tls->flags &= ~VLD_TLS_CRTALLOC;
1905
1906     return block;
1907 }
1908
1909 // _mfc80d_scalar_new - Calls to the MFC scalar new operator from mfc80d.dll are
1910 //   patched through to this function. This function is just a wrapper around
1911 //   the real MFC scalar new operator that sets appropriate flags to be
1912 //   consulted when the memory is actually allocated by RtlAllocateHeap.
1913 //
1914 //  - size (IN): The size, in bytes, of the memory block to be allocated.
1915 //
1916 //  Return Value:
1917 //
1918 //    Returns the value returned by the MFC scalar new operator.
1919 //
1920 void* VisualLeakDetector::_mfc80d_scalar_new (unsigned int size)
1921 {
1922     void    *block;
1923     SIZE_T   fp;
1924     HMODULE  mfc80d;
1925     tls_t   *tls = vld.gettls();
1926
1927     // The MFC new operators are CRT-based and allocate from the CRT heap.
1928     tls->flags |= VLD_TLS_CRTALLOC;
1929
1930     if (tls->addrfp == 0x0) {
1931         // This is the first call to enter VLD for the current allocation.
1932         // Record the current frame pointer.
1933         FRAMEPOINTER(fp);
1934         tls->addrfp = fp;
1935     }
1936
1937     if (pmfc80d_scalar_new == NULL) {
1938         // This is the first call to this function. Link to the real MFC 8.0 new
1939         // operator.
1940         mfc80d = GetModuleHandle(L"mfc80d.dll");
1941         pmfc80d_scalar_new = (new_t)GetProcAddress(mfc80d, (LPCSTR)893);
1942     }
1943
1944     // Do the allocation. The block will be mapped by _RtlAllocateHeap.
1945     block = pmfc80d_scalar_new(size);
1946
1947     // Reset thread local flags and variables for the next allocation.
1948     tls->addrfp = 0x0;
1949     tls->flags &= ~VLD_TLS_CRTALLOC;
1950
1951     return block;
1952 }
1953
1954 // _mfc80d_vector_new - Calls to the MFC vector new operator from mfc80d.dll are
1955 //   patched through to this function. This function is just a wrapper around
1956 //   the real MFC vector new operator that sets appropriate flags to be
1957 //   consulted when the memory is actually allocated by RtlAllocateHeap.
1958 //
1959 //  - size (IN): The size, in bytes, of the memory block to be allocated.
1960 //
1961 //  Return Value:
1962 //
1963 //    Returns the value returned by the MFC vector new operator.
1964 //
1965 void* VisualLeakDetector::_mfc80d_vector_new (unsigned int size)
1966 {
1967     void    *block;
1968     SIZE_T   fp;
1969     HMODULE  mfc80d;
1970     tls_t   *tls = vld.gettls();
1971
1972     // The MFC new operators are CRT-based and allocate from the CRT heap.
1973     tls->flags |= VLD_TLS_CRTALLOC;
1974
1975     if (tls->addrfp == 0x0) {
1976         // This is the first call to enter VLD for the current allocation.
1977         // Record the current frame pointer.
1978         FRAMEPOINTER(fp);
1979         tls->addrfp = fp;
1980     }
1981
1982     if (pmfc80d_vector_new == NULL) {
1983         // This is the first call to this function. Link to the real MFC 8.0 new
1984         // operator.
1985         mfc80d = GetModuleHandle(L"mfc80d.dll");
1986         pmfc80d_vector_new = (new_t)GetProcAddress(mfc80d, (LPCSTR)267);
1987     }
1988
1989     // Do the allocation. The block will be mapped by _RtlAllocateHeap.
1990     block = pmfc80d_vector_new(size);
1991
1992     // Reset thread local flags and variables for the next allocation.
1993     tls->addrfp = 0x0;
1994     tls->flags &= ~VLD_TLS_CRTALLOC;
1995
1996     return block;
1997 }
1998
1999 // _RtlAllocateHeap - Calls to RtlAllocateHeap are patched through to this
2000 //   function. This function invokes the real RtlAllocateHeap and then calls
2001 //   VLD's allocation tracking function. Pretty much all memory allocations
2002 //   will eventually result in a call to RtlAllocateHeap, so this is where we
2003 //   finally map the allocated block.
2004 //
2005 //  - heap (IN): Handle to the heap from which to allocate memory.
2006 //
2007 //  - flags (IN): Heap allocation control flags.
2008 //
2009 //  - size (IN): Size, in bytes, of the block to allocate.
2010 //
2011 //  Return Value:
2012 //
2013 //    Returns the return value from RtlAllocateHeap.
2014 //
2015 LPVOID VisualLeakDetector::_RtlAllocateHeap (HANDLE heap, DWORD flags, SIZE_T size)
2016 {
2017     BOOL                 crtalloc;
2018     BOOL                 excluded = FALSE;
2019     SIZE_T               fp;
2020     LPVOID               block;
2021     moduleinfo_t         moduleinfo;
2022     ModuleSet::Iterator  moduleit;
2023     SIZE_T               returnaddress;
2024     tls_t               *tls = vld.gettls();
2025
2026     // Allocate the block.
2027     block = RtlAllocateHeap(heap, flags, size);
2028     if ((block != NULL) && vld.enabled()) {
2029         if (tls->addrfp == 0x0) {
2030             // This is the first call to enter VLD for the current allocation.
2031             // Record the current frame pointer.
2032             FRAMEPOINTER(fp);
2033         }
2034         else {
2035             fp = tls->addrfp;
2036         }
2037         crtalloc = (tls->flags & VLD_TLS_CRTALLOC) ? TRUE : FALSE;
2038
2039         // Reset thread local flags and variables, in case any libraries called
2040         // into while mapping the block allocate some memory.
2041         tls->addrfp = 0x0;
2042         tls->flags &=~VLD_TLS_CRTALLOC;
2043
2044         // Find the information for the module that initiated this allocation.
2045         returnaddress = *((SIZE_T*)fp + 1);
2046         moduleinfo.addrhigh = returnaddress;
2047         moduleinfo.addrlow  = returnaddress;
2048         EnterCriticalSection(&vld.m_moduleslock);
2049         moduleit = vld.m_loadedmodules->find(moduleinfo);
2050         if (moduleit != vld.m_loadedmodules->end()) {
2051             excluded = (*moduleit).flags & VLD_MODULE_EXCLUDED ? TRUE : FALSE;
2052         }
2053         LeaveCriticalSection(&vld.m_moduleslock);
2054         if (!excluded) {
2055             // The module that initiated this allocation is included in leak
2056             // detection. Map this block to the specified heap.
2057             vld.mapblock(heap, block, size, fp, crtalloc);
2058         }
2059     }
2060
2061     // Reset thread local flags and variables for the next allocation.
2062     tls->addrfp = 0x0;
2063     tls->flags &= ~VLD_TLS_CRTALLOC;
2064
2065     return block;
2066 }
2067
2068 // _RtlFreeHeap - Calls to RtlFreeHeap are patched through to this function.
2069 //   This function calls VLD's free tracking function and then invokes the real
2070 //   RtlFreeHeap. Pretty much all memory frees will eventually result in a call
2071 //   to RtlFreeHeap, so this is where we finally unmap the freed block.
2072 //
2073 //  - heap (IN): Handle to the heap to which the block being freed belongs.
2074 //
2075 //  - flags (IN): Heap control flags.
2076 //
2077 //  - mem (IN): Pointer to the memory block being freed.
2078 //
2079 //  Return Value:
2080 //
2081 //    Returns the value returned by RtlFreeHeap.
2082 //
2083 BOOL VisualLeakDetector::_RtlFreeHeap (HANDLE heap, DWORD flags, LPVOID mem)
2084 {
2085     BOOL status;
2086
2087     // Unmap the block from the specified heap.
2088     vld.unmapblock(heap, mem);
2089
2090     status = RtlFreeHeap(heap, flags, mem);
2091
2092     return status;
2093 }
2094
2095 // _RtlReAllocateHeap - Calls to RtlReAllocateHeap are patched through to this
2096 //   function. This function invokes the real RtlReAllocateHeap and then calls
2097 //   VLD's reallocation tracking function. All arguments passed to this function
2098 //   are passed on to the real RtlReAllocateHeap without modification. Pretty
2099 //   much all memory re-allocations will eventually result in a call to
2100 //   RtlReAllocateHeap, so this is where we finally remap the reallocated block.
2101 //
2102 //  - heap (IN): Handle to the heap to reallocate memory from.
2103 //
2104 //  - flags (IN): Heap control flags.
2105 //
2106 //  - mem (IN): Pointer to the currently allocated block which is to be
2107 //      reallocated.
2108 //
2109 //  - size (IN): Size, in bytes, of the block to reallocate.
2110 //
2111 //  Return Value:
2112 //
2113 //    Returns the value returned by RtlReAllocateHeap.
2114 //
2115 LPVOID VisualLeakDetector::_RtlReAllocateHeap (HANDLE heap, DWORD flags, LPVOID mem, SIZE_T size)
2116 {
2117     BOOL                 crtalloc;
2118     BOOL                 excluded = FALSE;
2119     SIZE_T               fp;
2120     moduleinfo_t         moduleinfo;
2121     ModuleSet::Iterator  moduleit;
2122     LPVOID               newmem;
2123     SIZE_T               returnaddress;
2124     tls_t               *tls = vld.gettls();
2125
2126     // Reallocate the block.
2127     newmem = RtlReAllocateHeap(heap, flags, mem, size);
2128
2129     if (newmem != NULL) {
2130         if (tls->addrfp == 0x0) {
2131             // This is the first call to enter VLD for the current allocation.
2132             // Record the current frame pointer.
2133             FRAMEPOINTER(fp);
2134         }
2135         else {
2136             fp = tls->addrfp;
2137         }
2138         crtalloc = (tls->flags & VLD_TLS_CRTALLOC) ? TRUE : FALSE;
2139
2140         // Reset thread local flags and variables, in case any libraries called
2141         // into while remapping the block allocate some memory.
2142         tls->addrfp = 0x0;
2143         tls->flags &= ~VLD_TLS_CRTALLOC;
2144
2145         // Find the information for the module that initiated this reallocation.
2146         returnaddress = *((SIZE_T*)fp + 1);
2147         moduleinfo.addrhigh = returnaddress;
2148         moduleinfo.addrlow  = returnaddress;
2149         EnterCriticalSection(&vld.m_moduleslock);
2150         moduleit = vld.m_loadedmodules->find(moduleinfo);
2151         if (moduleit != vld.m_loadedmodules->end()) {
2152             excluded = (*moduleit).flags & VLD_MODULE_EXCLUDED ? TRUE : FALSE;
2153         }
2154         LeaveCriticalSection(&vld.m_moduleslock);
2155         if (!excluded) {
2156             // The module that initiated this allocation is included in leak
2157             // detection. Remap the block.
2158             vld.remapblock(heap, mem, newmem, size, fp, crtalloc);
2159         }
2160     }
2161
2162     // Reset thread local flags and variables for the next allocation.
2163     tls->addrfp = 0x0;
2164     tls->flags &= ~VLD_TLS_CRTALLOC;
2165
2166     return newmem;
2167 }
2168
2169 // AddRef - Calls to IMalloc::AddRef end up here. This function is just a
2170 //   wrapper around the real IMalloc::AddRef implementation.
2171 //
2172 //  Return Value:
2173 //
2174 //    Returns the value returned by the system implementation of
2175 //    IMalloc::AddRef.
2176 //
2177 ULONG VisualLeakDetector::AddRef ()
2178 {
2179     assert(m_imalloc != NULL);
2180     return m_imalloc->AddRef();
2181 }
2182
2183 // Alloc - Calls to IMalloc::Alloc end up here. This function is just a wrapper
2184 //   around the real IMalloc::Alloc implementation that sets appropriate flags
2185 //   to be consulted when the memory is actually allocated by RtlAllocateHeap.
2186 //
2187 //  - size (IN): The size of the memory block to allocate.
2188 //
2189 //  Return Value:
2190 //
2191 //    Returns the value returned by the system's IMalloc::Alloc implementation.
2192 //
2193 LPVOID VisualLeakDetector::Alloc (ULONG size)
2194 {
2195     LPVOID  block;
2196     SIZE_T  fp;
2197     tls_t  *tls = vld.gettls();
2198
2199     if (tls->addrfp == 0x0) {
2200         // This is the first call to enter VLD for the current allocation.
2201         // Record the current frame pointer.
2202         FRAMEPOINTER(fp);
2203         tls->addrfp = fp;
2204     }
2205
2206     // Do the allocation. The block will be mapped by _RtlAllocateHeap.
2207     assert(m_imalloc != NULL);
2208     block = m_imalloc->Alloc(size);
2209
2210     // Reset thread local flags and variables for the next allocation.
2211     tls->addrfp = 0x0;
2212     tls->flags &= ~VLD_TLS_CRTALLOC;
2213
2214     return block;
2215 }
2216
2217 // addloadedmodule - Callback function for EnumerateLoadedModules64. This
2218 //   function records information about every module loaded in the process,
2219 //   each time adding the module's information to the provided ModuleSet (the
2220 //   "context" parameter).
2221 //
2222 //   When EnumerateLoadedModules64 has finished calling this function for each
2223 //   loaded module, then the resulting ModuleSet can be used at any time to get
2224 //   information about any modules loaded into the process.
2225 //
2226 //   - modulepath (IN): The fully qualified path from where the module was
2227 //       loaded.
2228 //
2229 //   - modulebase (IN): The base address at which the module has been loaded.
2230 //
2231 //   - modulesize (IN): The size, in bytes, of the loaded module.
2232 //
2233 //   - context (IN): Pointer to the ModuleSet to which information about each
2234 //       module is to be added.
2235 //
2236 //  Return Value:
2237 //
2238 //    Always returns TRUE, which tells EnumerateLoadedModules64 to continue
2239 //    enumerating.
2240 //
2241 BOOL VisualLeakDetector::addloadedmodule (PCWSTR modulepath, DWORD64 modulebase, ULONG modulesize, PVOID context)
2242 {
2243     size_t        count;
2244     patchentry_t *entry;
2245     CHAR          extension [_MAX_EXT];
2246     CHAR          filename [_MAX_FNAME];
2247     UINT          index;
2248     moduleinfo_t  moduleinfo;
2249     LPSTR         modulenamea;
2250     LPSTR         modulepatha;
2251     ModuleSet*    newmodules = (ModuleSet*)context;
2252     SIZE_T        size;
2253     UINT          tablesize = sizeof(m_patchtable) / sizeof(patchentry_t);
2254
2255     // Convert the module path to ASCII.
2256     size = wcslen(modulepath) + 1;
2257     modulepatha = new CHAR [size];
2258     wcstombs_s(&count, modulepatha, size, modulepath, _TRUNCATE);
2259
2260     // Extract just the filename and extension from the module path.
2261     _splitpath_s(modulepatha, NULL, 0, NULL, 0, filename, _MAX_FNAME, extension, _MAX_EXT);
2262     size = strlen(filename) + strlen(extension) + 1;
2263     modulenamea = new CHAR [size];
2264     strncpy_s(modulenamea, size, filename, _TRUNCATE);
2265     strncat_s(modulenamea, size, extension, _TRUNCATE);
2266     _strlwr_s(modulenamea, size);
2267
2268     if (_stricmp(modulenamea, "vld.dll") == 0) {
2269         // Record Visual Leak Detector's own base address.
2270         vld.m_vldbase = (HMODULE)modulebase;
2271     }
2272     else {
2273         // See if this is a module listed in the patch table. If it is, update
2274         // the corresponding patch table entries' module base address.
2275         for (index = 0; index < tablesize; index++) {
2276             entry = &m_patchtable[index];
2277             if (_stricmp(entry->exportmodulename, modulenamea) == 0) {
2278                 entry->modulebase = (SIZE_T)modulebase;
2279             }
2280         }
2281     }
2282
2283     // Record the module's information and store it in the set.
2284     moduleinfo.addrlow  = (SIZE_T)modulebase;
2285     moduleinfo.addrhigh = (SIZE_T)(modulebase + modulesize) - 1;
2286     moduleinfo.flags    = 0x0;
2287     moduleinfo.name     = modulenamea;
2288     moduleinfo.path     = modulepatha;
2289     newmodules->insert(moduleinfo);
2290
2291     return TRUE;
2292 }
2293
2294 // attachtoloadedmodules - Attaches VLD to all modules contained in the provided
2295 //   ModuleSet. Not all modules are in the ModuleSet will actually be included
2296 //   in leak detection. Only modules that import the global VisualLeakDetector
2297 //   class object, or those that are otherwise explicitly included in leak
2298 //   detection, will be checked for memory leaks.
2299 //
2300 //   When VLD attaches to a module, it means that any of the imports listed in
2301 //   the import patch table which are imported by the module, will be redirected
2302 //   to VLD's designated replacements.
2303 //
2304 //  - newmodules (IN): Pointer to a ModuleSet containing information about any
2305 //      loaded modules that need to be attached.
2306 //
2307 //  Return Value:
2308 //
2309 //    None.
2310 //
2311 VOID VisualLeakDetector::attachtoloadedmodules (ModuleSet *newmodules)
2312 {
2313     size_t                count;
2314     DWORD64               modulebase;
2315     UINT32                moduleflags;
2316     IMAGEHLP_MODULE64     moduleimageinfo;
2317     LPCSTR                modulename;
2318 #define MAXMODULENAME (_MAX_FNAME + _MAX_EXT)
2319     WCHAR                 modulenamew [MAXMODULENAME];
2320     LPCSTR                modulepath;
2321     DWORD                 modulesize;
2322     ModuleSet::Iterator   newit;
2323     ModuleSet::Iterator   oldit;
2324     ModuleSet            *oldmodules;
2325     BOOL                  refresh;
2326     UINT                  tablesize = sizeof(m_patchtable) / sizeof(patchentry_t);
2327     ModuleSet::Muterator  updateit;
2328
2329     // Iterate through the supplied set, until all modules have been attached.
2330     for (newit = newmodules->begin(); newit != newmodules->end(); ++newit) {
2331         modulebase  = (DWORD64)(*newit).addrlow;
2332         moduleflags = 0x0;
2333         modulename  = (*newit).name;
2334         modulepath  = (*newit).path;
2335         modulesize  = (DWORD)((*newit).addrhigh - (*newit).addrlow) + 1;
2336
2337         refresh = FALSE;
2338         EnterCriticalSection(&m_moduleslock);
2339         oldmodules = m_loadedmodules;
2340         if (oldmodules != NULL) {
2341             // This is not the first time we have been called to attach to the
2342             // currently loaded modules.
2343             oldit = oldmodules->find(*newit);
2344             if (oldit != oldmodules->end()) {
2345                 // We've seen this "new" module loaded in the process before.
2346                 moduleflags = (*oldit).flags;
2347                 LeaveCriticalSection(&m_moduleslock);
2348                 if (moduleispatched((HMODULE)modulebase, m_patchtable, tablesize)) {
2349                     // This module is already attached. Just update the module's
2350                     // flags, nothing more.
2351                     updateit = newit;
2352                     (*updateit).flags = moduleflags;
2353                     continue;
2354                 }
2355                 else {
2356                     // This module may have been attached before and has been
2357                     // detached. We'll need to try reattaching to it in case it
2358                     // was unloaded and then subsequently reloaded.
2359                     refresh = TRUE;
2360                 }
2361             }
2362             else {
2363                 LeaveCriticalSection(&m_moduleslock);
2364             }
2365         }
2366         else {
2367             LeaveCriticalSection(&m_moduleslock);
2368         }
2369
2370         EnterCriticalSection(&symbollock);
2371         if ((refresh == TRUE) && (moduleflags & VLD_MODULE_SYMBOLSLOADED)) {
2372             // Discard the previously loaded symbols, so we can refresh them.
2373             if (SymUnloadModule64(currentprocess, modulebase) == FALSE) {
2374                 report(L"WARNING: Visual Leak Detector: Failed to unload the symbols for %s. Function names and line"
2375                        L" numbers shown in the memory leak report for %s may be inaccurate.", modulename, modulename);
2376             }
2377         }
2378
2379         // Try to load the module's symbols. This ensures that we have loaded
2380         // the symbols for every module that has ever been loaded into the
2381         // process, guaranteeing the symbols' availability when generating the
2382         // leak report.
2383         moduleimageinfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
2384         if ((SymGetModuleInfoW64(currentprocess, (DWORD64)modulebase, &moduleimageinfo) == TRUE) ||
2385             ((SymLoadModule64(currentprocess, NULL, modulepath, NULL, modulebase, modulesize) == modulebase) &&
2386             (SymGetModuleInfoW64(currentprocess, modulebase, &moduleimageinfo) == TRUE))) {
2387             moduleflags |= VLD_MODULE_SYMBOLSLOADED;
2388         }
2389         LeaveCriticalSection(&symbollock);
2390
2391         if (_stricmp("vld.dll", modulename) == 0) {
2392             // What happens when a module goes through it's own portal? Bad things.
2393             // Like infinite recursion. And ugly bald men wearing dresses. VLD
2394             // should not, therefore, attach to itself.
2395             continue;
2396         }
2397
2398         mbstowcs_s(&count, modulenamew, MAXMODULENAME, modulename, _TRUNCATE);
2399         if ((findimport((HMODULE)modulebase, m_vldbase, "vld.dll", "?vld@@3VVisualLeakDetector@@A") == FALSE) &&
2400             (wcsstr(vld.m_forcedmodulelist, modulenamew) == NULL)) {
2401             // This module does not import VLD. This means that none of the module's
2402             // sources #included vld.h. Exclude this module from leak detection.
2403             moduleflags |= VLD_MODULE_EXCLUDED;
2404         }
2405         else if (!(moduleflags & VLD_MODULE_SYMBOLSLOADED) || (moduleimageinfo.SymType == SymExport)) {
2406             // This module is going to be included in leak detection, but complete
2407             // symbols for this module couldn't be loaded. This means that any stack
2408             // traces through this module may lack information, like line numbers
2409             // and function names.
2410             report(L"WARNING: Visual Leak Detector: A module, %s, included in memory leak detection\n"
2411                    L"  does not have any debugging symbols available, or they could not be located.\n"
2412                    L"  Function names and/or line numbers for this module may not be available.\n", modulename);
2413         }
2414
2415         // Update the module's flags in the "new modules" set.
2416         updateit = newit;
2417         (*updateit).flags = moduleflags;
2418
2419         // Attach to the module.
2420         patchmodule((HMODULE)modulebase, m_patchtable, tablesize);
2421     }
2422 }
2423
2424 // buildsymbolsearchpath - Builds the symbol search path for the symbol handler.
2425 //   This helps the symbol handler find the symbols for the application being
2426 //   debugged.
2427 //
2428 //  Return Value:
2429 //
2430 //    Returns a string containing the search path. The caller is responsible for
2431 //    freeing the string.
2432 //
2433 LPWSTR VisualLeakDetector::buildsymbolsearchpath ()
2434 {
2435     WCHAR   directory [_MAX_DIR];
2436     WCHAR   drive [_MAX_DRIVE];
2437     LPWSTR  env;
2438     DWORD   envlen;
2439     SIZE_T  index;
2440     SIZE_T  length;
2441     HMODULE module;
2442     LPWSTR  path = new WCHAR [MAX_PATH];
2443     SIZE_T  pos = 0;
2444     WCHAR   system [MAX_PATH];
2445     WCHAR   windows [MAX_PATH];
2446
2447     // Oddly, the symbol handler ignores the link to the PDB embedded in the
2448     // executable image. So, we'll manually add the location of the executable
2449     // to the search path since that is often where the PDB will be located.
2450     path[0] = L'\0';
2451     module = GetModuleHandle(NULL);
2452     GetModuleFileName(module, path, MAX_PATH);
2453     _wsplitpath_s(path, drive, _MAX_DRIVE, directory, _MAX_DIR, NULL, 0, NULL, 0);
2454     wcsncpy_s(path, MAX_PATH, drive, _TRUNCATE);
2455     strapp(&path, directory);
2456
2457     // When the symbol handler is given a custom symbol search path, it will no
2458     // longer search the default directories (working directory, system root,
2459     // etc). But we'd like it to still search those directories, so we'll add
2460     // them to our custom search path.
2461     //
2462     // Append the working directory.
2463     strapp(&path, L";.\\");
2464
2465     // Append the Windows directory.
2466     if (GetWindowsDirectory(windows, MAX_PATH) != 0) {
2467         strapp(&path, L";");
2468         strapp(&path, windows);
2469     }
2470
2471     // Append the system directory.
2472     if (GetSystemDirectory(system, MAX_PATH) != 0) {
2473         strapp(&path, L";");
2474         strapp(&path, system);
2475     }
2476
2477     // Append %_NT_SYMBOL_PATH%.
2478     envlen = GetEnvironmentVariable(L"_NT_SYMBOL_PATH", NULL, 0);
2479     if (envlen != 0) {
2480         env = new WCHAR [envlen];
2481         if (GetEnvironmentVariable(L"_NT_SYMBOL_PATH", env, envlen) != 0) {
2482             strapp(&path, L";");
2483             strapp(&path, env);
2484         }
2485         delete [] env;
2486     }
2487
2488     //  Append %_NT_ALT_SYMBOL_PATH%.
2489     envlen = GetEnvironmentVariable(L"_NT_ALT_SYMBOL_PATH", NULL, 0);
2490     if (envlen != 0) {
2491         env = new WCHAR [envlen];
2492         if (GetEnvironmentVariable(L"_NT_ALT_SYMBOL_PATH", env, envlen) != 0) {
2493             strapp(&path, L";");
2494             strapp(&path, env);
2495         }
2496         delete [] env;
2497     }
2498
2499     // Remove any quotes from the path. The symbol handler doesn't like them.
2500     pos = 0;
2501     length = wcslen(path);
2502     while (pos < length) {
2503         if (path[pos] == L'\"') {
2504             for (index = pos; index < length; index++) {
2505                 path[index] = path[index + 1];
2506             }
2507         }
2508         pos++;
2509     }
2510
2511     return path;
2512 }
2513
2514 // configure - Configures VLD using values read from the vld.ini file.
2515 //
2516 //  Return Value:
2517 //
2518 //    None.
2519 //
2520 VOID VisualLeakDetector::configure ()
2521 {
2522 #define BSIZE 64
2523     WCHAR        buffer [BSIZE];
2524     WCHAR        filename [MAX_PATH];
2525     WCHAR        inipath [MAX_PATH];
2526     BOOL         keyopen = FALSE;
2527     DWORD        length;
2528     HKEY         productkey;
2529     LONG         regstatus;
2530     struct _stat s;
2531     DWORD        valuetype;
2532
2533     if (_wstat(L".\\vld.ini", &s) == 0) {
2534         // Found a copy of vld.ini in the working directory. Use it.
2535         wcsncpy_s(inipath, MAX_PATH, L".\\vld.ini", _TRUNCATE);
2536     }
2537     else {
2538         // Get the location of the vld.ini file from the registry.
2539         regstatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, VLDREGKEYPRODUCT, 0, KEY_QUERY_VALUE, &productkey);
2540         if (regstatus == ERROR_SUCCESS) {
2541             keyopen = TRUE;
2542             regstatus = RegQueryValueEx(productkey, L"IniFile", NULL, &valuetype, (LPBYTE)&inipath, &length);
2543         }
2544         if (keyopen) {
2545             RegCloseKey(productkey);
2546         }
2547         if ((regstatus != ERROR_SUCCESS) || (_wstat(inipath, &s) != 0)) {
2548             // The location of vld.ini could not be read from the registry. As a
2549             // last resort, look in the Windows directory.
2550             wcsncpy_s(inipath, MAX_PATH, L"vld.ini", _TRUNCATE);
2551         }
2552     }
2553
2554     // Read the boolean options.
2555     GetPrivateProfileString(L"Options", L"VLD", L"on", buffer, BSIZE, inipath);
2556     if (strtobool(buffer) == FALSE) {
2557         m_options |= VLD_OPT_VLDOFF;
2558         return;
2559     }
2560
2561     GetPrivateProfileString(L"Options", L"AggregateDuplicates", L"", buffer, BSIZE, inipath);
2562     if (strtobool(buffer) == TRUE) {
2563         m_options |= VLD_OPT_AGGREGATE_DUPLICATES;
2564     }
2565
2566     GetPrivateProfileString(L"Options", L"SelfTest", L"", buffer, BSIZE, inipath);
2567     if (strtobool(buffer) == TRUE) {
2568         m_options |= VLD_OPT_SELF_TEST;
2569     }
2570
2571     GetPrivateProfileString(L"Options", L"SlowDebuggerDump", L"", buffer, BSIZE, inipath);
2572     if (strtobool(buffer) == TRUE) {
2573         m_options |= VLD_OPT_SLOW_DEBUGGER_DUMP;
2574     }
2575
2576     GetPrivateProfileString(L"Options", L"StartDisabled", L"", buffer, BSIZE, inipath);
2577     if (strtobool(buffer) == TRUE) {
2578         m_options |= VLD_OPT_START_DISABLED;
2579     }
2580
2581     GetPrivateProfileString(L"Options", L"TraceInternalFrames", L"", buffer, BSIZE, inipath);
2582     if (strtobool(buffer) == TRUE) {
2583         m_options |= VLD_OPT_TRACE_INTERNAL_FRAMES;
2584     }
2585
2586     // Read the integer configuration options.
2587     m_maxdatadump = GetPrivateProfileInt(L"Options", L"MaxDataDump", VLD_DEFAULT_MAX_DATA_DUMP, inipath);
2588     m_maxtraceframes = GetPrivateProfileInt(L"Options", L"MaxTraceFrames", VLD_DEFAULT_MAX_TRACE_FRAMES, inipath);
2589     if (m_maxtraceframes < 1) {
2590         m_maxtraceframes = VLD_DEFAULT_MAX_TRACE_FRAMES;
2591     }
2592
2593     // Read the force-include module list.
2594     GetPrivateProfileString(L"Options", L"ForceIncludeModules", L"", m_forcedmodulelist, MAXMODULELISTLENGTH, inipath);
2595     _wcslwr_s(m_forcedmodulelist, MAXMODULELISTLENGTH);
2596
2597     // Read the report destination (debugger, file, or both).
2598     GetPrivateProfileString(L"Options", L"ReportFile", L"", filename, MAX_PATH, inipath);
2599     if (wcslen(filename) == 0) {
2600         wcsncpy_s(filename, MAX_PATH, VLD_DEFAULT_REPORT_FILE_NAME, _TRUNCATE);
2601     }
2602     _wfullpath(m_reportfilepath, filename, MAX_PATH);
2603     GetPrivateProfileString(L"Options", L"ReportTo", L"", buffer, BSIZE, inipath);
2604     if (_wcsicmp(buffer, L"both") == 0) {
2605         m_options |= (VLD_OPT_REPORT_TO_DEBUGGER | VLD_OPT_REPORT_TO_FILE);
2606     }
2607     else if (_wcsicmp(buffer, L"file") == 0) {
2608         m_options |= VLD_OPT_REPORT_TO_FILE;
2609     }
2610     else {
2611         m_options |= VLD_OPT_REPORT_TO_DEBUGGER;
2612     }
2613
2614     // Read the report file encoding (ascii or unicode).
2615     GetPrivateProfileString(L"Options", L"ReportEncoding", L"", buffer, BSIZE, inipath);
2616     if (_wcsicmp(buffer, L"unicode") == 0) {
2617         m_options |= VLD_OPT_UNICODE_REPORT;
2618     }
2619     if ((m_options & VLD_OPT_UNICODE_REPORT) && !(m_options & VLD_OPT_REPORT_TO_FILE)) {
2620         // If Unicode report encoding is enabled, then the report needs to be
2621         // sent to a file because the debugger will not display Unicode
2622         // characters, it will display question marks in their place instead.
2623         m_options |= VLD_OPT_REPORT_TO_FILE;
2624         m_status |= VLD_STATUS_FORCE_REPORT_TO_FILE;
2625     }
2626
2627     // Read the stack walking method.
2628     GetPrivateProfileString(L"Options", L"StackWalkMethod", L"", buffer, BSIZE, inipath);
2629     if (_wcsicmp(buffer, L"safe") == 0) {
2630         m_options |= VLD_OPT_SAFE_STACK_WALK;
2631     }
2632 }
2633
2634 // detachfrommodule - Callback function for EnumerateLoadedModules64 that
2635 //   detaches Visual Leak Detector from the specified module. If the specified
2636 //   module has not previously been attached to, then calling this function will
2637 //   not actually result in any changes.
2638 //
2639 //  - modulepath (IN): String containing the name, which may inlcude a path, of
2640 //      the module to detach from (ignored).
2641 //
2642 //  - modulebase (IN): Base address of the module.
2643 //
2644 //  - modulesize (IN): Total size of the module (ignored).
2645 //
2646 //  - context (IN): User-supplied context (ignored).
2647 //
2648 //  Return Value:
2649 //
2650 //    Always returns TRUE.
2651 //
2652 BOOL VisualLeakDetector::detachfrommodule (PCWSTR /*modulepath*/, DWORD64 modulebase, ULONG /*modulesize*/,
2653                                            PVOID /*context*/)
2654 {
2655     UINT tablesize = sizeof(m_patchtable) / sizeof(patchentry_t);
2656
2657     restoremodule((HMODULE)modulebase, m_patchtable, tablesize);
2658
2659     return TRUE;
2660 }
2661
2662 // DidAlloc - Calls to IMalloc::DidAlloc will end up here. This function is just
2663 //   a wrapper around the system implementation of IMalloc::DidAlloc.
2664 //
2665 //  - mem (IN): Pointer to a memory block to inquire about.
2666 //
2667 //  Return Value:
2668 //
2669 //    Returns the value returned by the system implementation of
2670 //    IMalloc::DidAlloc.
2671 //
2672 INT VisualLeakDetector::DidAlloc (LPVOID mem)
2673 {
2674     assert(m_imalloc != NULL);
2675     return m_imalloc->DidAlloc(mem);
2676 }
2677
2678 // enabled - Determines if memory leak detection is enabled for the current
2679 //   thread.
2680 //
2681 //  Return Value:
2682 //
2683 //    Returns true if Visual Leak Detector is enabled for the current thread.
2684 //    Otherwise, returns false.
2685 //
2686 BOOL VisualLeakDetector::enabled ()
2687 {
2688     tls_t *tls = vld.gettls();
2689
2690     if (!(m_status & VLD_STATUS_INSTALLED)) {
2691         // Memory leak detection is not yet enabled because VLD is still
2692         // initializing.
2693         return FALSE;
2694     }
2695
2696     if (!(tls->flags & VLD_TLS_DISABLED) && !(tls->flags & VLD_TLS_ENABLED)) {
2697         // The enabled/disabled state for the current thread has not been 
2698         // initialized yet. Use the default state.
2699         if (m_options & VLD_OPT_START_DISABLED) {
2700             tls->flags |= VLD_TLS_DISABLED;
2701         }
2702         else {
2703             tls->flags |= VLD_TLS_ENABLED;
2704         }
2705     }
2706
2707     return ((tls->flags & VLD_TLS_ENABLED) != 0);
2708 }
2709
2710 // eraseduplicates - Erases, from the block maps, blocks that appear to be
2711 //   duplicate leaks of an already identified leak.
2712 //
2713 //  - element (IN): BlockMap Iterator referencing the block of which to search
2714 //      for duplicates.
2715 //
2716 //  Return Value:
2717 //
2718 //    Returns the number of duplicate blocks erased from the block map.
2719 //
2720 SIZE_T VisualLeakDetector::eraseduplicates (const BlockMap::Iterator &element)
2721 {
2722     BlockMap::Iterator  blockit;
2723     BlockMap           *blockmap;
2724     blockinfo_t        *elementinfo;
2725     SIZE_T              erased = 0;
2726     HeapMap::Iterator   heapit;
2727     blockinfo_t        *info;
2728     BlockMap::Iterator  previt;
2729
2730     elementinfo = (*element).second;
2731
2732     // Iteratate through all block maps, looking for blocks with the same size
2733     // and callstack as the specified element.
2734     for (heapit = m_heapmap->begin(); heapit != m_heapmap->end(); ++heapit) {
2735         blockmap = &(*heapit).second->blockmap;
2736         for (blockit = blockmap->begin(); blockit != blockmap->end(); ++blockit) {
2737             if (blockit == element) {
2738                 // Don't delete the element of which we are searching for
2739                 // duplicates.
2740                 continue;
2741             }
2742             info = (*blockit).second;
2743             if ((info->size == elementinfo->size) && (*(info->callstack) == *(elementinfo->callstack))) {
2744                 // Found a duplicate. Erase it.
2745                 delete info->callstack;
2746                 delete info;
2747                 previt = blockit - 1;
2748                 blockmap->erase(blockit);
2749                 blockit = previt;
2750                 erased++;
2751             }
2752         }
2753     }
2754
2755     return erased;
2756 }
2757
2758 // Free - Calls to IMalloc::Free will end up here. This function is just a
2759 //   wrapper around the real IMalloc::Free implementation.
2760 //
2761 //  - mem (IN): Pointer to the memory block to be freed.
2762 //
2763 //  Return Value:
2764 //
2765 //    None.
2766 //
2767 VOID VisualLeakDetector::Free (LPVOID mem)
2768 {
2769     assert(m_imalloc != NULL);
2770     m_imalloc->Free(mem);
2771 }
2772
2773 // GetSize - Calls to IMalloc::GetSize will end up here. This function is just a
2774 //   wrapper around the real IMalloc::GetSize implementation.
2775 //
2776 //  - mem (IN): Pointer to the memory block to inquire about.
2777 //
2778 //  Return Value:
2779 //
2780 //    Returns the value returned by the system implementation of
2781 //    IMalloc::GetSize.
2782 //
2783 ULONG VisualLeakDetector::GetSize (LPVOID mem)
2784 {
2785     assert(m_imalloc != NULL);
2786     return m_imalloc->GetSize(mem);
2787 }
2788
2789 // gettls - Obtains the thread local strorage structure for the calling thread.
2790 //
2791 //  Return Value:
2792 //
2793 //    Returns a pointer to the thread local storage structure. (This function
2794 //    always succeeds).
2795 //
2796 tls_t* VisualLeakDetector::gettls ()
2797 {
2798     tls_t *tls;
2799     
2800     // Get the pointer to this thread's thread local storage structure.
2801     tls = (tls_t*)TlsGetValue(m_tlsindex);
2802     assert(GetLastError() == ERROR_SUCCESS);
2803
2804     if (tls == NULL) {
2805         // This thread's thread local storage structure has not been allocated.
2806         tls = new tls_t;
2807         TlsSetValue(m_tlsindex, tls);
2808         tls->addrfp = 0x0;
2809         tls->flags = 0x0;
2810         tls->threadid = GetCurrentThreadId();
2811
2812         // Add this thread's TLS to the TlsSet.
2813         EnterCriticalSection(&m_tlslock);
2814         m_tlsset->insert(tls);
2815         LeaveCriticalSection(&m_tlslock);
2816     }
2817
2818     return tls;
2819 }
2820
2821 // HeapMinimize - Calls to IMalloc::HeapMinimize will end up here. This function
2822 //   is just a wrapper around the real IMalloc::HeapMinimize implementation.
2823 //
2824 //  Return Value:
2825 //
2826 //    None.
2827 //
2828 VOID VisualLeakDetector::HeapMinimize ()
2829 {
2830     assert(m_imalloc != NULL);
2831     m_imalloc->HeapMinimize();
2832 }
2833
2834 // mapblock - Tracks memory allocations. Information about allocated blocks is
2835 //   collected and then the block is mapped to this information.
2836 //
2837 //  - heap (IN): Handle to the heap from which the block has been allocated.
2838 //
2839 //  - mem (IN): Pointer to the memory block being allocated.
2840 //
2841 //  - size (IN): Size, in bytes, of the memory block being allocated.
2842 //
2843 //  - framepointer (IN): Framepointer at the time this allocation first entered
2844 //      VLD's code. This is used from determining the starting point for the
2845 //      stack trace.
2846 //
2847 //  - crtalloc (IN): Should be set to TRUE if this allocation is a CRT memory
2848 //      block. Otherwise should be FALSE.
2849 //
2850 //  Return Value:
2851 //
2852 //    None.
2853 //
2854 VOID VisualLeakDetector::mapblock (HANDLE heap, LPCVOID mem, SIZE_T size, SIZE_T framepointer, BOOL crtalloc)
2855 {
2856     blockinfo_t        *blockinfo;
2857     BlockMap::Iterator  blockit;
2858     BlockMap           *blockmap;
2859     HeapMap::Iterator   heapit;
2860     static SIZE_T       serialnumber = 0;
2861
2862     // Record the block's information.
2863     blockinfo = new blockinfo_t;
2864     if (m_options & VLD_OPT_SAFE_STACK_WALK) {
2865         blockinfo->callstack = new SafeCallStack;
2866     }
2867     else {
2868         blockinfo->callstack = new FastCallStack;
2869     }
2870     if (m_options & VLD_OPT_TRACE_INTERNAL_FRAMES) {
2871         // Passing NULL for the frame pointer argument will force the stack
2872         // trace to begin at the current frame.
2873         blockinfo->callstack->getstacktrace(m_maxtraceframes, NULL);
2874     }
2875     else {
2876         // Start the stack trace at the call that first entered VLD's code.
2877         blockinfo->callstack->getstacktrace(m_maxtraceframes, (SIZE_T*)framepointer);
2878     }
2879     blockinfo->serialnumber = serialnumber++;
2880     blockinfo->size = size;
2881
2882     // Insert the block's information into the block map.
2883     EnterCriticalSection(&m_maplock);
2884     heapit = m_heapmap->find(heap);
2885     if (heapit == m_heapmap->end()) {
2886         // We haven't mapped this heap to a block map yet. Do it now.
2887         mapheap(heap);
2888         heapit = m_heapmap->find(heap);
2889         assert(heapit != m_heapmap->end());
2890     }
2891     if (crtalloc == TRUE) {
2892         // The heap that this block was allocated from is a CRT heap.
2893         (*heapit).second->flags |= VLD_HEAP_CRT;
2894     }
2895     blockmap = &(*heapit).second->blockmap;
2896     blockit = blockmap->insert(mem, blockinfo);
2897     if (blockit == blockmap->end()) {
2898         // A block with this address has already been allocated. The
2899         // previously allocated block must have been freed (probably by some
2900         // mechanism unknown to VLD), or the heap wouldn't have allocated it
2901         // again. Replace the previously allocated info with the new info.
2902         blockit = blockmap->find(mem);
2903         delete (*blockit).second->callstack;
2904         delete (*blockit).second;
2905         blockmap->erase(blockit);
2906         blockmap->insert(mem, blockinfo);
2907     }
2908     LeaveCriticalSection(&m_maplock);
2909 }
2910
2911 // mapheap - Tracks heap creation. Creates a block map for tracking individual
2912 //   allocations from the newly created heap and then maps the heap to this
2913 //   block map.
2914 //
2915 //  - heap (IN): Handle to the newly created heap.
2916 //
2917 //  Return Value:
2918 //
2919 //    None.
2920 //
2921 VOID VisualLeakDetector::mapheap (HANDLE heap)
2922 {
2923     heapinfo_t        *heapinfo;
2924     HeapMap::Iterator  heapit;
2925
2926     // Create a new block map for this heap and insert it into the heap map.
2927     heapinfo = new heapinfo_t;
2928     heapinfo->blockmap.reserve(BLOCKMAPRESERVE);
2929     heapinfo->flags = 0x0;
2930     EnterCriticalSection(&m_maplock);
2931     heapit = m_heapmap->insert(heap, heapinfo);
2932     if (heapit == m_heapmap->end()) {
2933         // Somehow this heap has been created twice without being destroyed,
2934         // or at least it was destroyed without VLD's knowledge. Unmap the heap
2935         // from the existing heapinfo, and remap it to the new one.
2936         report(L"WARNING: Visual Leak Detector detected a duplicate heap (" ADDRESSFORMAT L").\n", heap);
2937         heapit = m_heapmap->find(heap);
2938         unmapheap((*heapit).first);
2939         m_heapmap->insert(heap, heapinfo);
2940     }
2941     LeaveCriticalSection(&m_maplock);
2942 }
2943
2944 // QueryInterface - Calls to IMalloc::QueryInterface will end up here. This
2945 //   function is just a wrapper around the real IMalloc::QueryInterface
2946 //   implementation.
2947 //
2948 //  - iid (IN): COM interface ID to query about.
2949 //
2950 //  - object (IN): Address of a pointer to receive the requested interface
2951 //      pointer.
2952 //
2953 //  Return Value:
2954 //
2955 //    Returns the value returned by the system implementation of
2956 //    IMalloc::QueryInterface.
2957 //
2958 HRESULT VisualLeakDetector::QueryInterface (REFIID iid, LPVOID *object)
2959 {
2960     assert(m_imalloc != NULL);
2961     return m_imalloc->QueryInterface(iid, object);
2962 }
2963
2964 // Realloc - Calls to IMalloc::Realloc will end up here. This function is just a
2965 //   wrapper around the real IMalloc::Realloc implementation that sets
2966 //   appropriate flags to be consulted when the memory is actually allocated by
2967 //   RtlAllocateHeap.
2968 //
2969 //  - mem (IN): Pointer to the memory block to reallocate.
2970 //
2971 //  - size (IN): Size, in bytes, of the memory block to reallocate.
2972 //
2973 //  Return Value:
2974 //
2975 //    Returns the value returned by the system implementation of
2976 //    IMalloc::Realloc.
2977 //
2978 LPVOID VisualLeakDetector::Realloc (LPVOID mem, ULONG size)
2979 {
2980     LPVOID  block;
2981     SIZE_T  fp;
2982     tls_t  *tls = vld.gettls();
2983
2984     if (tls->addrfp == 0x0) {
2985         // This is the first call to enter VLD for the current allocation.
2986         // Record the current frame pointer.
2987         FRAMEPOINTER(fp);
2988         tls->addrfp = fp;
2989     }
2990
2991     // Do the allocation. The block will be mapped by _RtlReAllocateHeap.
2992     assert(m_imalloc != NULL);
2993     block = m_imalloc->Realloc(mem, size);
2994
2995     // Reset thread local flags and variables for the next allocation.
2996     tls->addrfp = 0x0;
2997     tls->flags &= ~VLD_TLS_CRTALLOC;
2998     
2999     return block;
3000 }
3001
3002 // Release - Calls to IMalloc::Release will end up here. This function is just
3003 //   a wrapper around the real IMalloc::Release implementation.
3004 //
3005 //  Return Value:
3006 //
3007 //    Returns the value returned by the system implementation of
3008 //    IMalloc::Release.
3009 //
3010 ULONG VisualLeakDetector::Release ()
3011 {
3012     assert(m_imalloc != NULL);
3013     return m_imalloc->Release();
3014 }
3015
3016 // remapblock - Tracks reallocations. Unmaps a block from its previously
3017 //   collected information and remaps it to updated information.
3018 //
3019 //  Note: If the block itself remains at the same address, then the block's
3020 //   information can simply be updated rather than having to actually erase and
3021 //   reinsert the block.
3022 //
3023 //  - heap (IN): Handle to the heap from which the memory is being reallocated.
3024 //
3025 //  - mem (IN): Pointer to the memory block being reallocated.
3026 //
3027 //  - newmem (IN): Pointer to the memory block being returned to the caller
3028 //      that requested the reallocation. This pointer may or may not be the same
3029 //      as the original memory block (as pointed to by "mem").
3030 //
3031 //  - size (IN): Size, in bytes, of the new memory block.
3032 //
3033 //  - framepointer (IN): The frame pointer at which this reallocation entered
3034 //      VLD's code. Used for determining the starting point of the stack trace.
3035 //
3036 //  - crtalloc (IN): Should be set to TRUE if this reallocation is for a CRT
3037 //      memory block. Otherwise should be set to FALSE.
3038 //
3039 //  Return Value:
3040 //
3041 //    None.
3042 //
3043 VOID VisualLeakDetector::remapblock (HANDLE heap, LPCVOID mem, LPCVOID newmem, SIZE_T size, SIZE_T framepointer,
3044                                      BOOL crtalloc)
3045 {
3046     BlockMap::Iterator   blockit;
3047     BlockMap            *blockmap;
3048     HeapMap::Iterator    heapit;
3049     blockinfo_t         *info;
3050
3051     if (newmem != mem) {
3052         // The block was not reallocated in-place. Instead the old block was
3053         // freed and a new block allocated to satisfy the new size.
3054         unmapblock(heap, mem);
3055         mapblock(heap, newmem, size, framepointer, crtalloc);
3056         return;
3057     }
3058
3059     // The block was reallocated in-place. Find the existing blockinfo_t
3060     // entry in the block map and update it with the new callstack and size.
3061     EnterCriticalSection(&m_maplock);
3062     heapit = m_heapmap->find(heap);
3063     if (heapit == m_heapmap->end()) {
3064         // We haven't mapped this heap to a block map yet. Obviously the
3065         // block has also not been mapped to a blockinfo_t entry yet either,
3066         // so treat this reallocation as a brand-new allocation (this will
3067         // also map the heap to a new block map).
3068         mapblock(heap, newmem, size, framepointer, crtalloc);
3069         LeaveCriticalSection(&m_maplock);
3070         return;
3071     }
3072
3073     // Find the block's blockinfo_t structure so that we can update it.
3074     blockmap = &(*heapit).second->blockmap;
3075     blockit = blockmap->find(mem);
3076     if (blockit == blockmap->end()) {
3077         // The block hasn't been mapped to a blockinfo_t entry yet.
3078         // Treat this reallocation as a new allocation.
3079         mapblock(heap, newmem, size, framepointer, crtalloc);
3080         LeaveCriticalSection(&m_maplock);
3081         return;
3082     }
3083
3084     // Found the blockinfo_t entry for this block. Update it with
3085     // a new callstack and new size.
3086     info = (*blockit).second;
3087     info->callstack->clear();
3088     if (crtalloc) {
3089         // The heap that this block was allocated from is a CRT heap.
3090         (*heapit).second->flags |= VLD_HEAP_CRT;
3091     }
3092     LeaveCriticalSection(&m_maplock);
3093
3094     // Update the block's callstack and size.
3095     if (m_options & VLD_OPT_TRACE_INTERNAL_FRAMES) {
3096         // Passing NULL for the frame pointer argument will force
3097         // the stack trace to begin at the current frame.
3098         info->callstack->getstacktrace(m_maxtraceframes, NULL);
3099     }
3100     else {
3101         // Start the stack trace at the call that first entered
3102         // VLD's code.
3103         info->callstack->getstacktrace(m_maxtraceframes, (SIZE_T*)framepointer);
3104     }
3105     info->size = size;
3106 }
3107
3108 // reportconfig - Generates a brief report summarizing Visual Leak Detector's
3109 //   configuration, as loaded from the vld.ini file.
3110 //
3111 //  Return Value:
3112 //
3113 //    None.
3114 //
3115 VOID VisualLeakDetector::reportconfig ()
3116 {
3117     if (m_options & VLD_OPT_AGGREGATE_DUPLICATES) {
3118         report(L"    Aggregating duplicate leaks.\n");
3119     }
3120     if (wcslen(m_forcedmodulelist) != 0) {
3121         report(L"    Forcing inclusion of these modules in leak detection: %s\n", m_forcedmodulelist);
3122     }
3123     if (m_maxdatadump != VLD_DEFAULT_MAX_DATA_DUMP) {
3124         if (m_maxdatadump == 0) {
3125             report(L"    Suppressing data dumps.\n");
3126         }
3127         else {
3128             report(L"    Limiting data dumps to %lu bytes.\n", m_maxdatadump);
3129         }
3130     }
3131     if (m_maxtraceframes != VLD_DEFAULT_MAX_TRACE_FRAMES) {
3132         report(L"    Limiting stack traces to %u frames.\n", m_maxtraceframes);
3133     }
3134     if (m_options & VLD_OPT_UNICODE_REPORT) {
3135         report(L"    Generating a Unicode (UTF-16) encoded report.\n");
3136     }
3137     if (m_options & VLD_OPT_REPORT_TO_FILE) {
3138         if (m_options & VLD_OPT_REPORT_TO_DEBUGGER) {
3139             report(L"    Outputting the report to the debugger and to %s\n", m_reportfilepath);
3140         }
3141         else {
3142             report(L"    Outputting the report to %s\n", m_reportfilepath);
3143         }
3144     }
3145     if (m_options & VLD_OPT_SLOW_DEBUGGER_DUMP) {
3146         report(L"    Outputting the report to the debugger at a slower rate.\n");
3147     }
3148     if (m_options & VLD_OPT_SAFE_STACK_WALK) {
3149         report(L"    Using the \"safe\" (but slow) stack walking method.\n");
3150     }
3151     if (m_options & VLD_OPT_SELF_TEST) {
3152         report(L"    Perfoming a memory leak self-test.\n");
3153     }
3154     if (m_options & VLD_OPT_START_DISABLED) {
3155         report(L"    Starting with memory leak detection disabled.\n");
3156     }
3157     if (m_options & VLD_OPT_TRACE_INTERNAL_FRAMES) {
3158         report(L"    Including heap and VLD internal frames in stack traces.\n");
3159     }
3160 }
3161
3162 // reportleaks - Generates a memory leak report for the specified heap.
3163 //
3164 //  - heap (IN): Handle to the heap for which to generate a memory leak
3165 //      report.
3166 //
3167 //  Return Value:
3168 //
3169 //    None.
3170 //
3171 VOID VisualLeakDetector::reportleaks (HANDLE heap)
3172 {
3173     LPCVOID              address;
3174     LPCVOID              block;
3175     BlockMap::Iterator   blockit;
3176     BlockMap            *blockmap;
3177     crtdbgblockheader_t *crtheader;
3178     SIZE_T               duplicates;
3179     heapinfo_t          *heapinfo;
3180     HeapMap::Iterator    heapit;
3181     blockinfo_t         *info;
3182     SIZE_T               size;
3183
3184     // Find the heap's information (blockmap, etc).
3185     EnterCriticalSection(&m_maplock);
3186     heapit = m_heapmap->find(heap);
3187     if (heapit == m_heapmap->end()) {
3188         // Nothing is allocated from this heap. No leaks.
3189         LeaveCriticalSection(&m_maplock);
3190         return;
3191     }
3192
3193     heapinfo = (*heapit).second;
3194     blockmap = &heapinfo->blockmap;
3195     for (blockit = blockmap->begin(); blockit != blockmap->end(); ++blockit) {
3196         // Found a block which is still in the BlockMap. We've identified a
3197         // potential memory leak.
3198         block = (*blockit).first;
3199         info = (*blockit).second;
3200         address = block;
3201         size = info->size;
3202         if (heapinfo->flags & VLD_HEAP_CRT) {
3203             // This block is allocated to a CRT heap, so the block has a CRT
3204             // memory block header prepended to it.
3205             crtheader = (crtdbgblockheader_t*)block;
3206             if (CRT_USE_TYPE(crtheader->use) == CRT_USE_INTERNAL) {
3207                 // This block is marked as being used internally by the CRT.
3208                 // The CRT will free the block after VLD is destroyed.
3209                 continue;
3210             }
3211             // The CRT header is more or less transparent to the user, so
3212             // the information about the contained block will probably be
3213             // more useful to the user. Accordingly, that's the information
3214             // we'll include in the report.
3215             address = CRTDBGBLOCKDATA(block);
3216             size = crtheader->size;
3217         }
3218         // It looks like a real memory leak.
3219         if (m_leaksfound == 0) {
3220             report(L"WARNING: Visual Leak Detector detected memory leaks!\n");
3221         }
3222         m_leaksfound++;
3223         report(L"---------- Block %ld at " ADDRESSFORMAT L": %u bytes ----------\n", info->serialnumber, address, size);
3224         if (m_options & VLD_OPT_AGGREGATE_DUPLICATES) {
3225             // Aggregate all other leaks which are duplicates of this one
3226             // under this same heading, to cut down on clutter.
3227             duplicates = eraseduplicates(blockit);
3228             if (duplicates) {
3229                 report(L"A total of %lu leaks match this size and call stack. Showing only the first one.\n",
3230                        duplicates + 1);
3231                 m_leaksfound += duplicates;
3232             }
3233         }
3234         // Dump the call stack.
3235         report(L"  Call Stack:\n");
3236         info->callstack->dump(m_options & VLD_OPT_TRACE_INTERNAL_FRAMES);
3237         // Dump the data in the user data section of the memory block.
3238         if (m_maxdatadump != 0) {
3239             report(L"  Data:\n");
3240             if (m_options & VLD_OPT_UNICODE_REPORT) {
3241                 dumpmemoryw(address, (m_maxdatadump < size) ? m_maxdatadump : size);
3242             }
3243             else {
3244                 dumpmemorya(address, (m_maxdatadump < size) ? m_maxdatadump : size);
3245             }
3246         }
3247         report(L"\n");
3248     }
3249
3250     LeaveCriticalSection(&m_maplock);
3251 }
3252
3253 // unmapblock - Tracks memory blocks that are freed. Unmaps the specified block
3254 //   from the block's information, relinquishing internally allocated resources.
3255 //
3256 //  - heap (IN): Handle to the heap to which this block is being freed.
3257 //
3258 //  - mem (IN): Pointer to the memory block being freed.
3259 //
3260 //  Return Value:
3261 //
3262 //    None.
3263 //
3264 VOID VisualLeakDetector::unmapblock (HANDLE heap, LPCVOID mem)
3265 {
3266     BlockMap::Iterator  blockit;
3267     BlockMap           *blockmap;
3268     HeapMap::Iterator   heapit;
3269     blockinfo_t        *info;
3270
3271     // Find this heap's block map.
3272     EnterCriticalSection(&m_maplock);
3273     heapit = m_heapmap->find(heap);
3274     if (heapit == m_heapmap->end()) {
3275         // We don't have a block map for this heap. We must not have monitored
3276         // this allocation (probably happened before VLD was initialized).
3277         LeaveCriticalSection(&m_maplock);
3278         return;
3279     }
3280
3281     // Find this block in the block map.
3282     blockmap = &(*heapit).second->blockmap;
3283     blockit = blockmap->find(mem);
3284     if (blockit == blockmap->end()) {
3285         // This block is not in the block map. We must not have monitored this
3286         // allocation (probably happened before VLD was initialized).
3287         LeaveCriticalSection(&m_maplock);
3288         return;
3289     }
3290
3291     // Free the blockinfo_t structure and erase it from the block map.
3292     info = (*blockit).second;
3293     delete info->callstack;
3294     delete info;
3295     blockmap->erase(blockit);
3296     LeaveCriticalSection(&m_maplock);
3297 }
3298
3299 // unmapheap - Tracks heap destruction. Unmaps the specified heap from its block
3300 //   map. The block map is cleared and deleted, relinquishing internally
3301 //   allocated resources.
3302 //
3303 //  - heap (IN): Handle to the heap which is being destroyed.
3304 //
3305 //  Return Value:
3306 //
3307 //    None.
3308 //
3309 VOID VisualLeakDetector::unmapheap (HANDLE heap)
3310 {
3311     BlockMap::Iterator  blockit;
3312     BlockMap           *blockmap;
3313     heapinfo_t         *heapinfo;
3314     HeapMap::Iterator   heapit;
3315
3316     // Find this heap's block map.
3317     EnterCriticalSection(&m_maplock);
3318     heapit = m_heapmap->find(heap);
3319     if (heapit == m_heapmap->end()) {
3320         // This heap hasn't been mapped. We must not have monitored this heap's
3321         // creation (probably happened before VLD was initialized).
3322         LeaveCriticalSection(&m_maplock);
3323         return;
3324     }
3325
3326     // Free all of the blockinfo_t structures stored in the block map.
3327     heapinfo = (*heapit).second;
3328     blockmap = &heapinfo->blockmap;
3329     for (blockit = blockmap->begin(); blockit != blockmap->end(); ++blockit) {
3330         delete (*blockit).second->callstack;
3331         delete (*blockit).second;
3332     }
3333     delete heapinfo;
3334
3335     // Remove this heap's block map from the heap map.
3336     m_heapmap->erase(heapit);
3337     LeaveCriticalSection(&m_maplock);
3338 }