Quake II RTX doxygen  1.0 dev
debug.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 
19 //
20 // win_dbg.c -- crash dump generation
21 //
22 
23 #include "client.h"
24 #include <dbghelp.h>
25 
26 typedef DWORD (WINAPI *SETSYMOPTIONS)(DWORD);
27 typedef BOOL (WINAPI *SYMGETMODULEINFO64)(HANDLE, DWORD64,
28  PIMAGEHLP_MODULE64);
29 typedef BOOL (WINAPI *SYMINITIALIZE)(HANDLE, PSTR, BOOL);
30 typedef BOOL (WINAPI *SYMCLEANUP)(HANDLE);
31 typedef BOOL (WINAPI *ENUMERATELOADEDMODULES64)(HANDLE,
32  PENUMLOADED_MODULES_CALLBACK64, PVOID);
33 typedef BOOL (WINAPI *STACKWALK64)(DWORD, HANDLE, HANDLE, LPSTACKFRAME64,
34  PVOID, PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64,
35  PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64);
36 typedef BOOL (WINAPI *SYMFROMADDR)(HANDLE, DWORD64, PDWORD64, PSYMBOL_INFO);
37 typedef PVOID(WINAPI *SYMFUNCTIONTABLEACCESS64)(HANDLE, DWORD64);
38 typedef DWORD64(WINAPI *SYMGETMODULEBASE64)(HANDLE, DWORD64);
39 typedef BOOL (WINAPI *GETFILEVERSIONINFOA)(LPCSTR, DWORD, DWORD, PVOID);
40 typedef BOOL (WINAPI *VERQUERYVALUEA)(const LPVOID, LPSTR, LPVOID *, PUINT);
41 typedef HINSTANCE(WINAPI *SHELLEXECUTEA)(HWND, LPCSTR, LPCSTR,
42  LPCSTR, LPCSTR, INT);
43 
56 
59 STATIC CHAR faultyModuleName[MAX_PATH];
61 
62 #define MI_SIZE_V1 584
63 #define MI_SIZE_V2 1664
64 #define MI_SIZE_V3 1672
65 
66 // google://dbghelp+not+backwards+compatible
67 STATIC CONST DWORD tryModuleSizes[4] = {
68  sizeof(IMAGEHLP_MODULE64), MI_SIZE_V3, MI_SIZE_V2, MI_SIZE_V1
69 };
70 
71 static const char monthNames[12][4] = {
72  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
73  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
74 };
75 
76 #define PRIxx64 "#.16I64x"
77 #define PRIxx32 "#.8I32x"
78 
79 // holy crap! fighting the `nice' 64-bit only APIs
80 #ifdef _WIN64
81 #define PRIxx PRIxx64
82 #define WORDxx(x) ((DWORD64)(x))
83 #else
84 #define PRIxx PRIxx32
85 #define WORDxx(x) ((DWORD32)(x))
86 #endif
87 
88 // does not check for overflow!
89 STATIC VOID write_report(LPCTSTR fmt, ...)
90 {
91  TCHAR buf[1024];
92  va_list argptr;
93  int len;
94  DWORD written;
95 
96  va_start(argptr, fmt);
97  len = wvsprintf(buf, fmt, argptr);
98  va_end(argptr);
99 
100  if (len > 0 && len < 1024) {
101  WriteFile(crashReport, buf, len, &written, NULL);
102  }
103 }
104 
106  PCSTR ModuleName,
107  DWORD64 ModuleBase,
108  ULONG ModuleSize,
109  PVOID UserContext)
110 {
111  IMAGEHLP_MODULE64 moduleInfo;
112  DWORD64 pc = *(DWORD64 *)UserContext;
113  BYTE buffer[4096];
114  PBYTE data;
115  UINT numBytes;
116  VS_FIXEDFILEINFO *info;
117  char version[64];
118  char *symbols, *star;
119  int len;
120  BOOL ret;
121 
122  len = lstrlen(ModuleName);
123  if (len >= MAX_PATH) {
124  return TRUE;
125  }
126 
127  if (pGetFileVersionInfoA(ModuleName, 0, sizeof(buffer), buffer) &&
128  pVerQueryValueA(buffer, "\\", (LPVOID *)&data, &numBytes) &&
129  numBytes >= sizeof(*info)) {
130  info = (VS_FIXEDFILEINFO *)data;
131  wsprintf(version, "%u.%u.%u.%u",
132  HIWORD(info->dwFileVersionMS),
133  LOWORD(info->dwFileVersionMS),
134  HIWORD(info->dwFileVersionLS),
135  LOWORD(info->dwFileVersionLS));
136  } else {
137  CopyMemory(version, "unknown", 8);
138  }
139 
140  moduleInfo.SizeOfStruct = moduleInfoSize;
141  ret = pSymGetModuleInfo64(
143  ModuleBase,
144  &moduleInfo);
145  if (ret) {
146  ModuleName = moduleInfo.ModuleName;
147  switch (moduleInfo.SymType) {
148  case SymNone: symbols = "none"; break;
149  case SymCoff: symbols = "COFF"; break;
150  case SymPdb: symbols = "PDB"; break;
151  case SymExport: symbols = "export"; break;
152  case SymVirtual: symbols = "virtual"; break;
153  default: symbols = "unknown"; break;
154  }
155  } else {
156  write_report("SymGetModuleInfo64 failed with error %#x\r\n",
157  GetLastError());
158  symbols = "failed";
159  }
160 
161  if (pc >= ModuleBase && pc < ModuleBase + ModuleSize) {
162  CopyMemory(faultyModuleName, ModuleName, len + 1);
163  star = " *";
164  } else {
165  star = "";
166  }
167 
168  write_report(
169  "%"PRIxx" %"PRIxx" %s (version %s, symbols %s)%s\r\n",
170  WORDxx(ModuleBase), WORDxx(ModuleBase + ModuleSize),
171  ModuleName, version, symbols, star);
172 
173  return TRUE;
174 }
175 
176 #define CRASH_TITLE PRODUCT " Unhandled Exception"
177 
178 // be careful to avoid using any non-trivial C runtime functions here!
179 // C runtime structures may be already corrupted and unusable at this point.
180 LONG WINAPI Sys_ExceptionFilter(LPEXCEPTION_POINTERS exceptionInfo)
181 {
182  STACKFRAME64 stackFrame;
183  PEXCEPTION_RECORD exception;
184  PCONTEXT context;
185  DWORD64 pc;
186  SYMBOL_INFO *symbol;
187  int count, ret, i;
188  DWORD64 offset;
189  BYTE buffer[sizeof(SYMBOL_INFO) + 256 - 1];
190  IMAGEHLP_MODULE64 moduleInfo;
191  char path[MAX_PATH];
192  char execdir[MAX_PATH];
193  HMODULE moduleHandle;
194  SYSTEMTIME systemTime;
195  OSVERSIONINFO vinfo;
196  DWORD len;
197  LONG action;
198 
199  // give previous filter a chance to handle this exception
200  if (prevExceptionFilter) {
201  action = prevExceptionFilter(exceptionInfo);
202  if (action != EXCEPTION_CONTINUE_SEARCH) {
203  return action;
204  }
205  }
206 
207  // debugger present? not our business
208  if (IsDebuggerPresent()) {
209  return EXCEPTION_CONTINUE_SEARCH;
210  }
211 
212  // called from different thread? not our business
213  if (GetCurrentThread() != mainProcessThread) {
214  return EXCEPTION_CONTINUE_SEARCH;
215  }
216 
217 #if USE_CLIENT
218  //Win_Shutdown();
219  VID_Shutdown();
220 #endif
221 
222  ret = MessageBox(NULL,
223  PRODUCT " has encountered an unhandled "
224  "exception and needs to be terminated.\n"
225  "Would you like to generate a crash report?",
226  CRASH_TITLE,
227  MB_ICONERROR | MB_YESNO
228 #if !USE_CLIENT
229  | MB_SERVICE_NOTIFICATION
230 #endif
231  );
232  if (ret == IDNO) {
233  return EXCEPTION_EXECUTE_HANDLER;
234  }
235 
236 #define LL(x) \
237  do { \
238  moduleHandle = LoadLibrary(x); \
239  if (!moduleHandle) { \
240  return EXCEPTION_CONTINUE_SEARCH; \
241  } \
242  } while(0)
243 
244 #define GPA(x, y) \
245  do { \
246  p##y = (x)GetProcAddress(moduleHandle, #y); \
247  if (!p##y) { \
248  return EXCEPTION_CONTINUE_SEARCH; \
249  } \
250  } while(0)
251 
252  LL("dbghelp.dll");
253  GPA(SETSYMOPTIONS, SymSetOptions);
254  GPA(SYMGETMODULEINFO64, SymGetModuleInfo64);
255  GPA(SYMCLEANUP, SymCleanup);
256  GPA(SYMINITIALIZE, SymInitialize);
257  GPA(ENUMERATELOADEDMODULES64, EnumerateLoadedModules64);
258  GPA(STACKWALK64, StackWalk64);
259  GPA(SYMFROMADDR, SymFromAddr);
260  GPA(SYMFUNCTIONTABLEACCESS64, SymFunctionTableAccess64);
261  GPA(SYMGETMODULEBASE64, SymGetModuleBase64);
262 
263  LL("version.dll");
264  GPA(GETFILEVERSIONINFOA, GetFileVersionInfoA);
265  GPA(VERQUERYVALUEA, VerQueryValueA);
266 
267  LL("shell32.dll");
268  GPA(SHELLEXECUTEA, ShellExecuteA);
269 
270  // get base directory to save crash dump to
271  len = GetModuleFileName(NULL, execdir, sizeof(execdir));
272  if (!len || len >= sizeof(execdir)) {
273  return EXCEPTION_CONTINUE_SEARCH;
274  }
275 
276  while (--len) {
277  if (execdir[len] == '\\') {
278  break;
279  }
280  }
281 
282  if (!len || len + 24 >= MAX_PATH) {
283  return EXCEPTION_CONTINUE_SEARCH;
284  }
285 
286  execdir[len] = 0;
287 
288  CopyMemory(path, execdir, len);
289  CopyMemory(path + len, "\\Q2RTX_CrashReportXX.txt", 25);
290  for (i = 0; i < 100; i++) {
291  path[len + 18] = '0' + i / 10;
292  path[len + 19] = '0' + i % 10;
293  crashReport = CreateFile(
294  path,
295  GENERIC_WRITE,
296  FILE_SHARE_READ,
297  NULL,
298  CREATE_NEW,
299  FILE_ATTRIBUTE_NORMAL,
300  NULL);
301 
302  if (crashReport != INVALID_HANDLE_VALUE) {
303  break;
304  }
305 
306  if (GetLastError() != ERROR_FILE_EXISTS) {
307  MessageBox(NULL,
308  "Couldn't create crash report. "
309  "Base directory is not writable.",
310  CRASH_TITLE,
311  MB_ICONERROR);
312  return EXCEPTION_EXECUTE_HANDLER;
313  }
314  }
315 
316  if (i == 100) {
317  MessageBox(NULL,
318  "Couldn't create crash report. "
319  "All report slots are full.\n"
320  "Please remove existing reports from base directory.",
321  CRASH_TITLE,
322  MB_ICONERROR);
323  return EXCEPTION_EXECUTE_HANDLER;
324  }
325 
327  SYMOPT_LOAD_ANYTHING |
328  SYMOPT_DEBUG |
329  SYMOPT_FAIL_CRITICAL_ERRORS);
330 
331  processHandle = GetCurrentProcess();
332  threadHandle = GetCurrentThread();
333 
334  pSymInitialize(processHandle, execdir, TRUE);
335 
336  GetSystemTime(&systemTime);
337  write_report(
338  "Crash report generated %s %u %u, %02u:%02u:%02u UTC\r\n",
339  monthNames[(systemTime.wMonth - 1) % 12],
340  systemTime.wDay,
341  systemTime.wYear,
342  systemTime.wHour,
343  systemTime.wMinute,
344  systemTime.wSecond);
345  write_report(
346  "by " APPLICATION " " VERSION_STRING
347  ", built " __DATE__", " __TIME__ "\r\n");
348 
349 #pragma warning(push)
350 #pragma warning(disable: 4996) // warning C4996: 'GetVersionExA': was declared deprecated
351  vinfo.dwOSVersionInfoSize = sizeof(vinfo);
352  if (GetVersionEx(&vinfo)) {
353  write_report(
354  "\r\nWindows version: %u.%u (build %u) %s\r\n",
355  vinfo.dwMajorVersion,
356  vinfo.dwMinorVersion,
357  vinfo.dwBuildNumber,
358  vinfo.szCSDVersion);
359  } else {
360  write_report("GetVersionEx failed with error %#x\r\n",
361  GetLastError());
362  }
363 #pragma warning(pop)
364 
365  // oh no, dbghelp is not backwards and forwards compatible
366  // why in hell is it different from other windows DLLs?
367  for (i = 0; i < 4; i++) {
368  len = tryModuleSizes[i];
369  if (i && len >= sizeof(moduleInfo)) {
370  continue;
371  }
372  moduleInfo.SizeOfStruct = len;
375  (DWORD64)((INT_PTR)hGlobalInstance),
376  &moduleInfo)) {
377  moduleInfoSize = len;
378  if (i) {
379  write_report(
380  "Module info size is %u (not %u)\r\n",
381  len, tryModuleSizes[0]);
382  }
383  break;
384  }
385  }
386 
387  if (i == 4) {
388  // bad luck
389  write_report("SymGetModuleInfo64 is fucked up :(");
390  moduleInfoSize = sizeof(moduleInfo);
391  }
392 
393  CopyMemory(faultyModuleName, "unknown", 8);
394 
395  exception = exceptionInfo->ExceptionRecord;
396  context = exceptionInfo->ContextRecord;
397 
398 #ifdef _WIN64
399  pc = context->Rip;
400 #else
401  pc = (DWORD64)context->Eip;
402 #endif
403 
404  write_report("\r\nLoaded modules:\r\n");
408  &pc
409  );
410  if (!ret) {
411  write_report("EnumerateLoadedModules64 failed with error %#x\r\n",
412  GetLastError());
413  }
414 
415  write_report("\r\nException information:\r\n");
416  write_report("Code: %#08x\r\n", exception->ExceptionCode);
417  write_report("Address: %"PRIxx" (%s)\r\n", WORDxx(pc), faultyModuleName);
418 
419  write_report("\r\nThread context:\r\n");
420 #ifdef _WIN64
421  write_report("RIP: %"PRIxx64" RBP: %"PRIxx64" RSP: %"PRIxx64"\r\n",
422  context->Rip, context->Rbp, context->Rsp);
423  write_report("RAX: %"PRIxx64" RBX: %"PRIxx64" RCX: %"PRIxx64"\r\n",
424  context->Rax, context->Rbx, context->Rcx);
425  write_report("RDX: %"PRIxx64" RSI: %"PRIxx64" RDI: %"PRIxx64"\r\n",
426  context->Rdx, context->Rsi, context->Rdi);
427  write_report("R8 : %"PRIxx64" R9 : %"PRIxx64" R10: %"PRIxx64"\r\n",
428  context->R8, context->R9, context->R10);
429  write_report("R11: %"PRIxx64" R12: %"PRIxx64" R13: %"PRIxx64"\r\n",
430  context->R11, context->R12, context->R13);
431  write_report("R14: %"PRIxx64" R15: %"PRIxx64"\r\n",
432  context->R14, context->R15);
433 #else
434  write_report("EIP: %"PRIxx32" EBP: %"PRIxx32" ESP: %"PRIxx32"\r\n",
435  context->Eip, context->Ebp, context->Esp);
436  write_report("EAX: %"PRIxx32" EBX: %"PRIxx32" ECX: %"PRIxx32"\r\n",
437  context->Eax, context->Ebx, context->Ecx);
438  write_report("EDX: %"PRIxx32" ESI: %"PRIxx32" EDI: %"PRIxx32"\r\n",
439  context->Edx, context->Esi, context->Edi);
440 #endif
441 
442  ZeroMemory(&stackFrame, sizeof(stackFrame));
443 #ifdef _WIN64
444  stackFrame.AddrPC.Offset = context->Rip;
445  stackFrame.AddrFrame.Offset = context->Rbp;
446  stackFrame.AddrStack.Offset = context->Rsp;
447 #else
448  stackFrame.AddrPC.Offset = context->Eip;
449  stackFrame.AddrFrame.Offset = context->Ebp;
450  stackFrame.AddrStack.Offset = context->Esp;
451 #endif
452  stackFrame.AddrPC.Mode = AddrModeFlat;
453  stackFrame.AddrFrame.Mode = AddrModeFlat;
454  stackFrame.AddrStack.Mode = AddrModeFlat;
455 
456  write_report("\r\nStack trace:\r\n");
457  count = 0;
458  symbol = (SYMBOL_INFO *)buffer;
459  symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
460  symbol->MaxNameLen = 256;
461  while (pStackWalk64(
462 #ifdef _WIN64
463  IMAGE_FILE_MACHINE_AMD64,
464 #else
465  IMAGE_FILE_MACHINE_I386,
466 #endif
468  threadHandle,
469  &stackFrame,
470  context,
471  NULL,
474  NULL)) {
475  write_report(
476  "%d: %"PRIxx" %"PRIxx" %"PRIxx" %"PRIxx" ",
477  count,
478  WORDxx(stackFrame.Params[0]),
479  WORDxx(stackFrame.Params[1]),
480  WORDxx(stackFrame.Params[2]),
481  WORDxx(stackFrame.Params[3]));
482 
483  moduleInfo.SizeOfStruct = moduleInfoSize;
486  stackFrame.AddrPC.Offset,
487  &moduleInfo)) {
488  if (moduleInfo.SymType != SymNone &&
489  moduleInfo.SymType != SymExport &&
490  pSymFromAddr(
492  stackFrame.AddrPC.Offset,
493  &offset,
494  symbol)) {
495  write_report("%s!%s+%"PRIxx32"\r\n",
496  moduleInfo.ModuleName,
497  symbol->Name, (DWORD32)offset);
498  } else {
499  write_report("%s!%"PRIxx"\r\n",
500  moduleInfo.ModuleName,
501  WORDxx(stackFrame.AddrPC.Offset));
502  }
503  } else {
504  write_report("%"PRIxx"\r\n",
505  WORDxx(stackFrame.AddrPC.Offset));
506  }
507 
508  count++;
509  }
510 
511  CloseHandle(crashReport);
512 
514 
515  pShellExecuteA(NULL, "open", path, NULL, execdir, SW_SHOW);
516 
517  return EXCEPTION_EXECUTE_HANDLER;
518 }
519 
pEnumerateLoadedModules64
STATIC ENUMERATELOADEDMODULES64 pEnumerateLoadedModules64
Definition: debug.c:48
pSymGetModuleBase64
STATIC SYMGETMODULEBASE64 pSymGetModuleBase64
Definition: debug.c:52
SYMFUNCTIONTABLEACCESS64
PVOID(WINAPI * SYMFUNCTIONTABLEACCESS64)(HANDLE, DWORD64)
Definition: debug.c:37
SYMFROMADDR
BOOL(WINAPI * SYMFROMADDR)(HANDLE, DWORD64, PDWORD64, PSYMBOL_INFO)
Definition: debug.c:36
pShellExecuteA
STATIC SHELLEXECUTEA pShellExecuteA
Definition: debug.c:55
MI_SIZE_V3
#define MI_SIZE_V3
Definition: debug.c:64
SYMCLEANUP
BOOL(WINAPI * SYMCLEANUP)(HANDLE)
Definition: debug.c:30
MI_SIZE_V2
#define MI_SIZE_V2
Definition: debug.c:63
pSymGetModuleInfo64
STATIC SYMGETMODULEINFO64 pSymGetModuleInfo64
Definition: debug.c:45
LL
#define LL(x)
Sys_ExceptionFilter
LONG WINAPI Sys_ExceptionFilter(LPEXCEPTION_POINTERS exceptionInfo)
Definition: debug.c:180
moduleInfoSize
STATIC DWORD moduleInfoSize
Definition: debug.c:60
pSymFromAddr
STATIC SYMFROMADDR pSymFromAddr
Definition: debug.c:50
hGlobalInstance
HINSTANCE hGlobalInstance
Definition: system.c:28
STATIC
#define STATIC
Definition: client.h:41
faultyModuleName
STATIC CHAR faultyModuleName[MAX_PATH]
Definition: debug.c:59
BOOL
BOOL(WINAPI *qwglSetPixelFormat)(HDC
pStackWalk64
STATIC STACKWALK64 pStackWalk64
Definition: debug.c:49
pGetFileVersionInfoA
STATIC GETFILEVERSIONINFOA pGetFileVersionInfoA
Definition: debug.c:53
processHandle
STATIC HANDLE processHandle
Definition: debug.c:57
pSymSetOptions
STATIC SETSYMOPTIONS pSymSetOptions
Definition: debug.c:44
CRASH_TITLE
#define CRASH_TITLE
Definition: debug.c:176
tryModuleSizes
STATIC CONST DWORD tryModuleSizes[4]
Definition: debug.c:67
enum_modules_callback
STATIC BOOL CALLBACK enum_modules_callback(PCSTR ModuleName, DWORD64 ModuleBase, ULONG ModuleSize, PVOID UserContext)
Definition: debug.c:105
client.h
pSymInitialize
STATIC SYMINITIALIZE pSymInitialize
Definition: debug.c:46
ENUMERATELOADEDMODULES64
BOOL(WINAPI * ENUMERATELOADEDMODULES64)(HANDLE, PENUMLOADED_MODULES_CALLBACK64, PVOID)
Definition: debug.c:31
PRIxx64
#define PRIxx64
Definition: debug.c:76
VID_Shutdown
void VID_Shutdown(void)
Definition: glimp.c:54
pVerQueryValueA
STATIC VERQUERYVALUEA pVerQueryValueA
Definition: debug.c:54
SYMGETMODULEINFO64
BOOL(WINAPI * SYMGETMODULEINFO64)(HANDLE, DWORD64, PIMAGEHLP_MODULE64)
Definition: debug.c:27
UINT
CONST PIXELFORMATDESCRIPTOR UINT
Definition: wgl.c:26
GETFILEVERSIONINFOA
BOOL(WINAPI * GETFILEVERSIONINFOA)(LPCSTR, DWORD, DWORD, PVOID)
Definition: debug.c:39
GPA
#define GPA(x, y)
crashReport
STATIC HANDLE crashReport
Definition: debug.c:58
WORDxx
#define WORDxx(x)
Definition: debug.c:85
PRIxx
#define PRIxx
Definition: debug.c:84
context
static ALCcontext * context
Definition: dynamic.c:54
SETSYMOPTIONS
DWORD(WINAPI * SETSYMOPTIONS)(DWORD)
Definition: debug.c:26
SYMINITIALIZE
BOOL(WINAPI * SYMINITIALIZE)(HANDLE, PSTR, BOOL)
Definition: debug.c:29
threadHandle
STATIC HANDLE threadHandle
Definition: debug.c:57
STACKWALK64
BOOL(WINAPI * STACKWALK64)(DWORD, HANDLE, HANDLE, LPSTACKFRAME64, PVOID, PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64, PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64)
Definition: debug.c:33
monthNames
static const char monthNames[12][4]
Definition: debug.c:71
PRIxx32
#define PRIxx32
Definition: debug.c:77
SHELLEXECUTEA
HINSTANCE(WINAPI * SHELLEXECUTEA)(HWND, LPCSTR, LPCSTR, LPCSTR, LPCSTR, INT)
Definition: debug.c:41
pSymCleanup
STATIC SYMCLEANUP pSymCleanup
Definition: debug.c:47
VERQUERYVALUEA
BOOL(WINAPI * VERQUERYVALUEA)(const LPVOID, LPSTR, LPVOID *, PUINT)
Definition: debug.c:40
SYMGETMODULEBASE64
DWORD64(WINAPI * SYMGETMODULEBASE64)(HANDLE, DWORD64)
Definition: debug.c:38
MI_SIZE_V1
#define MI_SIZE_V1
Definition: debug.c:62
write_report
STATIC VOID write_report(LPCTSTR fmt,...)
Definition: debug.c:89
pSymFunctionTableAccess64
STATIC SYMFUNCTIONTABLEACCESS64 pSymFunctionTableAccess64
Definition: debug.c:51