8888#include < stdlib.h>
8989#include < tchar.h>
9090#include < windows.h>
91+ #include < new>
92+
9193#pragma comment(lib, "version.lib") // for "VerQueryValue"
94+
9295#pragma warning(disable : 4826)
96+ #if _MSC_VER >= 1900
97+ #pragma warning(disable : 4091) // For fix unnamed enums from DbgHelp.h
98+ #endif
9399
94100
95101// If VC7 and later, then use the shipped 'dbghelp.h'-file
@@ -249,13 +255,12 @@ static void MyStrCpy(char* szDest, size_t nMaxDestSize, const char* szSrc)
249255class StackWalkerInternal
250256{
251257public:
252- StackWalkerInternal (StackWalker* parent, HANDLE hProcess)
258+ StackWalkerInternal (StackWalker* parent, HANDLE hProcess, PCONTEXT ctx )
253259 {
254260 m_parent = parent;
255261 m_hDbhHelp = NULL ;
256262 pSC = NULL ;
257263 m_hProcess = hProcess;
258- m_szSymPath = NULL ;
259264 pSFTA = NULL ;
260265 pSGLFA = NULL ;
261266 pSGMB = NULL ;
@@ -268,7 +273,11 @@ class StackWalkerInternal
268273 pSW = NULL ;
269274 pUDSN = NULL ;
270275 pSGSP = NULL ;
276+ m_ctx.ContextFlags = 0 ;
277+ if (ctx != NULL )
278+ m_ctx = *ctx;
271279 }
280+
272281 ~StackWalkerInternal ()
273282 {
274283 if (pSC != NULL )
@@ -277,10 +286,8 @@ class StackWalkerInternal
277286 FreeLibrary (m_hDbhHelp);
278287 m_hDbhHelp = NULL ;
279288 m_parent = NULL ;
280- if (m_szSymPath != NULL )
281- free (m_szSymPath);
282- m_szSymPath = NULL ;
283289 }
290+
284291 BOOL Init (LPCSTR szSymPath)
285292 {
286293 if (m_parent == NULL )
@@ -381,9 +388,7 @@ class StackWalkerInternal
381388 }
382389
383390 // SymInitialize
384- if (szSymPath != NULL )
385- m_szSymPath = _strdup (szSymPath);
386- if (this ->pSI (m_hProcess, m_szSymPath, FALSE ) == FALSE )
391+ if (this ->pSI (m_hProcess, szSymPath, FALSE ) == FALSE )
387392 this ->m_parent ->OnDbgHelpErr (" SymInitialize" , GetLastError (), 0 );
388393
389394 DWORD symOptions = this ->pSGO (); // SymGetOptions
@@ -409,12 +414,12 @@ class StackWalkerInternal
409414
410415 StackWalker* m_parent;
411416
417+ CONTEXT m_ctx;
412418 HMODULE m_hDbhHelp;
413419 HANDLE m_hProcess;
414- LPSTR m_szSymPath;
415420
416421#pragma pack(push, 8)
417- typedef struct IMAGEHLP_MODULE64_V3
422+ typedef struct _IMAGEHLP_MODULE64_V3
418423 {
419424 DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64)
420425 DWORD64 BaseOfImage; // base load address of module
@@ -441,9 +446,9 @@ class StackWalkerInternal
441446 // new elements: 17-Dec-2003
442447 BOOL SourceIndexed; // pdb supports source server
443448 BOOL Publics; // contains public symbols
444- };
449+ } IMAGEHLP_MODULE64_V3, *PIMAGEHLP_MODULE64_V3 ;
445450
446- typedef struct IMAGEHLP_MODULE64_V2
451+ typedef struct _IMAGEHLP_MODULE64_V2
447452 {
448453 DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64)
449454 DWORD64 BaseOfImage; // base load address of module
@@ -455,7 +460,7 @@ class StackWalkerInternal
455460 CHAR ModuleName[32 ]; // module name
456461 CHAR ImageName[256 ]; // image name
457462 CHAR LoadedImageName[256 ]; // symbol file name
458- };
463+ } IMAGEHLP_MODULE64_V2, *PIMAGEHLP_MODULE64_V2 ;
459464#pragma pack(pop)
460465
461466 // SymCleanup()
@@ -495,14 +500,14 @@ class StackWalkerInternal
495500 tSGSFA pSGSFA;
496501
497502 // SymInitialize()
498- typedef BOOL (__stdcall* tSI)(IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess );
503+ typedef BOOL (__stdcall* tSI)(IN HANDLE hProcess, IN LPCSTR UserSearchPath, IN BOOL fInvadeProcess );
499504 tSI pSI;
500505
501506 // SymLoadModule64()
502507 typedef DWORD64 (__stdcall* tSLM)(IN HANDLE hProcess,
503508 IN HANDLE hFile,
504- IN PSTR ImageName,
505- IN PSTR ModuleName,
509+ IN LPCSTR ImageName,
510+ IN LPCSTR ModuleName,
506511 IN DWORD64 BaseOfDll,
507512 IN DWORD SizeOfDll);
508513 tSLM pSLM;
@@ -870,41 +875,102 @@ class StackWalkerInternal
870875};
871876
872877// #############################################################
873- StackWalker::StackWalker (DWORD dwProcessId, HANDLE hProcess)
878+
879+ #if defined(_MSC_VER) && _MSC_VER >= 1400 && _MSC_VER < 1900
880+ extern " C" void * __cdecl _getptd ();
881+ #endif
882+ #if defined(_MSC_VER) && _MSC_VER >= 1900
883+ extern " C" void ** __cdecl __current_exception_context ();
884+ #endif
885+
886+ static PCONTEXT get_current_exception_context ()
874887{
875- this ->m_options = OptionsAll;
888+ PCONTEXT * pctx = NULL ;
889+ #if defined(_MSC_VER) && _MSC_VER >= 1400 && _MSC_VER < 1900
890+ LPSTR ptd = (LPSTR)_getptd ();
891+ if (ptd)
892+ pctx = (PCONTEXT *)(ptd + (sizeof (void *) == 4 ? 0x8C : 0xF8 ));
893+ #endif
894+ #if defined(_MSC_VER) && _MSC_VER >= 1900
895+ pctx = (PCONTEXT *)__current_exception_context ();
896+ #endif
897+ return pctx ? *pctx : NULL ;
898+ }
899+
900+ bool StackWalker::Init (ExceptType extype, int options, LPCSTR szSymPath, DWORD dwProcessId,
901+ HANDLE hProcess, PEXCEPTION_POINTERS exp)
902+ {
903+ PCONTEXT ctx = NULL ;
904+ if (extype == AfterCatch)
905+ ctx = get_current_exception_context ();
906+ if (extype == AfterExcept && exp)
907+ ctx = exp->ContextRecord ;
908+ this ->m_options = options;
876909 this ->m_modulesLoaded = FALSE ;
877- this ->m_hProcess = hProcess;
878- this ->m_sw = new StackWalkerInternal (this , this ->m_hProcess );
879- this ->m_dwProcessId = dwProcessId;
880910 this ->m_szSymPath = NULL ;
881911 this ->m_MaxRecursionCount = 1000 ;
912+ this ->m_sw = NULL ;
913+ SetTargetProcess (dwProcessId, hProcess);
914+ SetSymPath (szSymPath);
915+ /* MSVC ignore std::nothrow specifier for `new` operator */
916+ LPVOID buf = malloc (sizeof (StackWalkerInternal));
917+ if (!buf)
918+ return false ;
919+ memset (buf, 0 , sizeof (StackWalkerInternal));
920+ this ->m_sw = new (buf) StackWalkerInternal (this , this ->m_hProcess , ctx); // placement new
921+ return true ;
882922}
923+
924+ StackWalker::StackWalker (DWORD dwProcessId, HANDLE hProcess)
925+ {
926+ Init (NonExcept, OptionsAll, NULL , dwProcessId, hProcess);
927+ }
928+
883929StackWalker::StackWalker (int options, LPCSTR szSymPath, DWORD dwProcessId, HANDLE hProcess)
884930{
885- this ->m_options = options;
886- this ->m_modulesLoaded = FALSE ;
887- this ->m_hProcess = hProcess;
888- this ->m_sw = new StackWalkerInternal (this , this ->m_hProcess );
889- this ->m_dwProcessId = dwProcessId;
890- if (szSymPath != NULL )
891- {
892- this ->m_szSymPath = _strdup (szSymPath);
893- this ->m_options |= SymBuildPath;
894- }
895- else
896- this ->m_szSymPath = NULL ;
897- this ->m_MaxRecursionCount = 1000 ;
931+ Init (NonExcept, options, szSymPath, dwProcessId, hProcess);
932+ }
933+
934+ StackWalker::StackWalker (ExceptType extype, int options, PEXCEPTION_POINTERS exp)
935+ {
936+ Init (extype, options, NULL , GetCurrentProcessId (), GetCurrentProcess (), exp);
898937}
899938
900939StackWalker::~StackWalker ()
901940{
902- if (m_szSymPath != NULL )
941+ SetSymPath (NULL );
942+ if (m_sw != NULL ) {
943+ m_sw->~StackWalkerInternal (); // call the object's destructor
944+ free (m_sw);
945+ }
946+ m_sw = NULL ;
947+ }
948+
949+ bool StackWalker::SetSymPath (LPCSTR szSymPath)
950+ {
951+ if (m_szSymPath)
903952 free (m_szSymPath);
904953 m_szSymPath = NULL ;
905- if (this ->m_sw != NULL )
906- delete this ->m_sw ;
907- this ->m_sw = NULL ;
954+ if (szSymPath == NULL )
955+ return true ;
956+ m_szSymPath = _strdup (szSymPath);
957+ if (m_szSymPath)
958+ m_options |= SymBuildPath;
959+ return true ;
960+ }
961+
962+ bool StackWalker::SetTargetProcess (DWORD dwProcessId, HANDLE hProcess)
963+ {
964+ m_dwProcessId = dwProcessId;
965+ m_hProcess = hProcess;
966+ if (m_sw)
967+ m_sw->m_hProcess = hProcess;
968+ return true ;
969+ }
970+
971+ PCONTEXT StackWalker::GetCurrentExceptionContext ()
972+ {
973+ return get_current_exception_context ();
908974}
909975
910976BOOL StackWalker::LoadModules ()
@@ -1068,7 +1134,10 @@ BOOL StackWalker::ShowCallstack(HANDLE hThread,
10681134 if (GetThreadId (hThread) == GetCurrentThreadId ())
10691135#endif
10701136 {
1071- GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX (c, USED_CONTEXT_FLAGS);
1137+ if (m_sw->m_ctx .ContextFlags != 0 )
1138+ c = m_sw->m_ctx ; // context taken at Init
1139+ else
1140+ GET_CURRENT_CONTEXT_STACKWALKER_CODEPLEX (c, USED_CONTEXT_FLAGS);
10721141 }
10731142 else
10741143 {
0 commit comments