From a36deb2cf99e775da675e4389a308e7e4722128b Mon Sep 17 00:00:00 2001 From: William Moberg Date: Tue, 23 Feb 2016 18:19:48 +0100 Subject: [PATCH 1/5] WIP, trying to figure out why minidumps doesn't work. --- include/Game/MiniDump.h | 2 +- src/Game/MiniDump.cpp | 90 ++++++++++++++++++++++++++++------------- src/Game/main.cpp | 30 +++++++++++--- 3 files changed, 87 insertions(+), 35 deletions(-) diff --git a/include/Game/MiniDump.h b/include/Game/MiniDump.h index 4ad4548d..123dc37e 100644 --- a/include/Game/MiniDump.h +++ b/include/Game/MiniDump.h @@ -3,6 +3,6 @@ #include -void WINAPI Create_Dump(PEXCEPTION_POINTERS pException, BOOL File_Flag, BOOL Show_Flag); +void WINAPI Create_Dump(PEXCEPTION_POINTERS pException); #endif diff --git a/src/Game/MiniDump.cpp b/src/Game/MiniDump.cpp index bd8ee2de..4ebf1536 100644 --- a/src/Game/MiniDump.cpp +++ b/src/Game/MiniDump.cpp @@ -9,6 +9,7 @@ #include #include +#include #include //#include "dbghelp.h" @@ -28,9 +29,24 @@ typedef struct _MINIDUMP_EXCEPTION_INFORMATION { BOOL ClientPointers; } MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION; -typedef enum _MINIDUMP_TYPE { - MiniDumpNormal = 0x00000000, - MiniDumpWithDataSegs = 0x00000001, +typedef enum _MINIDUMP_TYPE +{ + MiniDumpNormal = 0x00000000, + MiniDumpWithDataSegs = 0x00000001, + MiniDumpWithFullMemory = 0x00000002, + MiniDumpWithHandleData = 0x00000004, + MiniDumpFilterMemory = 0x00000008, + MiniDumpScanMemory = 0x00000010, + MiniDumpWithUnloadedModules = 0x00000020, + MiniDumpWithIndirectlyReferencedMemory = 0x00000040, + MiniDumpFilterModulePaths = 0x00000080, + MiniDumpWithProcessThreadData = 0x00000100, + MiniDumpWithPrivateReadWriteMemory = 0x00000200, + MiniDumpWithoutOptionalData = 0x00000400, + MiniDumpWithFullMemoryInfo = 0x00000800, + MiniDumpWithThreadInfo = 0x00001000, + MiniDumpWithCodeSegs = 0x00002000, + MiniDumpWithoutManagedState = 0x00004000, } MINIDUMP_TYPE; typedef BOOL (WINAPI * MINIDUMP_WRITE_DUMP)( @@ -63,48 +79,64 @@ MINIDUMP_WRITE_DUMP MiniDumpWriteDump_; typedef HANDLE (WINAPI * CREATE_TOOL_HELP32_SNAPSHOT)(DWORD dwFlags, DWORD th32ProcessID); //************************************************************************************* -void WINAPI Create_Dump(PEXCEPTION_POINTERS pException, BOOL File_Flag, BOOL Show_Flag) +void WINAPI Create_Dump(PEXCEPTION_POINTERS pException) //************************************************************************************* // Create dump. // pException can be either GetExceptionInformation() or NULL. -// If File_Flag = TRUE - write dump files (.dmz and .dmp) with the name of the current process. -// If Show_Flag = TRUE - show message with Get_Exception_Info() dump. { // Try to get MiniDumpWriteDump() address. hDbgHelp = LoadLibrary("DBGHELP.DLL"); MiniDumpWriteDump_ = (MINIDUMP_WRITE_DUMP)GetProcAddress(hDbgHelp, "MiniDumpWriteDump"); - // If MiniDumpWriteDump() of DbgHelp.dll available. - if (MiniDumpWriteDump_) - { - HANDLE hDump_File; - CHAR Dump_Path[MAX_PATH]; + // If MiniDumpWriteDump() of DbgHelp.dll available. + if (MiniDumpWriteDump_) + { + //get absolute path of current process: C:/ ... /name.exe + CHAR Dump_Path[MAX_PATH]; + GetModuleFileName(NULL, Dump_Path, sizeof(Dump_Path)); + std::string path(Dump_Path); - GetModuleFileName(NULL, Dump_Path, sizeof(Dump_Path)); //path of current process + //Get current time in a string. std::time_t t = std::time(NULL); char tStr[16]; - std::strftime(tStr, 32, " %a %H-%M-%S", std::localtime(&t)); + std::strftime(tStr, ARRAYSIZE(tStr), " %a %H-%M-%S", std::localtime(&t)); std::string time(tStr); - std::string path(Dump_Path); + // Remove the .exe from path path = path.substr(0, path.length() - 4); + // Add the current time and .dmp path += time + ".dmp"; - MINIDUMP_EXCEPTION_INFORMATION M; - M.ThreadId = GetCurrentThreadId(); - M.ExceptionPointers = pException; - M.ClientPointers = 0; - - hDump_File = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - - MiniDumpWriteDump_(GetCurrentProcess(), GetCurrentProcessId(), hDump_File, - MiniDumpNormal, (pException) ? &M : NULL, NULL, NULL); - - CloseHandle(hDump_File); - - std::cout << "Memory dumped to: \"" << path.c_str() << "\""; - MessageBox(NULL, ("Application crashed, memory dumped to: " + path).c_str(), "MiniDump", MB_ICONHAND | MB_OK); + MINIDUMP_EXCEPTION_INFORMATION M; + M.ThreadId = GetCurrentThreadId(); + M.ExceptionPointers = pException; + M.ClientPointers = TRUE; + + HANDLE hDump_File = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + DWORD curProId = GetCurrentProcessId(); + //HANDLE curPro = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_DUP_HANDLE, FALSE, curProId); + HANDLE curPro = GetCurrentProcess(); + + BOOL result = MiniDumpWriteDump_(curPro, curProId, hDump_File, + MiniDumpNormal, (pException) ? &M : NULL, NULL, NULL); + HRESULT error = (HRESULT)GetLastError(); + + CloseHandle(hDump_File); + if (!result) { + _com_error cErr(error); + HRESULT actualErrorCode = error & 0xFFFF; + char eBuf[16]; + std::sprintf(eBuf, "0x%x", actualErrorCode); + std::cout << "Bad memory dump at: \"" << path.c_str() << "\"" << std::endl + << "because MiniDumpWriteDump failed with error #" << actualErrorCode << " (" << eBuf << "): \"" << cErr.ErrorMessage() << "\"" << std::endl; + MessageBox(NULL, "Application crashed, memory dump failed, but file was created.", "MiniDump", MB_ICONHAND | MB_OK); + } else { + std::cout << "Memory dumped to: \"" << path.c_str() << "\""; + MessageBox(NULL, ("Application crashed, memory dumped to: " + path).c_str(), "MiniDump", MB_ICONHAND | MB_OK); + } } else { - MessageBox(NULL, "Application crashed, memory dump failed.", "MiniDump", MB_ICONHAND | MB_OK); + std::cout << "Memory dump failed because MiniDumpWriteDump is not available."; + MessageBox(NULL, "Application crashed, could not create a memory dump.", "MiniDump", MB_ICONHAND | MB_OK); } } diff --git a/src/Game/main.cpp b/src/Game/main.cpp index dd2a5a84..f69c27d6 100644 --- a/src/Game/main.cpp +++ b/src/Game/main.cpp @@ -1,25 +1,45 @@ -#include "Game.h" +//#include "Game.h" #include "MiniDump.h" LONG WINAPI CrashHandler(EXCEPTION_POINTERS* pException); int main(int argc, char* argv[]) { - ::SetUnhandledExceptionFilter(CrashHandler); + //::SetUnhandledExceptionFilter(CrashHandler); + //EXCEPTION_POINTERS* pException = new EXCEPTION_POINTERS(); + //pException->ContextRecord = new _CONTEXT(); + //pException->ExceptionRecord = new EXCEPTION_RECORD(); + //CrashHandler(pException); + //return 0; + + __try { + int* ii = nullptr; + *ii = 17; + + //int x = asd[4]; + //std::cout << "crash before we get here, don't optimize x. " << x; + + //throw std::exception(); + } __except (CrashHandler(GetExceptionInformation())) { + system("pause"); + return 0; + } + system("pause"); + /* Game game(argc, argv); while (game.Running()) { game.Tick(); } - - return 0; + */ + return 0; } LONG WINAPI CrashHandler(EXCEPTION_POINTERS* pException) { //Take minidump. path should be bin/TacticalZ.dmp //Then show MessageBox, and exit application. - Create_Dump(pException, 1, 1); + Create_Dump(pException); return EXCEPTION_EXECUTE_HANDLER;// EXCEPTION_CONTINUE_SEARCH } \ No newline at end of file From 05bbecc4524848a146a812beb200f739df6e7136 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Wed, 24 Feb 2016 17:23:47 +0100 Subject: [PATCH 2/5] WIP, minidump is done in another program, started from our app. The other program is not in git yet. --- src/Game/main.cpp | 49 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/src/Game/main.cpp b/src/Game/main.cpp index f69c27d6..1445f9ed 100644 --- a/src/Game/main.cpp +++ b/src/Game/main.cpp @@ -1,4 +1,4 @@ -//#include "Game.h" +#include "Game.h" #include "MiniDump.h" LONG WINAPI CrashHandler(EXCEPTION_POINTERS* pException); @@ -37,9 +37,50 @@ int main(int argc, char* argv[]) LONG WINAPI CrashHandler(EXCEPTION_POINTERS* pException) { - //Take minidump. path should be bin/TacticalZ.dmp - //Then show MessageBox, and exit application. - Create_Dump(pException); + // Get absolute path of current process: C:/ ... /name.exe + CHAR Dump_Path[MAX_PATH]; + GetModuleFileName(NULL, Dump_Path, sizeof(Dump_Path)); + std::string path(Dump_Path); + // Then make the path into C:/ .. /nameDump.exe + // Remove the .exe from path + path = path.substr(0, path.length() - 4); + path += "Dump.exe"; + + DWORD procId = GetCurrentProcessId(); + DWORD threadId = GetCurrentThreadId(); + std::uintptr_t intExcPtr = reinterpret_cast(pException); + std::ostringstream ss; + ss << procId << " " << threadId << " " << intExcPtr; + char cmds[128]; + strcpy(cmds, ss.str().c_str()); + + STARTUPINFO sInfo; + PROCESS_INFORMATION pInfo; + ZeroMemory(&sInfo, sizeof(sInfo)); + ZeroMemory(&pInfo, sizeof(pInfo)); + sInfo.cb = sizeof(sInfo); + + if (CreateProcess(path.c_str(), + cmds, + nullptr, + nullptr, + FALSE, + NORMAL_PRIORITY_CLASS, + nullptr, + nullptr, + &sInfo, + &pInfo) + ) { + WaitForSingleObject(pInfo.hProcess, INFINITE); + CloseHandle(pInfo.hProcess); + CloseHandle(pInfo.hThread); + } else { + HRESULT error = ((HRESULT)GetLastError()) & 0xFFFF; + char hexErrBuf[16]; + std::sprintf(hexErrBuf, "0x%x", error); + std::cout << "Could not create a minidump because CreateProcess failed with error " << hexErrBuf; + MessageBox(NULL, "Application crashed, could not create a memory dump.", "MiniDump", MB_ICONHAND | MB_OK); + } return EXCEPTION_EXECUTE_HANDLER;// EXCEPTION_CONTINUE_SEARCH } \ No newline at end of file From cc34f53b16a3aaefe7fe53af18451e25e8b84b75 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Thu, 3 Mar 2016 16:07:35 +0100 Subject: [PATCH 3/5] Memorydump stage 1 fix --- src/Game/main.cpp | 50 ++++++++++++----------------------------------- 1 file changed, 13 insertions(+), 37 deletions(-) diff --git a/src/Game/main.cpp b/src/Game/main.cpp index 1445f9ed..e03a424c 100644 --- a/src/Game/main.cpp +++ b/src/Game/main.cpp @@ -1,41 +1,22 @@ #include "Game.h" #include "MiniDump.h" -LONG WINAPI CrashHandler(EXCEPTION_POINTERS* pException); +LONG WINAPI CrashHandler(LPEXCEPTION_POINTERS pException); int main(int argc, char* argv[]) { - //::SetUnhandledExceptionFilter(CrashHandler); + SetUnhandledExceptionFilter(CrashHandler); - //EXCEPTION_POINTERS* pException = new EXCEPTION_POINTERS(); - //pException->ContextRecord = new _CONTEXT(); - //pException->ExceptionRecord = new EXCEPTION_RECORD(); - //CrashHandler(pException); - //return 0; - - __try { - int* ii = nullptr; - *ii = 17; - - //int x = asd[4]; - //std::cout << "crash before we get here, don't optimize x. " << x; - - //throw std::exception(); - } __except (CrashHandler(GetExceptionInformation())) { - system("pause"); - return 0; - } - system("pause"); - /* + //run the .exe file to get a possible crashdump Game game(argc, argv); while (game.Running()) { game.Tick(); } - */ + return 0; } -LONG WINAPI CrashHandler(EXCEPTION_POINTERS* pException) +LONG WINAPI CrashHandler(LPEXCEPTION_POINTERS pException) { // Get absolute path of current process: C:/ ... /name.exe CHAR Dump_Path[MAX_PATH]; @@ -46,22 +27,17 @@ LONG WINAPI CrashHandler(EXCEPTION_POINTERS* pException) path = path.substr(0, path.length() - 4); path += "Dump.exe"; - DWORD procId = GetCurrentProcessId(); - DWORD threadId = GetCurrentThreadId(); - std::uintptr_t intExcPtr = reinterpret_cast(pException); - std::ostringstream ss; - ss << procId << " " << threadId << " " << intExcPtr; - char cmds[128]; - strcpy(cmds, ss.str().c_str()); + wchar_t commandLine[32768]; + swprintf_s(commandLine, sizeof(commandLine) / sizeof(commandLine[0]), L"\"%ls\" %lu %lu %p", path.c_str(), GetCurrentProcessId(), GetCurrentThreadId(), pException); - STARTUPINFO sInfo; + STARTUPINFOW sInfo; PROCESS_INFORMATION pInfo; ZeroMemory(&sInfo, sizeof(sInfo)); ZeroMemory(&pInfo, sizeof(pInfo)); sInfo.cb = sizeof(sInfo); - if (CreateProcess(path.c_str(), - cmds, + if (CreateProcessW(L"TacticalZDump.exe", + commandLine, nullptr, nullptr, FALSE, @@ -69,8 +45,7 @@ LONG WINAPI CrashHandler(EXCEPTION_POINTERS* pException) nullptr, nullptr, &sInfo, - &pInfo) - ) { + &pInfo)) { WaitForSingleObject(pInfo.hProcess, INFINITE); CloseHandle(pInfo.hProcess); CloseHandle(pInfo.hThread); @@ -83,4 +58,5 @@ LONG WINAPI CrashHandler(EXCEPTION_POINTERS* pException) } return EXCEPTION_EXECUTE_HANDLER;// EXCEPTION_CONTINUE_SEARCH -} \ No newline at end of file +} + From db09d93111a067cfe82dd66de09d982f07194fa2 Mon Sep 17 00:00:00 2001 From: verysecrethero Date: Thu, 3 Mar 2016 16:41:47 +0100 Subject: [PATCH 4/5] Minidump stage 2 fix --- include/Game/MiniDump.h | 7 ++- src/Game/main.cpp | 132 +++++++++++++++++++++++++++------------- 2 files changed, 94 insertions(+), 45 deletions(-) diff --git a/include/Game/MiniDump.h b/include/Game/MiniDump.h index 123dc37e..a984f6e4 100644 --- a/include/Game/MiniDump.h +++ b/include/Game/MiniDump.h @@ -1,8 +1,11 @@ #ifndef MiniDump_h__ #define MiniDump_h__ -#include +#include -void WINAPI Create_Dump(PEXCEPTION_POINTERS pException); +#include +#include + +long WINAPI Create_Dump_Immediate(LPEXCEPTION_POINTERS pException); #endif diff --git a/src/Game/main.cpp b/src/Game/main.cpp index e03a424c..3eb71387 100644 --- a/src/Game/main.cpp +++ b/src/Game/main.cpp @@ -1,13 +1,10 @@ #include "Game.h" #include "MiniDump.h" -LONG WINAPI CrashHandler(LPEXCEPTION_POINTERS pException); - int main(int argc, char* argv[]) { - SetUnhandledExceptionFilter(CrashHandler); + SetUnhandledExceptionFilter(Create_Dump_Immediate); - //run the .exe file to get a possible crashdump Game game(argc, argv); while (game.Running()) { game.Tick(); @@ -16,47 +13,96 @@ int main(int argc, char* argv[]) return 0; } -LONG WINAPI CrashHandler(LPEXCEPTION_POINTERS pException) +/* +Inspired by Original Author: Vladimir Sedach. + +Purpose: demo of Call Stack creation by our own means, +and with MiniDumpWriteDump() function of DbgHelp.dll. +*/ + +#pragma optimize("y", off) //generate stack frame pointers for all functions - same as /Oy- in the project +#pragma warning(disable: 4200) //nonstandard extension used : zero-sized array in struct/union +#pragma warning(disable: 4100) //unreferenced formal parameter + +typedef BOOL(WINAPI * MINIDUMP_WRITE_DUMP)( + IN HANDLE hProcess, + IN DWORD ProcessId, + IN HANDLE hFile, + IN MINIDUMP_TYPE DumpType, + IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL + IN PVOID UserStreamParam, OPTIONAL + IN PVOID CallbackParam OPTIONAL + ); + + + +//************************************************************************************* +long WINAPI Create_Dump_Immediate(LPEXCEPTION_POINTERS pException) +//************************************************************************************* +// Create dump. +// pException can be either GetExceptionInformation() or NULL. { - // Get absolute path of current process: C:/ ... /name.exe - CHAR Dump_Path[MAX_PATH]; - GetModuleFileName(NULL, Dump_Path, sizeof(Dump_Path)); - std::string path(Dump_Path); - // Then make the path into C:/ .. /nameDump.exe - // Remove the .exe from path - path = path.substr(0, path.length() - 4); - path += "Dump.exe"; - - wchar_t commandLine[32768]; - swprintf_s(commandLine, sizeof(commandLine) / sizeof(commandLine[0]), L"\"%ls\" %lu %lu %p", path.c_str(), GetCurrentProcessId(), GetCurrentThreadId(), pException); - - STARTUPINFOW sInfo; - PROCESS_INFORMATION pInfo; - ZeroMemory(&sInfo, sizeof(sInfo)); - ZeroMemory(&pInfo, sizeof(pInfo)); - sInfo.cb = sizeof(sInfo); - - if (CreateProcessW(L"TacticalZDump.exe", - commandLine, - nullptr, - nullptr, - FALSE, - NORMAL_PRIORITY_CLASS, - nullptr, - nullptr, - &sInfo, - &pInfo)) { - WaitForSingleObject(pInfo.hProcess, INFINITE); - CloseHandle(pInfo.hProcess); - CloseHandle(pInfo.hThread); + // Try to get MiniDumpWriteDump() address. + HMODULE hDbgHelp = LoadLibrary("DBGHELP.DLL"); + MINIDUMP_WRITE_DUMP MiniDumpWriteDump_ = (MINIDUMP_WRITE_DUMP)GetProcAddress(hDbgHelp, "MiniDumpWriteDump"); + + // If MiniDumpWriteDump() of DbgHelp.dll available. + if (MiniDumpWriteDump_) { + // Get absolute path of current process: C:/ ... /name.exe + CHAR Dump_Path[MAX_PATH]; + GetModuleFileName(NULL, Dump_Path, sizeof(Dump_Path)); + std::string path(Dump_Path); + + // Get current time in a string. + std::time_t t = std::time(NULL); + char tStr[16]; + std::strftime(tStr, ARRAYSIZE(tStr), " %a %H-%M-%S", std::localtime(&t)); + std::string time(tStr); + // Remove the .exe from path + path = path.substr(0, path.length() - 4); + // Add the current time and .dmp + path += "dump" + time + ".dmp"; + + DWORD procId = GetCurrentProcessId(); + DWORD threadId = GetCurrentThreadId(); + + MINIDUMP_EXCEPTION_INFORMATION M; + M.ThreadId = threadId; + M.ExceptionPointers = pException; + M.ClientPointers = TRUE; + + HANDLE hDump_File = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + HANDLE process = GetCurrentProcess(); + + BOOL result = MiniDumpWriteDump_(process, procId, hDump_File, + (MINIDUMP_TYPE)(MiniDumpWithDataSegs | + MiniDumpWithHandleData | + MiniDumpScanMemory | + MiniDumpWithUnloadedModules | + MiniDumpWithIndirectlyReferencedMemory | + MiniDumpWithPrivateReadWriteMemory | + MiniDumpWithFullMemoryInfo | + MiniDumpWithThreadInfo | + MiniDumpIgnoreInaccessibleMemory) + , &M, NULL, NULL); + HRESULT error = (HRESULT)GetLastError(); + + CloseHandle(hDump_File); + if (!result) { + _com_error cErr(error); + HRESULT actualErrorCode = error & 0xFFFF; + char hexErrBuf[16]; + std::sprintf(hexErrBuf, "0x%x", actualErrorCode); + std::cout << "Bad memory dump at: \"" << path.c_str() << "\"" << std::endl + << "because MiniDumpWriteDump failed with error #" << actualErrorCode << " (" << hexErrBuf << "): \"" << cErr.ErrorMessage() << "\"" << std::endl; + MessageBox(NULL, "Application crashed, memory dump failed, but file was created.", "MiniDump", MB_ICONHAND | MB_OK); + } else { + std::cout << "Memory dumped to: \"" << path.c_str() << "\"" << std::endl; + MessageBox(NULL, ("Application crashed, memory dumped to: " + path).c_str(), "MiniDump", MB_ICONHAND | MB_OK); + } } else { - HRESULT error = ((HRESULT)GetLastError()) & 0xFFFF; - char hexErrBuf[16]; - std::sprintf(hexErrBuf, "0x%x", error); - std::cout << "Could not create a minidump because CreateProcess failed with error " << hexErrBuf; + std::cout << "Memory dump failed because MiniDumpWriteDump is not available." << std::endl; MessageBox(NULL, "Application crashed, could not create a memory dump.", "MiniDump", MB_ICONHAND | MB_OK); } - - return EXCEPTION_EXECUTE_HANDLER;// EXCEPTION_CONTINUE_SEARCH + return 0; } - From bc3c8299e8d06db5b5b2c013425348805b660909 Mon Sep 17 00:00:00 2001 From: William Moberg Date: Fri, 4 Mar 2016 03:05:09 +0100 Subject: [PATCH 5/5] Moved minidump code to MiniDump.cpp from main. --- include/Game/MiniDump.h | 4 +- src/Game/MiniDump.cpp | 141 ++++++++++++++-------------------------- src/Game/main.cpp | 98 +--------------------------- 3 files changed, 53 insertions(+), 190 deletions(-) diff --git a/include/Game/MiniDump.h b/include/Game/MiniDump.h index a984f6e4..022622a7 100644 --- a/include/Game/MiniDump.h +++ b/include/Game/MiniDump.h @@ -1,11 +1,9 @@ #ifndef MiniDump_h__ #define MiniDump_h__ +#include #include -#include -#include - long WINAPI Create_Dump_Immediate(LPEXCEPTION_POINTERS pException); #endif diff --git a/src/Game/MiniDump.cpp b/src/Game/MiniDump.cpp index 4ebf1536..01ed4c90 100644 --- a/src/Game/MiniDump.cpp +++ b/src/Game/MiniDump.cpp @@ -1,102 +1,49 @@ /* - Author: Vladimir Sedach. +Inspired by Original Author: Vladimir Sedach. - Purpose: demo of Call Stack creation by our own means, - and with MiniDumpWriteDump() function of DbgHelp.dll. +Purpose: demo of Call Stack creation by our own means, +and with MiniDumpWriteDump() function of DbgHelp.dll. */ +#include "MiniDump.h" + +#include #include #include - -#include #include -#include -//#include "dbghelp.h" - -//#define DEBUG_DPRINTF 1 //allow d() -//#include "wfun.h" - -#pragma optimize("y", off) //generate stack frame pointers for all functions - same as /Oy- in the project -#pragma warning(disable: 4200) //nonstandard extension used : zero-sized array in struct/union -#pragma warning(disable: 4100) //unreferenced formal parameter - -// In case you don't have dbghelp.h. -#ifndef _DBGHELP_ - -typedef struct _MINIDUMP_EXCEPTION_INFORMATION { - DWORD ThreadId; - PEXCEPTION_POINTERS ExceptionPointers; - BOOL ClientPointers; -} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION; - -typedef enum _MINIDUMP_TYPE -{ - MiniDumpNormal = 0x00000000, - MiniDumpWithDataSegs = 0x00000001, - MiniDumpWithFullMemory = 0x00000002, - MiniDumpWithHandleData = 0x00000004, - MiniDumpFilterMemory = 0x00000008, - MiniDumpScanMemory = 0x00000010, - MiniDumpWithUnloadedModules = 0x00000020, - MiniDumpWithIndirectlyReferencedMemory = 0x00000040, - MiniDumpFilterModulePaths = 0x00000080, - MiniDumpWithProcessThreadData = 0x00000100, - MiniDumpWithPrivateReadWriteMemory = 0x00000200, - MiniDumpWithoutOptionalData = 0x00000400, - MiniDumpWithFullMemoryInfo = 0x00000800, - MiniDumpWithThreadInfo = 0x00001000, - MiniDumpWithCodeSegs = 0x00002000, - MiniDumpWithoutManagedState = 0x00004000, -} MINIDUMP_TYPE; - -typedef BOOL (WINAPI * MINIDUMP_WRITE_DUMP)( - IN HANDLE hProcess, - IN DWORD ProcessId, - IN HANDLE hFile, - IN MINIDUMP_TYPE DumpType, - IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL - IN PVOID UserStreamParam, OPTIONAL - IN PVOID CallbackParam OPTIONAL - ); - -#else - -typedef BOOL (WINAPI * MINIDUMP_WRITE_DUMP)( - IN HANDLE hProcess, - IN DWORD ProcessId, - IN HANDLE hFile, - IN MINIDUMP_TYPE DumpType, - IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL - IN PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL - IN PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL - ); -#endif //#ifndef _DBGHELP_ -HMODULE hDbgHelp; -MINIDUMP_WRITE_DUMP MiniDumpWriteDump_; +#pragma optimize("y", off) //generate stack frame pointers for all functions - same as /Oy- in the project +#pragma warning(disable: 4200) //nonstandard extension used : zero-sized array in struct/union +#pragma warning(disable: 4100) //unreferenced formal parameter -// Tool Help functions. -typedef HANDLE (WINAPI * CREATE_TOOL_HELP32_SNAPSHOT)(DWORD dwFlags, DWORD th32ProcessID); +typedef BOOL(WINAPI * MINIDUMP_WRITE_DUMP)( + IN HANDLE hProcess, + IN DWORD ProcessId, + IN HANDLE hFile, + IN MINIDUMP_TYPE DumpType, + IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL + IN PVOID UserStreamParam, OPTIONAL + IN PVOID CallbackParam OPTIONAL + ); //************************************************************************************* -void WINAPI Create_Dump(PEXCEPTION_POINTERS pException) +long WINAPI Create_Dump_Immediate(LPEXCEPTION_POINTERS pException) //************************************************************************************* // Create dump. // pException can be either GetExceptionInformation() or NULL. { // Try to get MiniDumpWriteDump() address. - hDbgHelp = LoadLibrary("DBGHELP.DLL"); - MiniDumpWriteDump_ = (MINIDUMP_WRITE_DUMP)GetProcAddress(hDbgHelp, "MiniDumpWriteDump"); + HMODULE hDbgHelp = LoadLibrary("DBGHELP.DLL"); + MINIDUMP_WRITE_DUMP MiniDumpWriteDump_ = (MINIDUMP_WRITE_DUMP)GetProcAddress(hDbgHelp, "MiniDumpWriteDump"); // If MiniDumpWriteDump() of DbgHelp.dll available. - if (MiniDumpWriteDump_) - { - //get absolute path of current process: C:/ ... /name.exe + if (MiniDumpWriteDump_) { + // Get absolute path of current process: C:/ ... /name.exe CHAR Dump_Path[MAX_PATH]; GetModuleFileName(NULL, Dump_Path, sizeof(Dump_Path)); std::string path(Dump_Path); - //Get current time in a string. + // Get current time in a string. std::time_t t = std::time(NULL); char tStr[16]; std::strftime(tStr, ARRAYSIZE(tStr), " %a %H-%M-%S", std::localtime(&t)); @@ -104,39 +51,51 @@ void WINAPI Create_Dump(PEXCEPTION_POINTERS pException) // Remove the .exe from path path = path.substr(0, path.length() - 4); // Add the current time and .dmp - path += time + ".dmp"; + path += "dump" + time + ".dmp"; + + DWORD procId = GetCurrentProcessId(); + DWORD threadId = GetCurrentThreadId(); MINIDUMP_EXCEPTION_INFORMATION M; - M.ThreadId = GetCurrentThreadId(); + M.ThreadId = threadId; M.ExceptionPointers = pException; M.ClientPointers = TRUE; HANDLE hDump_File = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - - DWORD curProId = GetCurrentProcessId(); - //HANDLE curPro = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_DUP_HANDLE, FALSE, curProId); - HANDLE curPro = GetCurrentProcess(); - - BOOL result = MiniDumpWriteDump_(curPro, curProId, hDump_File, - MiniDumpNormal, (pException) ? &M : NULL, NULL, NULL); + HANDLE process = GetCurrentProcess(); + + BOOL result = MiniDumpWriteDump_(process, procId, hDump_File + , (MINIDUMP_TYPE)(MiniDumpWithDataSegs | + MiniDumpWithHandleData | + MiniDumpScanMemory | + MiniDumpWithUnloadedModules | + MiniDumpWithIndirectlyReferencedMemory | + MiniDumpWithPrivateReadWriteMemory | + MiniDumpWithFullMemoryInfo | + MiniDumpWithThreadInfo | + MiniDumpIgnoreInaccessibleMemory) + , &M, NULL, NULL); HRESULT error = (HRESULT)GetLastError(); CloseHandle(hDump_File); if (!result) { _com_error cErr(error); HRESULT actualErrorCode = error & 0xFFFF; - char eBuf[16]; - std::sprintf(eBuf, "0x%x", actualErrorCode); + char hexErrBuf[16]; + std::sprintf(hexErrBuf, "0x%x", actualErrorCode); std::cout << "Bad memory dump at: \"" << path.c_str() << "\"" << std::endl - << "because MiniDumpWriteDump failed with error #" << actualErrorCode << " (" << eBuf << "): \"" << cErr.ErrorMessage() << "\"" << std::endl; + << "because MiniDumpWriteDump failed with error #" << actualErrorCode << " (" << hexErrBuf << "): \"" << cErr.ErrorMessage() << "\"" << std::endl; MessageBox(NULL, "Application crashed, memory dump failed, but file was created.", "MiniDump", MB_ICONHAND | MB_OK); } else { - std::cout << "Memory dumped to: \"" << path.c_str() << "\""; + std::cout << "Memory dumped to: \"" << path.c_str() << "\"" << std::endl; MessageBox(NULL, ("Application crashed, memory dumped to: " + path).c_str(), "MiniDump", MB_ICONHAND | MB_OK); } } else { - std::cout << "Memory dump failed because MiniDumpWriteDump is not available."; + std::cout << "Memory dump failed because MiniDumpWriteDump is not available." << std::endl; MessageBox(NULL, "Application crashed, could not create a memory dump.", "MiniDump", MB_ICONHAND | MB_OK); } + + // Basically, terminate the application. + return EXCEPTION_EXECUTE_HANDLER; } diff --git a/src/Game/main.cpp b/src/Game/main.cpp index aa76cc07..b94f0b97 100644 --- a/src/Game/main.cpp +++ b/src/Game/main.cpp @@ -7,104 +7,10 @@ int main(int argc, char* argv[]) Game game(argc, argv); while (game.Running()) { - PerformanceTimer::StartTimer("Game-Tick"); + PerformanceTimer::StartTimer("Game-Tick"); game.Tick(); - PerformanceTimer::StopTimer("Game-Tick"); + PerformanceTimer::StopTimer("Game-Tick"); } return 0; } - -/* -Inspired by Original Author: Vladimir Sedach. - -Purpose: demo of Call Stack creation by our own means, -and with MiniDumpWriteDump() function of DbgHelp.dll. -*/ - -#pragma optimize("y", off) //generate stack frame pointers for all functions - same as /Oy- in the project -#pragma warning(disable: 4200) //nonstandard extension used : zero-sized array in struct/union -#pragma warning(disable: 4100) //unreferenced formal parameter - -typedef BOOL(WINAPI * MINIDUMP_WRITE_DUMP)( - IN HANDLE hProcess, - IN DWORD ProcessId, - IN HANDLE hFile, - IN MINIDUMP_TYPE DumpType, - IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL - IN PVOID UserStreamParam, OPTIONAL - IN PVOID CallbackParam OPTIONAL - ); - - - -//************************************************************************************* -long WINAPI Create_Dump_Immediate(LPEXCEPTION_POINTERS pException) -//************************************************************************************* -// Create dump. -// pException can be either GetExceptionInformation() or NULL. -{ - // Try to get MiniDumpWriteDump() address. - HMODULE hDbgHelp = LoadLibrary("DBGHELP.DLL"); - MINIDUMP_WRITE_DUMP MiniDumpWriteDump_ = (MINIDUMP_WRITE_DUMP)GetProcAddress(hDbgHelp, "MiniDumpWriteDump"); - - // If MiniDumpWriteDump() of DbgHelp.dll available. - if (MiniDumpWriteDump_) { - // Get absolute path of current process: C:/ ... /name.exe - CHAR Dump_Path[MAX_PATH]; - GetModuleFileName(NULL, Dump_Path, sizeof(Dump_Path)); - std::string path(Dump_Path); - - // Get current time in a string. - std::time_t t = std::time(NULL); - char tStr[16]; - std::strftime(tStr, ARRAYSIZE(tStr), " %a %H-%M-%S", std::localtime(&t)); - std::string time(tStr); - // Remove the .exe from path - path = path.substr(0, path.length() - 4); - // Add the current time and .dmp - path += "dump" + time + ".dmp"; - - DWORD procId = GetCurrentProcessId(); - DWORD threadId = GetCurrentThreadId(); - - MINIDUMP_EXCEPTION_INFORMATION M; - M.ThreadId = threadId; - M.ExceptionPointers = pException; - M.ClientPointers = TRUE; - - HANDLE hDump_File = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - HANDLE process = GetCurrentProcess(); - - BOOL result = MiniDumpWriteDump_(process, procId, hDump_File, - (MINIDUMP_TYPE)(MiniDumpWithDataSegs | - MiniDumpWithHandleData | - MiniDumpScanMemory | - MiniDumpWithUnloadedModules | - MiniDumpWithIndirectlyReferencedMemory | - MiniDumpWithPrivateReadWriteMemory | - MiniDumpWithFullMemoryInfo | - MiniDumpWithThreadInfo | - MiniDumpIgnoreInaccessibleMemory) - , &M, NULL, NULL); - HRESULT error = (HRESULT)GetLastError(); - - CloseHandle(hDump_File); - if (!result) { - _com_error cErr(error); - HRESULT actualErrorCode = error & 0xFFFF; - char hexErrBuf[16]; - std::sprintf(hexErrBuf, "0x%x", actualErrorCode); - std::cout << "Bad memory dump at: \"" << path.c_str() << "\"" << std::endl - << "because MiniDumpWriteDump failed with error #" << actualErrorCode << " (" << hexErrBuf << "): \"" << cErr.ErrorMessage() << "\"" << std::endl; - MessageBox(NULL, "Application crashed, memory dump failed, but file was created.", "MiniDump", MB_ICONHAND | MB_OK); - } else { - std::cout << "Memory dumped to: \"" << path.c_str() << "\"" << std::endl; - MessageBox(NULL, ("Application crashed, memory dumped to: " + path).c_str(), "MiniDump", MB_ICONHAND | MB_OK); - } - } else { - std::cout << "Memory dump failed because MiniDumpWriteDump is not available." << std::endl; - MessageBox(NULL, "Application crashed, could not create a memory dump.", "MiniDump", MB_ICONHAND | MB_OK); - } - return 0; -}