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