StackWalker.h
<br />
<br />
#pragma once<br />
<br />
#ifndef IMP_EXP_EH<br />
#ifdef STACK_WALKER_DLL_ENABLE<br />
#ifdef STACK_WALKER_EXPORT<br />
#define IMP_EXP_EH _declspec(dllexport)<br />
#else<br />
#define IMP_EXP_EH _declspec(dllimport)<br />
#endif<br />
#else<br />
#define IMP_EXP_EH<br />
#endif<br />
#endif<br />
<br />
#include <windows.h><br />
#include <iostream><br />
#include <string><br />
<br />
typedef unsigned int u32;<br />
typedef std::ostream ST_OSTREAMA;<br />
typedef std::wostream ST_OSTREAMW;<br />
<br />
#if _MSC_VER < 1300<br />
typedef unsigned __int64 DWORD64, *PDWORD64;<br />
#if defined(_WIN64)<br />
typedef unsigned __int64 SIZE_T, *PSIZE_T;<br />
#else<br />
typedef unsigned long SIZE_T, *PSIZE_T;<br />
#endif<br />
#endif // _MSC_VER < 1300<br />
<br />
class StackWalkerInternal;<br />
<br />
class IMP_EXP_EH StackWalker<br />
{<br />
public:<br />
typedef enum StackWalkOptions<br />
{<br />
RetrieveNone = 0,<br />
<br />
RetrieveSymbol = 1,<br />
<br />
RetrieveLine = 2,<br />
<br />
RetrieveModuleInfo = 4,<br />
<br />
RetrieveFileVersion = 8,<br />
<br />
RetrieveVerbose = 0xF,<br />
<br />
SymBuildPath = 0x10,<br />
<br />
SymUseSymSrv = 0x20,<br />
<br />
SymAll = 0x30,<br />
<br />
OptionsAll = RetrieveVerbose | SymBuildPath<br />
} StackWalkOptions;<br />
<br />
StackWalker(<br />
int options = OptionsAll,
LPCSTR szSymPath = NULL, <br />
DWORD dwProcessId = GetCurrentProcessId(), <br />
HANDLE hProcess = GetCurrentProcess()<br />
);<br />
StackWalker(DWORD dwProcessId, HANDLE hProcess);<br />
virtual ~StackWalker();<br />
<br />
typedef BOOL (__stdcall *PReadProcessMemoryRoutine)(<br />
HANDLE hProcess,<br />
DWORD64 qwBaseAddress,<br />
PVOID lpBuffer,<br />
DWORD nSize,<br />
LPDWORD lpNumberOfBytesRead,<br />
LPVOID pUserData
);<br />
<br />
BOOL LoadModules();<br />
<br />
<br />
void OstreamRegister( ST_OSTREAMA* pos );<br />
void OstreamRegister( ST_OSTREAMW* pwos );<br />
<br />
BOOL ShowCallstack(<br />
const CONTEXT *context = NULL, <br />
HANDLE hThread = GetCurrentThread(), <br />
PReadProcessMemoryRoutine readMemoryFunction = NULL,<br />
LPVOID pUserData = NULL
);<br />
<br />
#if _MSC_VER >= 1300<br />
protected:<br />
#endif<br />
enum { STACKWALK_MAX_NAMELEN = 1024 };
<br />
protected:<br />
typedef struct CallstackEntry<br />
{<br />
DWORD64 offset;
CHAR name[STACKWALK_MAX_NAMELEN];<br />
CHAR undName[STACKWALK_MAX_NAMELEN];<br />
CHAR undFullName[STACKWALK_MAX_NAMELEN];<br />
DWORD64 offsetFromSmybol;<br />
DWORD offsetFromLine;<br />
DWORD lineNumber;<br />
CHAR lineFileName[STACKWALK_MAX_NAMELEN];<br />
DWORD symType;<br />
LPCSTR symTypeString;<br />
CHAR moduleName[STACKWALK_MAX_NAMELEN];<br />
DWORD64 baseOfImage;<br />
CHAR loadedImageName[STACKWALK_MAX_NAMELEN];<br />
} CallstackEntry;<br />
<br />
typedef enum CallstackEntryType {firstEntry, nextEntry, lastEntry};<br />
<br />
virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName);<br />
virtual void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion);<br />
virtual void OnCallstackEntry(CallstackEntryType eType, CallstackEntry &entry);<br />
virtual void OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr);<br />
virtual void OnOutput(LPCSTR szTextA);<br />
virtual void OnOutput(LPCWSTR szTextW);<br />
<br />
StackWalkerInternal *m_sw;<br />
HANDLE m_hProcess;<br />
DWORD m_dwProcessId;<br />
BOOL m_modulesLoaded;<br />
LPSTR m_szSymPath;<br />
ST_OSTREAMA* m_pos;
ST_OSTREAMW* m_pwos;
BOOL m_useUnicode;<br />
<br />
int m_options;<br />
<br />
static BOOL __stdcall myReadProcMem(HANDLE hProcess, DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead);<br />
<br />
friend StackWalkerInternal;<br />
};<br />
<br />
<br />
<br />
<br />
#if defined(_M_IX86)<br />
#ifdef CURRENT_THREAD_VIA_EXCEPTION<br />
#define GET_CURRENT_CONTEXT(c, contextFlags) \<br />
do { \<br />
memset(&c, 0, sizeof(CONTEXT)); \<br />
EXCEPTION_POINTERS *pExp = NULL; \<br />
__try { \<br />
throw 0; \<br />
} __except( ( (pExp = GetExceptionInformation()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_EXECUTE_HANDLER)) {} \<br />
if (pExp != NULL) \<br />
memcpy(&c, pExp->ContextRecord, sizeof(CONTEXT)); \<br />
c.ContextFlags = contextFlags; \<br />
} while(0);<br />
#else<br />
#define GET_CURRENT_CONTEXT(c, contextFlags) \<br />
do { \<br />
memset(&c, 0, sizeof(CONTEXT)); \<br />
c.ContextFlags = contextFlags; \<br />
__asm call x \<br />
__asm x: pop eax \<br />
__asm mov c.Eip, eax \<br />
__asm mov c.Ebp, ebp \<br />
__asm mov c.Esp, esp \<br />
} while(0);<br />
#endif<br />
<br />
#else<br />
<br />
#define GET_CURRENT_CONTEXT(c, contextFlags) \<br />
do { \<br />
memset(&c, 0, sizeof(CONTEXT)); \<br />
c.ContextFlags = contextFlags; \<br />
RtlCaptureContext(&c); \<br />
} while(0);<br />
#endif<br />
StackWalker.cpp
<br />
<br />
#include <windows.h><br />
#include <tchar.h><br />
#include <stdio.h><br />
#pragma comment(lib, "version.lib") // for "VerQueryValue"<br />
<br />
#define STACK_WALKER_EXPORT // This makes header export biased<br />
#include "StackWalker.h"<br />
<br />
<br />
#if _MSC_VER >= 1300<br />
#include <dbghelp.h><br />
#else<br />
typedef enum {<br />
SymNone = 0,<br />
SymCoff,<br />
SymCv,<br />
SymPdb,<br />
SymExport,<br />
SymDeferred,<br />
SymSym,<br />
SymDia,<br />
SymVirtual,<br />
NumSymTypes<br />
} SYM_TYPE;<br />
typedef struct _IMAGEHLP_LINE64 {<br />
DWORD SizeOfStruct;
PVOID Key;
DWORD LineNumber;
PCHAR FileName;
DWORD64 Address;
} IMAGEHLP_LINE64, *PIMAGEHLP_LINE64;<br />
typedef struct _IMAGEHLP_MODULE64 {<br />
DWORD SizeOfStruct;
DWORD64 BaseOfImage;
DWORD ImageSize;
DWORD TimeDateStamp;
DWORD CheckSum;
DWORD NumSyms;
SYM_TYPE SymType;
CHAR ModuleName[32];
CHAR ImageName[256];
CHAR LoadedImageName[256];
} IMAGEHLP_MODULE64, *PIMAGEHLP_MODULE64;<br />
typedef struct _IMAGEHLP_SYMBOL64 {<br />
DWORD SizeOfStruct;
DWORD64 Address;
DWORD Size;
DWORD Flags;
DWORD MaxNameLength;
CHAR Name[1];
} IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64;<br />
typedef enum {<br />
AddrMode1616,<br />
AddrMode1632,<br />
AddrModeReal,<br />
AddrModeFlat<br />
} ADDRESS_MODE;<br />
typedef struct _tagADDRESS64 {<br />
DWORD64 Offset;<br />
WORD Segment;<br />
ADDRESS_MODE Mode;<br />
} ADDRESS64, *LPADDRESS64;<br />
typedef struct _KDHELP64 {<br />
DWORD64 Thread;<br />
DWORD ThCallbackStack;<br />
DWORD ThCallbackBStore;<br />
DWORD NextCallback;<br />
DWORD FramePointer;<br />
DWORD64 KiCallUserMode;<br />
DWORD64 KeUserCallbackDispatcher;<br />
DWORD64 SystemRangeStart;<br />
DWORD64 Reserved[8];<br />
} KDHELP64, *PKDHELP64;<br />
typedef struct _tagSTACKFRAME64 {<br />
ADDRESS64 AddrPC;
ADDRESS64 AddrReturn;
ADDRESS64 AddrFrame;
ADDRESS64 AddrStack;
ADDRESS64 AddrBStore;
PVOID FuncTableEntry;
DWORD64 Params[4];
BOOL Far;
BOOL Virtual;
DWORD64 Reserved[3];<br />
KDHELP64 KdHelp;<br />
} STACKFRAME64, *LPSTACKFRAME64;<br />
typedef<br />
BOOL<br />
(__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)(<br />
HANDLE hProcess,<br />
DWORD64 qwBaseAddress,<br />
PVOID lpBuffer,<br />
DWORD nSize,<br />
LPDWORD lpNumberOfBytesRead<br />
);<br />
typedef<br />
PVOID<br />
(__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)(<br />
HANDLE hProcess,<br />
DWORD64 AddrBase<br />
);<br />
typedef<br />
DWORD64<br />
(__stdcall *PGET_MODULE_BASE_ROUTINE64)(<br />
HANDLE hProcess,<br />
DWORD64 Address<br />
);<br />
typedef<br />
DWORD64<br />
(__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(<br />
HANDLE hProcess,<br />
HANDLE hThread,<br />
LPADDRESS64 lpaddr<br />
);<br />
#define SYMOPT_CASE_INSENSITIVE 0x00000001<br />
#define SYMOPT_UNDNAME 0x00000002<br />
#define SYMOPT_DEFERRED_LOADS 0x00000004<br />
#define SYMOPT_NO_CPP 0x00000008<br />
#define SYMOPT_LOAD_LINES 0x00000010<br />
#define SYMOPT_OMAP_FIND_NEAREST 0x00000020<br />
#define SYMOPT_LOAD_ANYTHING 0x00000040<br />
#define SYMOPT_IGNORE_CVREC 0x00000080<br />
#define SYMOPT_NO_UNQUALIFIED_LOADS 0x00000100<br />
#define SYMOPT_FAIL_CRITICAL_ERRORS 0x00000200<br />
#define SYMOPT_EXACT_SYMBOLS 0x00000400<br />
#define SYMOPT_ALLOW_ABSOLUTE_SYMBOLS 0x00000800<br />
#define SYMOPT_IGNORE_NT_SYMPATH 0x00001000<br />
#define SYMOPT_INCLUDE_32BIT_MODULES 0x00002000<br />
#define SYMOPT_PUBLICS_ONLY 0x00004000<br />
#define SYMOPT_NO_PUBLICS 0x00008000<br />
#define SYMOPT_AUTO_PUBLICS 0x00010000<br />
#define SYMOPT_NO_IMAGE_SEARCH 0x00020000<br />
#define SYMOPT_SECURE 0x00040000<br />
#define SYMOPT_DEBUG 0x80000000<br />
#define UNDNAME_COMPLETE (0x0000) // Enable full undecoration<br />
#define UNDNAME_NAME_ONLY (0x1000) // Crack only the name for primary declaration;<br />
#endif // _MSC_VER < 1300<br />
<br />
#ifndef INVALID_FILE_ATTRIBUTES<br />
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)<br />
#endif <br />
<br />
<br />
#if _MSC_VER < 1400<br />
#define strcpy_s strcpy<br />
#define strcat_s(dst, len, src) strcat(dst, src)<br />
#define _snprintf_s _snprintf<br />
#define _tcscat_s _tcscat<br />
#endif<br />
<br />
#define USED_CONTEXT_FLAGS CONTEXT_FULL<br />
<br />
<br />
class StackWalkerInternal<br />
{<br />
public:<br />
StackWalkerInternal(StackWalker *parent, HANDLE hProcess)<br />
{<br />
m_parent = parent;<br />
m_hDbhHelp = NULL;<br />
pSC = NULL;<br />
m_hProcess = hProcess;<br />
m_szSymPath = NULL;<br />
pSFTA = NULL;<br />
pSGLFA = NULL;<br />
pSGMB = NULL;<br />
pSGMI = NULL;<br />
pSGO = NULL;<br />
pSGSFA = NULL;<br />
pSI = NULL;<br />
pSLM = NULL;<br />
pSSO = NULL;<br />
pSW = NULL;<br />
pUDSN = NULL;<br />
pSGSP = NULL;<br />
}<br />
~StackWalkerInternal()<br />
{<br />
if (pSC != NULL)<br />
pSC(m_hProcess);
if (m_hDbhHelp != NULL)<br />
FreeLibrary(m_hDbhHelp);<br />
m_hDbhHelp = NULL;<br />
m_parent = NULL;<br />
if(m_szSymPath != NULL)<br />
free(m_szSymPath);<br />
m_szSymPath = NULL;<br />
}<br />
BOOL Init(LPCSTR szSymPath)<br />
{<br />
if (m_parent == NULL)<br />
return FALSE;<br />
TCHAR szTemp[4096];<br />
if (GetModuleFileName(NULL, szTemp, 4096) > 0)<br />
{<br />
_tcscat_s(szTemp, _T(".local"));<br />
if (GetFileAttributes(szTemp) == INVALID_FILE_ATTRIBUTES)<br />
{<br />
if (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, 4096) > 0)<br />
{<br />
_tcscat_s(szTemp, _T("\\Debugging Tools for Windows\\dbghelp.dll"));<br />
if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES)<br />
{<br />
m_hDbhHelp = LoadLibrary(szTemp);<br />
}<br />
}<br />
if ( (m_hDbhHelp == NULL) && (GetEnvironmentVariable(_T("ProgramFiles"), szTemp, 4096) > 0) )<br />
{<br />
_tcscat_s(szTemp, _T("\\Debugging Tools for Windows 64-Bit\\dbghelp.dll"));<br />
if (GetFileAttributes(szTemp) != INVALID_FILE_ATTRIBUTES)<br />
{<br />
m_hDbhHelp = LoadLibrary(szTemp);<br />
}<br />
}<br />
}<br />
}<br />
if (m_hDbhHelp == NULL)
m_hDbhHelp = LoadLibrary( _T("dbghelp.dll") );<br />
if (m_hDbhHelp == NULL)<br />
return FALSE;<br />
pSI = (tSI) GetProcAddress(m_hDbhHelp, "SymInitialize" );<br />
pSC = (tSC) GetProcAddress(m_hDbhHelp, "SymCleanup" );<br />
<br />
pSW = (tSW) GetProcAddress(m_hDbhHelp, "StackWalk64" );<br />
pSGO = (tSGO) GetProcAddress(m_hDbhHelp, "SymGetOptions" );<br />
pSSO = (tSSO) GetProcAddress(m_hDbhHelp, "SymSetOptions" );<br />
<br />
pSFTA = (tSFTA) GetProcAddress(m_hDbhHelp, "SymFunctionTableAccess64" );<br />
pSGLFA = (tSGLFA) GetProcAddress(m_hDbhHelp, "SymGetLineFromAddr64" );<br />
pSGMB = (tSGMB) GetProcAddress(m_hDbhHelp, "SymGetModuleBase64" );<br />
pSGMI = (tSGMI) GetProcAddress(m_hDbhHelp, "SymGetModuleInfo64" );<br />
pSGSFA = (tSGSFA) GetProcAddress(m_hDbhHelp, "SymGetSymFromAddr64" );<br />
pUDSN = (tUDSN) GetProcAddress(m_hDbhHelp, "UnDecorateSymbolName" );<br />
pSLM = (tSLM) GetProcAddress(m_hDbhHelp, "SymLoadModule64" );<br />
pSGSP =(tSGSP) GetProcAddress(m_hDbhHelp, "SymGetSearchPath" );<br />
<br />
if ( pSC == NULL || pSFTA == NULL || pSGMB == NULL || pSGMI == NULL ||<br />
pSGO == NULL || pSGSFA == NULL || pSI == NULL || pSSO == NULL ||<br />
pSW == NULL || pUDSN == NULL || pSLM == NULL )<br />
{<br />
FreeLibrary(m_hDbhHelp);<br />
m_hDbhHelp = NULL;<br />
pSC = NULL;<br />
return FALSE;<br />
}<br />
<br />
if (szSymPath != NULL)<br />
m_szSymPath = _strdup(szSymPath);<br />
if (this->pSI(m_hProcess, m_szSymPath, FALSE) == FALSE)<br />
this->m_parent->OnDbgHelpErr("SymInitialize", GetLastError(), 0);<br />
<br />
DWORD symOptions = this->pSGO();
symOptions |= SYMOPT_FAIL_CRITICAL_ERRORS | SYMOPT_LOAD_ANYTHING | SYMOPT_LOAD_LINES;<br />
symOptions = this->pSSO(symOptions);<br />
<br />
char buf[StackWalker::STACKWALK_MAX_NAMELEN] = {0};<br />
if (this->pSGSP != NULL)<br />
{<br />
if (this->pSGSP(m_hProcess, buf, StackWalker::STACKWALK_MAX_NAMELEN) == FALSE)<br />
this->m_parent->OnDbgHelpErr("SymGetSearchPath", GetLastError(), 0);<br />
}<br />
char szUserName[1024] = {0};<br />
DWORD dwSize = 1024;<br />
GetUserNameA(szUserName, &dwSize);<br />
this->m_parent->OnSymInit(buf, symOptions, szUserName);<br />
<br />
return TRUE;<br />
}<br />
<br />
StackWalker *m_parent;<br />
<br />
HMODULE m_hDbhHelp;<br />
HANDLE m_hProcess;<br />
LPSTR m_szSymPath;<br />
<br />
<br />
typedef struct IMAGEHLP_MODULE64_V2 {<br />
DWORD SizeOfStruct;
DWORD64 BaseOfImage;
DWORD ImageSize;
DWORD TimeDateStamp;
DWORD CheckSum;
DWORD NumSyms;
SYM_TYPE SymType;
CHAR ModuleName[32];
CHAR ImageName[256];
CHAR LoadedImageName[256];
};<br />
<br />
<br />
typedef BOOL (__stdcall *tSC)( IN HANDLE hProcess );<br />
tSC pSC;<br />
<br />
typedef PVOID (__stdcall *tSFTA)( HANDLE hProcess, DWORD64 AddrBase );<br />
tSFTA pSFTA;<br />
<br />
typedef BOOL (__stdcall *tSGLFA)( IN HANDLE hProcess, IN DWORD64 dwAddr,<br />
OUT PDWORD pdwDisplacement, OUT PIMAGEHLP_LINE64 Line );<br />
tSGLFA pSGLFA;<br />
<br />
typedef DWORD64 (__stdcall *tSGMB)( IN HANDLE hProcess, IN DWORD64 dwAddr );<br />
tSGMB pSGMB;<br />
<br />
typedef BOOL (__stdcall *tSGMI)( IN HANDLE hProcess, IN DWORD64 dwAddr, OUT IMAGEHLP_MODULE64_V2 *ModuleInfo );<br />
tSGMI pSGMI;<br />
<br />
<br />
typedef DWORD (__stdcall *tSGO)( VOID );<br />
tSGO pSGO;<br />
<br />
typedef BOOL (__stdcall *tSGSFA)( IN HANDLE hProcess, IN DWORD64 dwAddr,<br />
OUT PDWORD64 pdwDisplacement, OUT PIMAGEHLP_SYMBOL64 Symbol );<br />
tSGSFA pSGSFA;<br />
<br />
typedef BOOL (__stdcall *tSI)( IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess );<br />
tSI pSI;<br />
<br />
typedef DWORD64 (__stdcall *tSLM)( IN HANDLE hProcess, IN HANDLE hFile,<br />
IN PSTR ImageName, IN PSTR ModuleName, IN DWORD64 BaseOfDll, IN DWORD SizeOfDll );<br />
tSLM pSLM;<br />
<br />
typedef DWORD (__stdcall *tSSO)( IN DWORD SymOptions );<br />
tSSO pSSO;<br />
<br />
typedef BOOL (__stdcall *tSW)( <br />
DWORD MachineType, <br />
HANDLE hProcess,<br />
HANDLE hThread, <br />
LPSTACKFRAME64 StackFrame, <br />
PVOID ContextRecord,<br />
PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,<br />
PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,<br />
PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,<br />
PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress );<br />
tSW pSW;<br />
<br />
typedef DWORD (__stdcall WINAPI *tUDSN)( PCSTR DecoratedName, PSTR UnDecoratedName,<br />
DWORD UndecoratedLength, DWORD Flags );<br />
tUDSN pUDSN;<br />
<br />
typedef BOOL (__stdcall WINAPI *tSGSP)(HANDLE hProcess, PSTR SearchPath, DWORD SearchPathLength);<br />
tSGSP pSGSP;<br />
<br />
<br />
private:<br />
#define MAX_MODULE_NAME32 255<br />
#define TH32CS_SNAPMODULE 0x00000008<br />
#pragma pack( push, 8 )<br />
typedef struct tagMODULEENTRY32<br />
{<br />
DWORD dwSize;<br />
DWORD th32ModuleID;
DWORD th32ProcessID;
DWORD GlblcntUsage;
DWORD ProccntUsage;
BYTE * modBaseAddr;
DWORD modBaseSize;
HMODULE hModule;
char szModule[MAX_MODULE_NAME32 + 1];<br />
char szExePath[MAX_PATH];<br />
} MODULEENTRY32;<br />
typedef MODULEENTRY32 * PMODULEENTRY32;<br />
typedef MODULEENTRY32 * LPMODULEENTRY32;<br />
#pragma pack( pop )<br />
<br />
BOOL GetModuleListTH32(HANDLE hProcess, DWORD pid)<br />
{<br />
typedef HANDLE (__stdcall *tCT32S)(DWORD dwFlags, DWORD th32ProcessID);<br />
typedef BOOL (__stdcall *tM32F)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);<br />
typedef BOOL (__stdcall *tM32N)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);<br />
<br />
const TCHAR *dllname[] = { _T("kernel32.dll"), _T("tlhelp32.dll") };<br />
HINSTANCE hToolhelp = NULL;<br />
tCT32S pCT32S = NULL;<br />
tM32F pM32F = NULL;<br />
tM32N pM32N = NULL;<br />
<br />
HANDLE hSnap;<br />
MODULEENTRY32 me;<br />
me.dwSize = sizeof(me);<br />
BOOL keepGoing;<br />
size_t i;<br />
<br />
for (i = 0; i<(sizeof(dllname) / sizeof(dllname[0])); i++ )<br />
{<br />
hToolhelp = LoadLibrary( dllname[i] );<br />
if (hToolhelp == NULL)<br />
continue;<br />
pCT32S = (tCT32S) GetProcAddress(hToolhelp, "CreateToolhelp32Snapshot");<br />
pM32F = (tM32F) GetProcAddress(hToolhelp, "Module32First");<br />
pM32N = (tM32N) GetProcAddress(hToolhelp, "Module32Next");<br />
if ( (pCT32S != NULL) && (pM32F != NULL) && (pM32N != NULL) )<br />
break;
FreeLibrary(hToolhelp);<br />
hToolhelp = NULL;<br />
}<br />
<br />
if (hToolhelp == NULL)<br />
return FALSE;<br />
<br />
hSnap = pCT32S( TH32CS_SNAPMODULE, pid );<br />
if (hSnap == (HANDLE) -1)<br />
return FALSE;<br />
<br />
keepGoing = !!pM32F( hSnap, &me );<br />
int cnt = 0;<br />
while (keepGoing)<br />
{<br />
this->LoadModule(hProcess, me.szExePath, me.szModule, (DWORD64) me.modBaseAddr, me.modBaseSize);<br />
cnt++;<br />
keepGoing = !!pM32N( hSnap, &me );<br />
}<br />
CloseHandle(hSnap);<br />
FreeLibrary(hToolhelp);<br />
if (cnt <= 0)<br />
return FALSE;<br />
return TRUE;<br />
}
<br />
typedef struct _MODULEINFO {<br />
LPVOID lpBaseOfDll;<br />
DWORD SizeOfImage;<br />
LPVOID EntryPoint;<br />
} MODULEINFO, *LPMODULEINFO;<br />
<br />
BOOL GetModuleListPSAPI(HANDLE hProcess)<br />
{<br />
typedef BOOL (__stdcall *tEPM)(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded );<br />
typedef DWORD (__stdcall *tGMFNE)(HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize );<br />
typedef DWORD (__stdcall *tGMBN)(HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize );<br />
typedef BOOL (__stdcall *tGMI)(HANDLE hProcess, HMODULE hModule, LPMODULEINFO pmi, DWORD nSize );<br />
<br />
HINSTANCE hPsapi;<br />
tEPM pEPM;<br />
tGMFNE pGMFNE;<br />
tGMBN pGMBN;<br />
tGMI pGMI;<br />
<br />
DWORD i;<br />
DWORD cbNeeded;<br />
MODULEINFO mi;<br />
HMODULE *hMods = 0;<br />
char *tt = NULL;<br />
char *tt2 = NULL;<br />
const SIZE_T TTBUFLEN = 8096;<br />
int cnt = 0;<br />
<br />
hPsapi = LoadLibrary( _T("psapi.dll") );<br />
if (hPsapi == NULL)<br />
return FALSE;<br />
<br />
pEPM = (tEPM) GetProcAddress( hPsapi, "EnumProcessModules" );<br />
pGMFNE = (tGMFNE) GetProcAddress( hPsapi, "GetModuleFileNameExA" );<br />
pGMBN = (tGMFNE) GetProcAddress( hPsapi, "GetModuleBaseNameA" );<br />
pGMI = (tGMI) GetProcAddress( hPsapi, "GetModuleInformation" );<br />
if ( (pEPM == NULL) || (pGMFNE == NULL) || (pGMBN == NULL) || (pGMI == NULL) )<br />
{<br />
FreeLibrary(hPsapi);<br />
return FALSE;<br />
}<br />
<br />
hMods = (HMODULE*) malloc(sizeof(HMODULE) * (TTBUFLEN / sizeof HMODULE));<br />
tt = (char*) malloc(sizeof(char) * TTBUFLEN);<br />
tt2 = (char*) malloc(sizeof(char) * TTBUFLEN);<br />
if ( (hMods == NULL) || (tt == NULL) || (tt2 == NULL) )<br />
goto cleanup;<br />
<br />
if ( ! pEPM( hProcess, hMods, TTBUFLEN, &cbNeeded ) )<br />
{<br />
goto cleanup;<br />
}<br />
<br />
if ( cbNeeded > TTBUFLEN )<br />
{<br />
goto cleanup;<br />
}<br />
<br />
for ( i = 0; i < cbNeeded / sizeof hMods[0]; i++ )<br />
{<br />
pGMI(hProcess, hMods[i], &mi, sizeof mi );<br />
tt[0] = 0;<br />
pGMFNE(hProcess, hMods[i], tt, TTBUFLEN );<br />
tt2[0] = 0;<br />
pGMBN(hProcess, hMods[i], tt2, TTBUFLEN );<br />
<br />
DWORD dwRes = this->LoadModule(hProcess, tt, tt2, (DWORD64) mi.lpBaseOfDll, mi.SizeOfImage);<br />
if (dwRes != ERROR_SUCCESS)<br />
this->m_parent->OnDbgHelpErr("LoadModule", dwRes, 0);<br />
cnt++;<br />
}<br />
<br />
cleanup:<br />
if (hPsapi != NULL) FreeLibrary(hPsapi);<br />
if (tt2 != NULL) free(tt2);<br />
if (tt != NULL) free(tt);<br />
if (hMods != NULL) free(hMods);<br />
<br />
return cnt != 0;<br />
}
<br />
DWORD LoadModule(HANDLE hProcess, LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size)<br />
{<br />
CHAR *szImg = _strdup(img);<br />
CHAR *szMod = _strdup(mod);<br />
DWORD result = ERROR_SUCCESS;<br />
if ( (szImg == NULL) || (szMod == NULL) )<br />
result = ERROR_NOT_ENOUGH_MEMORY;<br />
else<br />
{<br />
if (pSLM(hProcess, 0, szImg, szMod, baseAddr, size) == 0)<br />
result = GetLastError();<br />
}<br />
ULONGLONG fileVersion = 0;<br />
if ( (m_parent != NULL) && (szImg != NULL) )<br />
{<br />
if ( (this->m_parent->m_options & StackWalker::RetrieveFileVersion) != 0)<br />
{<br />
VS_FIXEDFILEINFO *fInfo = NULL;<br />
DWORD dwHandle;<br />
DWORD dwSize = GetFileVersionInfoSizeA(szImg, &dwHandle);<br />
if (dwSize > 0)<br />
{<br />
LPVOID vData = malloc(dwSize);<br />
if (vData != NULL)<br />
{<br />
if (GetFileVersionInfoA(szImg, dwHandle, dwSize, vData) != 0)<br />
{<br />
UINT len;<br />
TCHAR szSubBlock[] = _T("\\");<br />
if (VerQueryValue(vData, szSubBlock, (LPVOID*) &fInfo, &len) == 0)<br />
fInfo = NULL;<br />
else<br />
{<br />
fileVersion = ((ULONGLONG)fInfo->dwFileVersionLS) + ((ULONGLONG)fInfo->dwFileVersionMS << 32);<br />
}<br />
}<br />
free(vData);<br />
}<br />
}<br />
}<br />
<br />
IMAGEHLP_MODULE64_V2 Module;<br />
const char *szSymType = "-unknown-";<br />
if (this->GetModuleInfo(hProcess, baseAddr, &Module) != FALSE)<br />
{<br />
switch(Module.SymType)<br />
{<br />
case SymNone:<br />
szSymType = "-nosymbols-";<br />
break;<br />
case SymCoff:<br />
szSymType = "COFF";<br />
break;<br />
case SymCv:<br />
szSymType = "CV";<br />
break;<br />
case SymPdb:<br />
szSymType = "PDB";<br />
break;<br />
case SymExport:<br />
szSymType = "-exported-";<br />
break;<br />
case SymDeferred:<br />
szSymType = "-deferred-";<br />
break;<br />
case SymSym:<br />
szSymType = "SYM";<br />
break;<br />
case 8:
szSymType = "Virtual";<br />
break;<br />
case 9:
szSymType = "DIA";<br />
break;<br />
}<br />
}<br />
this->m_parent->OnLoadModule(img, mod, baseAddr, size, result, szSymType, Module.LoadedImageName, fileVersion);<br />
}<br />
if (szImg != NULL) free(szImg);<br />
if (szMod != NULL) free(szMod);<br />
return result;<br />
}<br />
public:<br />
BOOL LoadModules(HANDLE hProcess, DWORD dwProcessId)<br />
{<br />
if (GetModuleListTH32(hProcess, dwProcessId))<br />
return true;<br />
return GetModuleListPSAPI(hProcess);<br />
}<br />
<br />
<br />
BOOL GetModuleInfo(HANDLE hProcess, DWORD64 baseAddr, IMAGEHLP_MODULE64_V2 *pModuleInfo)<br />
{<br />
if(this->pSGMI == NULL)<br />
{<br />
SetLastError(ERROR_DLL_INIT_FAILED);<br />
return FALSE;<br />
}<br />
pModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE64_V2);<br />
void *pData = malloc(4096);
if (pData == NULL)<br />
{<br />
SetLastError(ERROR_NOT_ENOUGH_MEMORY);<br />
return FALSE;<br />
}<br />
memcpy(pData, pModuleInfo, sizeof(IMAGEHLP_MODULE64_V2));<br />
if (this->pSGMI(hProcess, baseAddr, (IMAGEHLP_MODULE64_V2*) pData)) {<br />
memcpy(pModuleInfo, pData, sizeof(IMAGEHLP_MODULE64_V2));<br />
pModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE64_V2);<br />
free(pData);<br />
return TRUE;<br />
}<br />
free(pData);<br />
SetLastError(ERROR_DLL_INIT_FAILED);<br />
return FALSE;<br />
}<br />
};<br />
<br />
<br />
<br />
StackWalker::StackWalker(DWORD dwProcessId, HANDLE hProcess)<br />
{<br />
this->m_options = OptionsAll;<br />
this->m_modulesLoaded = FALSE;<br />
this->m_hProcess = hProcess;<br />
this->m_sw = new StackWalkerInternal(this, this->m_hProcess);<br />
this->m_dwProcessId = dwProcessId;<br />
this->m_szSymPath = NULL;<br />
this->m_pwos = NULL;<br />
}<br />
StackWalker::StackWalker(int options, LPCSTR szSymPath, DWORD dwProcessId, HANDLE hProcess)<br />
{<br />
this->m_options = options;<br />
this->m_modulesLoaded = FALSE;<br />
this->m_hProcess = hProcess;<br />
this->m_sw = new StackWalkerInternal(this, this->m_hProcess);<br />
this->m_dwProcessId = dwProcessId;<br />
if (szSymPath)<br />
this->m_szSymPath = _strdup(szSymPath);<br />
else<br />
this->m_szSymPath = NULL;<br />
this->m_pwos = NULL;<br />
}<br />
<br />
StackWalker::~StackWalker()<br />
{<br />
if (m_szSymPath)<br />
free(m_szSymPath);<br />
m_szSymPath = NULL;<br />
if (this->m_sw)<br />
delete this->m_sw;<br />
this->m_sw = NULL;<br />
}<br />
<br />
BOOL StackWalker::LoadModules()<br />
{<br />
if (this->m_sw == NULL)<br />
{<br />
SetLastError(ERROR_DLL_INIT_FAILED);<br />
return FALSE;<br />
}<br />
if (m_modulesLoaded != FALSE)<br />
return TRUE;<br />
<br />
char *szSymPath = NULL;<br />
if (this->m_options & SymBuildPath)<br />
{<br />
const size_t nSymPathLen = 4096;<br />
szSymPath = (char*) malloc(nSymPathLen);<br />
if (szSymPath == NULL)<br />
{<br />
SetLastError(ERROR_NOT_ENOUGH_MEMORY);<br />
return FALSE;<br />
}<br />
szSymPath[0] = 0;<br />
if (this->m_szSymPath)<br />
{<br />
strcat_s(szSymPath, nSymPathLen, this->m_szSymPath);<br />
strcat_s(szSymPath, nSymPathLen, ";");<br />
}<br />
<br />
strcat_s(szSymPath, nSymPathLen, ".;");<br />
<br />
const size_t nTempLen = 1024;<br />
char szTemp[nTempLen];<br />
if (GetCurrentDirectoryA(nTempLen, szTemp) > 0)<br />
{<br />
szTemp[nTempLen-1] = 0;<br />
strcat_s(szSymPath, nSymPathLen, szTemp);<br />
strcat_s(szSymPath, nSymPathLen, ";");<br />
}<br />
<br />
if (GetModuleFileNameA(NULL, szTemp, nTempLen) > 0)<br />
{<br />
szTemp[nTempLen-1] = 0;<br />
for (char *p = (szTemp+strlen(szTemp)-1); p >= szTemp; --p)<br />
{<br />
if ( (*p == '\\') || (*p == '/') || (*p == ':') )<br />
{<br />
*p = 0;<br />
break;<br />
}<br />
}
if (strlen(szTemp) > 0)<br />
{<br />
strcat_s(szSymPath, nSymPathLen, szTemp);<br />
strcat_s(szSymPath, nSymPathLen, ";");<br />
}<br />
}<br />
if (GetEnvironmentVariableA("_NT_SYMBOL_PATH", szTemp, nTempLen) > 0)<br />
{<br />
szTemp[nTempLen-1] = 0;<br />
strcat_s(szSymPath, nSymPathLen, szTemp);<br />
strcat_s(szSymPath, nSymPathLen, ";");<br />
}<br />
if (GetEnvironmentVariableA("_NT_ALTERNATE_SYMBOL_PATH", szTemp, nTempLen) > 0)<br />
{<br />
szTemp[nTempLen-1] = 0;<br />
strcat_s(szSymPath, nSymPathLen, szTemp);<br />
strcat_s(szSymPath, nSymPathLen, ";");<br />
}<br />
if (GetEnvironmentVariableA("SYSTEMROOT", szTemp, nTempLen) > 0)<br />
{<br />
szTemp[nTempLen-1] = 0;<br />
strcat_s(szSymPath, nSymPathLen, szTemp);<br />
strcat_s(szSymPath, nSymPathLen, ";");<br />
strcat_s(szTemp, nTempLen, "\\system32");<br />
strcat_s(szSymPath, nSymPathLen, szTemp);<br />
strcat_s(szSymPath, nSymPathLen, ";");<br />
}<br />
<br />
if ((this->m_options & SymBuildPath) && (this->m_options & SymUseSymSrv))<br />
{<br />
if (GetEnvironmentVariableA("SYSTEMDRIVE", szTemp, nTempLen) > 0)<br />
{<br />
szTemp[nTempLen-1] = 0;<br />
strcat_s(szSymPath, nSymPathLen, "SRV*");<br />
strcat_s(szSymPath, nSymPathLen, szTemp);<br />
strcat_s(szSymPath, nSymPathLen, "\\websymbols");<br />
strcat_s(szSymPath, nSymPathLen, "*http://msdl.microsoft.com/download/symbols;");<br />
}<br />
else<br />
strcat_s(szSymPath, nSymPathLen, "SRV*c:\\websymbols*http://msdl.microsoft.com/download/symbols;");<br />
}<br />
}<br />
<br />
BOOL bRet = this->m_sw->Init(szSymPath);<br />
if (szSymPath != NULL) free(szSymPath); szSymPath = NULL;<br />
if (bRet == FALSE)<br />
{<br />
this->OnDbgHelpErr("Error while initializing dbghelp.dll", 0, 0);<br />
SetLastError(ERROR_DLL_INIT_FAILED);<br />
return FALSE;<br />
}<br />
<br />
bRet = this->m_sw->LoadModules(this->m_hProcess, this->m_dwProcessId);<br />
if (bRet != FALSE)<br />
m_modulesLoaded = TRUE;<br />
return bRet;<br />
}<br />
<br />
<br />
static StackWalker::PReadProcessMemoryRoutine s_readMemoryFunction = NULL;<br />
static LPVOID s_readMemoryFunction_UserData = NULL;<br />
<br />
void StackWalker::OstreamRegister( ST_OSTREAMA* pos )<br />
{<br />
m_pos = pos;<br />
m_pwos = NULL;<br />
}<br />
<br />
void StackWalker::OstreamRegister( ST_OSTREAMW* pwos )<br />
{<br />
m_pos = NULL;<br />
m_pwos = pwos;<br />
}<br />
<br />
BOOL StackWalker::ShowCallstack(const CONTEXT *context, HANDLE hThread, <br />
PReadProcessMemoryRoutine readMemoryFunction, LPVOID pUserData)<br />
{<br />
CONTEXT c;<br />
CallstackEntry csEntry;<br />
IMAGEHLP_SYMBOL64 *pSym = NULL;<br />
StackWalkerInternal::IMAGEHLP_MODULE64_V2 Module;<br />
IMAGEHLP_LINE64 Line;<br />
int frameNum;<br />
<br />
if (m_modulesLoaded == FALSE)<br />
this->LoadModules();
<br />
if (this->m_sw->m_hDbhHelp == NULL)<br />
{<br />
SetLastError(ERROR_DLL_INIT_FAILED);<br />
return FALSE;<br />
}<br />
<br />
s_readMemoryFunction = readMemoryFunction;<br />
s_readMemoryFunction_UserData = pUserData;<br />
<br />
if (context == NULL)<br />
{<br />
if (hThread == GetCurrentThread())<br />
{<br />
GET_CURRENT_CONTEXT(c, USED_CONTEXT_FLAGS);<br />
}<br />
else<br />
{<br />
SuspendThread(hThread);<br />
memset(&c, 0, sizeof(CONTEXT));<br />
c.ContextFlags = USED_CONTEXT_FLAGS;<br />
if (GetThreadContext(hThread, &c) == FALSE)<br />
{<br />
ResumeThread(hThread);<br />
return FALSE;<br />
}<br />
}<br />
}<br />
else<br />
c = *context;<br />
<br />
STACKFRAME64 s;
memset(&s, 0, sizeof(s));<br />
DWORD imageType;<br />
#ifdef _M_IX86<br />
imageType = IMAGE_FILE_MACHINE_I386;<br />
s.AddrPC.Offset = c.Eip;<br />
s.AddrPC.Mode = AddrModeFlat;<br />
s.AddrFrame.Offset = c.Ebp;<br />
s.AddrFrame.Mode = AddrModeFlat;<br />
s.AddrStack.Offset = c.Esp;<br />
s.AddrStack.Mode = AddrModeFlat;<br />
#elif _M_X64<br />
imageType = IMAGE_FILE_MACHINE_AMD64;<br />
s.AddrPC.Offset = c.Rip;<br />
s.AddrPC.Mode = AddrModeFlat;<br />
s.AddrFrame.Offset = c.Rsp;<br />
s.AddrFrame.Mode = AddrModeFlat;<br />
s.AddrStack.Offset = c.Rsp;<br />
s.AddrStack.Mode = AddrModeFlat;<br />
#elif _M_IA64<br />
imageType = IMAGE_FILE_MACHINE_IA64;<br />
s.AddrPC.Offset = c.StIIP;<br />
s.AddrPC.Mode = AddrModeFlat;<br />
s.AddrFrame.Offset = c.IntSp;<br />
s.AddrFrame.Mode = AddrModeFlat;<br />
s.AddrBStore.Offset = c.RsBSP;<br />
s.AddrBStore.Mode = AddrModeFlat;<br />
s.AddrStack.Offset = c.IntSp;<br />
s.AddrStack.Mode = AddrModeFlat;<br />
#else<br />
#error "Platform not supported!"<br />
#endif<br />
<br />
pSym = (IMAGEHLP_SYMBOL64 *) malloc(sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN);<br />
if (!pSym) goto cleanup;
memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN);<br />
pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);<br />
pSym->MaxNameLength = STACKWALK_MAX_NAMELEN;<br />
<br />
memset(&Line, 0, sizeof(Line));<br />
Line.SizeOfStruct = sizeof(Line);<br />
<br />
memset(&Module, 0, sizeof(Module));<br />
Module.SizeOfStruct = sizeof(Module);<br />
<br />
for (frameNum = 0; ; ++frameNum )<br />
{<br />
if ( ! this->m_sw->pSW(imageType, this->m_hProcess, hThread, &s, &c, myReadProcMem, this->m_sw->pSFTA, this->m_sw->pSGMB, NULL) )<br />
{<br />
this->OnDbgHelpErr("StackWalk64", GetLastError(), s.AddrPC.Offset);<br />
break;<br />
}<br />
<br />
csEntry.offset = s.AddrPC.Offset;<br />
csEntry.name[0] = 0;<br />
csEntry.undName[0] = 0;<br />
csEntry.undFullName[0] = 0;<br />
csEntry.offsetFromSmybol = 0;<br />
csEntry.offsetFromLine = 0;<br />
csEntry.lineFileName[0] = 0;<br />
csEntry.lineNumber = 0;<br />
csEntry.loadedImageName[0] = 0;<br />
csEntry.moduleName[0] = 0;<br />
if (s.AddrPC.Offset == s.AddrReturn.Offset)<br />
{<br />
this->OnDbgHelpErr("StackWalk64-Endless-Callstack!", 0, s.AddrPC.Offset);<br />
break;<br />
}<br />
if (s.AddrPC.Offset != 0)<br />
{<br />
if (this->m_sw->pSGSFA(this->m_hProcess, s.AddrPC.Offset, &(csEntry.offsetFromSmybol), pSym) != FALSE)<br />
{<br />
strcpy_s(csEntry.name, pSym->Name);<br />
this->m_sw->pUDSN( pSym->Name, csEntry.undName, STACKWALK_MAX_NAMELEN, UNDNAME_NAME_ONLY );<br />
this->m_sw->pUDSN( pSym->Name, csEntry.undFullName, STACKWALK_MAX_NAMELEN, UNDNAME_COMPLETE );<br />
}<br />
else<br />
{<br />
this->OnDbgHelpErr("SymGetSymFromAddr64", GetLastError(), s.AddrPC.Offset);<br />
}<br />
<br />
if (this->m_sw->pSGLFA != NULL )<br />
{
if (this->m_sw->pSGLFA(this->m_hProcess, s.AddrPC.Offset, &(csEntry.offsetFromLine), &Line) != FALSE)<br />
{<br />
csEntry.lineNumber = Line.LineNumber;<br />
strcpy_s(csEntry.lineFileName, Line.FileName);<br />
}<br />
else<br />
{<br />
this->OnDbgHelpErr("SymGetLineFromAddr64", GetLastError(), s.AddrPC.Offset);<br />
}<br />
}
<br />
if (this->m_sw->GetModuleInfo(this->m_hProcess, s.AddrPC.Offset, &Module ) != FALSE)<br />
{
switch ( Module.SymType )<br />
{<br />
case SymNone:<br />
csEntry.symTypeString = "-nosymbols-";<br />
break;<br />
case SymCoff:<br />
csEntry.symTypeString = "COFF";<br />
break;<br />
case SymCv:<br />
csEntry.symTypeString = "CV";<br />
break;<br />
case SymPdb:<br />
csEntry.symTypeString = "PDB";<br />
break;<br />
case SymExport:<br />
csEntry.symTypeString = "-exported-";<br />
break;<br />
case SymDeferred:<br />
csEntry.symTypeString = "-deferred-";<br />
break;<br />
case SymSym:<br />
csEntry.symTypeString = "SYM";<br />
break;<br />
#if API_VERSION_NUMBER >= 9<br />
case SymDia:<br />
csEntry.symTypeString = "DIA";<br />
break;<br />
#endif<br />
case 8:
csEntry.symTypeString = "Virtual";<br />
break;<br />
default:<br />
csEntry.symTypeString = NULL;<br />
break;<br />
}<br />
<br />
strcpy_s(csEntry.moduleName, Module.ModuleName);<br />
csEntry.baseOfImage = Module.BaseOfImage;<br />
strcpy_s(csEntry.loadedImageName, Module.LoadedImageName);<br />
}
else<br />
{<br />
this->OnDbgHelpErr("SymGetModuleInfo64", GetLastError(), s.AddrPC.Offset);<br />
}<br />
}
<br />
CallstackEntryType et = nextEntry;<br />
if (frameNum == 0)<br />
et = firstEntry;<br />
this->OnCallstackEntry(et, csEntry);<br />
<br />
if (s.AddrReturn.Offset == 0)<br />
{<br />
this->OnCallstackEntry(lastEntry, csEntry);<br />
SetLastError(ERROR_SUCCESS);<br />
break;<br />
}<br />
}
<br />
cleanup:<br />
if (pSym) free( pSym );<br />
<br />
if (context == NULL)<br />
ResumeThread(hThread);<br />
<br />
return TRUE;<br />
}<br />
<br />
BOOL __stdcall StackWalker::myReadProcMem(<br />
HANDLE hProcess,<br />
DWORD64 qwBaseAddress,<br />
PVOID lpBuffer,<br />
DWORD nSize,<br />
LPDWORD lpNumberOfBytesRead<br />
)<br />
{<br />
if (s_readMemoryFunction == NULL)<br />
{<br />
SIZE_T st;<br />
BOOL bRet = ReadProcessMemory(hProcess, (LPVOID) qwBaseAddress, lpBuffer, nSize, &st);<br />
*lpNumberOfBytesRead = (DWORD) st;<br />
return bRet;<br />
}<br />
else<br />
{<br />
return s_readMemoryFunction(hProcess, qwBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead, s_readMemoryFunction_UserData);<br />
}<br />
}<br />
<br />
void StackWalker::OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion)<br />
{<br />
CHAR buffer[STACKWALK_MAX_NAMELEN];<br />
if (fileVersion == 0)<br />
_snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "%s:%s (%p), size: %d (result: %d), SymType: '%s', PDB: '%s'\n", img, mod, (LPVOID) baseAddr, size, result, symType, pdbName);<br />
else<br />
{<br />
DWORD v4 = (DWORD) fileVersion & 0xFFFF;<br />
DWORD v3 = (DWORD) (fileVersion>>16) & 0xFFFF;<br />
DWORD v2 = (DWORD) (fileVersion>>32) & 0xFFFF;<br />
DWORD v1 = (DWORD) (fileVersion>>48) & 0xFFFF;<br />
_snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "%s:%s (%p), size: %d (result: %d), SymType: '%s', PDB: '%s', fileVersion: %d.%d.%d.%d\n", img, mod, (LPVOID) baseAddr, size, result, symType, pdbName, v1, v2, v3, v4);<br />
}<br />
OnOutput(buffer);<br />
}<br />
<br />
void StackWalker::OnCallstackEntry(CallstackEntryType eType, CallstackEntry &entry)<br />
{<br />
CHAR buffer[STACKWALK_MAX_NAMELEN];<br />
if ( (eType != lastEntry) && (entry.offset != 0) )<br />
{<br />
if (entry.name[0] == 0)<br />
strcpy_s(entry.name, "(function-name not available)");<br />
if (entry.undName[0] != 0)<br />
strcpy_s(entry.name, entry.undName);<br />
if (entry.undFullName[0] != 0)<br />
strcpy_s(entry.name, entry.undFullName);<br />
if (entry.lineFileName[0] == 0)<br />
{<br />
strcpy_s(entry.lineFileName, "(filename not available)");<br />
if (entry.moduleName[0] == 0)<br />
strcpy_s(entry.moduleName, "(module-name not available)");<br />
_snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "%p (%s): %s: %s\n", (LPVOID) entry.offset, entry.moduleName, entry.lineFileName, entry.name);<br />
}<br />
else<br />
_snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "%s (%d): %s\n", entry.lineFileName, entry.lineNumber, entry.name);<br />
OnOutput(buffer);<br />
}<br />
}<br />
<br />
void StackWalker::OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr)<br />
{<br />
CHAR buffer[STACKWALK_MAX_NAMELEN];<br />
_snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "ERROR: %s, GetLastError: %d (Address: %p)\n", szFuncName, gle, (LPVOID) addr);<br />
OnOutput(buffer);<br />
}<br />
<br />
void StackWalker::OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName)<br />
{<br />
CHAR buffer[STACKWALK_MAX_NAMELEN];<br />
_snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "SymInit: Symbol-SearchPath: '%s', symOptions: %d, UserName: '%s'\n", szSearchPath, symOptions, szUserName);<br />
OnOutput(buffer);<br />
#if _MSC_VER <= 1200<br />
OSVERSIONINFOA ver;<br />
ZeroMemory(&ver, sizeof(OSVERSIONINFOA));<br />
ver.dwOSVersionInfoSize = sizeof(ver);<br />
if (GetVersionExA(&ver) != FALSE)<br />
{<br />
_snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "OS-Version: %d.%d.%d (%s)\n", <br />
ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber,<br />
ver.szCSDVersion);<br />
OnOutput(buffer);<br />
}<br />
#else<br />
OSVERSIONINFOEXA ver;<br />
ZeroMemory(&ver, sizeof(OSVERSIONINFOEXA));<br />
ver.dwOSVersionInfoSize = sizeof(ver);<br />
if (GetVersionExA( (OSVERSIONINFOA*) &ver) != FALSE)<br />
{<br />
_snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "OS-Version: %d.%d.%d (%s) 0x%x-0x%x\n", <br />
ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber,<br />
ver.szCSDVersion, ver.wSuiteMask, ver.wProductType);<br />
OnOutput(buffer);<br />
}<br />
#endif<br />
}<br />
<br />
void StackWalker::OnOutput(LPCSTR buffer)<br />
{<br />
if (m_pos) {<br />
*m_pos << buffer;<br />
} else if (m_pwos) {<br />
register u32 iLen = strlen(buffer) + 1;
register wchar_t *pBufferW = (wchar_t*)malloc(sizeof(wchar_t)*iLen);<br />
for (register u32 i = 0; i < iLen; i++) {<br />
pBufferW[i] = (wchar_t)buffer[i];<br />
}<br />
*m_pwos << pBufferW;<br />
free(pBufferW);<br />
} else {<br />
OutputDebugStringA(buffer);<br />
}<br />
}<br />
<br />
void StackWalker::OnOutput(LPCWSTR buffer)<br />
{<br />
if (m_pos) {<br />
register u32 iLen = lstrlen(buffer) + 1;
register char *pBufferA = (char*)malloc(sizeof(char)*iLen);<br />
for (register u32 i = 0; i < iLen; i++) {<br />
pBufferA[i] = (char)buffer[i];<br />
}<br />
*m_pos << pBufferA;<br />
free(pBufferA);<br />
} else if (m_pwos) {<br />
*m_pwos << buffer;<br />
} else {<br />
OutputDebugStringW(buffer);<br />
}<br />
}<br />
|