Windows程序开发之Dump文件生成
来源:互联网 发布:公路工程概预算软件 编辑:程序博客网 时间:2024/06/02 00:58
原文出处:http://blog.csdn.net/hiwubihe/article/details/52648002
MiniDumper.h
#ifndef MINIDUMPER_H#define MINIDUMPER_H#include <windows.h>class CMiniDumper{public: CMiniDumper(bool bPromptUserForMiniDump = true); ~CMiniDumper(void);private: static LONG WINAPI unhandledExceptionHandler(struct _EXCEPTION_POINTERS *pExceptionInfo); void disableSetUnhandledExceptionFilter(); static void __cdecl myInvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved); static void __cdecl myPurecallHandler(void); void setMiniDumpFileName(void); bool getImpersonationToken(HANDLE* phToken); BOOL enablePrivilege(LPCTSTR pszPriv, HANDLE hToken, TOKEN_PRIVILEGES* ptpOld); BOOL restorePrivilege(HANDLE hToken, TOKEN_PRIVILEGES* ptpOld); LONG writeMiniDump(_EXCEPTION_POINTERS *pExceptionInfo ); _EXCEPTION_POINTERS *m_pExceptionInfo; TCHAR m_szMiniDumpPath[MAX_PATH]; TCHAR m_szAppPath[MAX_PATH]; TCHAR m_szAppBaseName[MAX_PATH]; bool m_bPromptUserForMiniDump; static CMiniDumper* s_pMiniDumper; static LPCRITICAL_SECTION s_pCriticalSection;};#endif // MINIDUMPER_H
MiniDumper.cpp
#include <windows.h>#include <stdio.h>#include <assert.h>#include <time.h>#include <tchar.h>#include <dbghelp.h>#include "MiniDumper.h"#ifdef UNICODE #define _tcssprintf wsprintf #define tcsplitpath _wsplitpath#else #define _tcssprintf sprintf #define tcsplitpath _splitpath#endif#ifndef LogError#define LogError printf#endif const int USER_DATA_BUFFER_SIZE = 4096;//-----------------------------------------------------------------------------// GLOBALS//-----------------------------------------------------------------------------CMiniDumper* CMiniDumper::s_pMiniDumper = NULL;LPCRITICAL_SECTION CMiniDumper::s_pCriticalSection = NULL;// Based on dbghelp.htypedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType, CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);//-----------------------------------------------------------------------------// Name: CMiniDumper()// Desc: Constructor//-----------------------------------------------------------------------------CMiniDumper::CMiniDumper( bool bPromptUserForMiniDump ){ // Our CMiniDumper should act alone as a singleton. assert( !s_pMiniDumper ); s_pMiniDumper = this; m_bPromptUserForMiniDump = bPromptUserForMiniDump; // The SetUnhandledExceptionFilter function enables an application to // supersede the top-level exception handler of each thread and process. // After calling this function, if an exception occurs in a process // that is not being debugged, and the exception makes it to the // unhandled exception filter, that filter will call the exception // filter function specified by the lpTopLevelExceptionFilter parameter. ::SetUnhandledExceptionFilter( unhandledExceptionHandler ); /* * 为了安全起见(万一有某种新型的异常没有被事先安装的处理器过滤,UEF会被覆盖), * 你可以HOOK掉Kernel32.SetUnhandledExceptionFilter,从而禁止任何可能的覆盖。 */ _set_abort_behavior(0, _CALL_REPORTFAULT); _set_invalid_parameter_handler(myInvalidParameterHandler); _set_purecall_handler(myPurecallHandler); disableSetUnhandledExceptionFilter(); // Since DBGHELP.dll is not inherently thread-safe, making calls into it // from more than one thread simultaneously may yield undefined behavior. // This means that if your application has multiple threads, or is // called by multiple threads in a non-synchronized manner, you need to // make sure that all calls into DBGHELP.dll are isolated via a global // critical section. s_pCriticalSection = new CRITICAL_SECTION; if( s_pCriticalSection ) InitializeCriticalSection( s_pCriticalSection );}//-----------------------------------------------------------------------------// Name: ~CMiniDumper()// Desc: Destructor//-----------------------------------------------------------------------------CMiniDumper::~CMiniDumper( void ){ if( s_pCriticalSection ) { DeleteCriticalSection( s_pCriticalSection ); delete s_pCriticalSection; }}//-----------------------------------------------------------------------------// Name: unhandledExceptionHandler()// Desc: Call-back filter function for unhandled exceptions//-----------------------------------------------------------------------------LONG CMiniDumper::unhandledExceptionHandler( _EXCEPTION_POINTERS *pExceptionInfo ){ if( !s_pMiniDumper ) return EXCEPTION_CONTINUE_SEARCH; return s_pMiniDumper->writeMiniDump( pExceptionInfo );}void CMiniDumper::disableSetUnhandledExceptionFilter(){ void *addr = (void*)GetProcAddress(LoadLibrary(_T("kernel32.dll")), "SetUnhandledExceptionFilter"); if (addr) { unsigned char code[16]; int size = 0; code[size++] = 0x33; code[size++] = 0xC0; code[size++] = 0xC2; code[size++] = 0x04; code[size++] = 0x00; DWORD dwOldFlag, dwTempFlag; VirtualProtect(addr, size, PAGE_READWRITE, &dwOldFlag); WriteProcessMemory(GetCurrentProcess(), addr, code, size, NULL); VirtualProtect(addr, size, dwOldFlag, &dwTempFlag); }}void CMiniDumper::myInvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved){ //wprintf(L"Invalid parameter detected in function %s." // L" File: %s Line: %d\n", function, file, line); //wprintf(L"Expression: %s\n", expression); throw 1;}void CMiniDumper::myPurecallHandler(void){ throw 1;}//-----------------------------------------------------------------------------// Name: setMiniDumpFileName()// Desc: //-----------------------------------------------------------------------------void CMiniDumper::setMiniDumpFileName( void ){ time_t currentTime; time( ¤tTime ); TCHAR chTmp[100]; memset(chTmp, 0, sizeof(chTmp)); struct tm *p; p = localtime(¤tTime); if(p == NULL) return; p->tm_year = p->tm_year + 1900; p->tm_mon = p->tm_mon + 1; _tcssprintf(chTmp, _T("%04d-%02d-%02d_%02d-%02d-%02d"), p->tm_year, p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec); _tcssprintf( m_szMiniDumpPath, _T("%s%s_%s.dmp"), m_szAppPath, m_szAppBaseName, chTmp );}//-----------------------------------------------------------------------------// Name: getImpersonationToken()// Desc: The method acts as a potential workaround for the fact that the // current thread may not have a token assigned to it, and if not, the // process token is received.//-----------------------------------------------------------------------------bool CMiniDumper::getImpersonationToken( HANDLE* phToken ){ *phToken = NULL; if( !OpenThreadToken( GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, TRUE, phToken) ) { if( GetLastError() == ERROR_NO_TOKEN ) { // No impersonation token for the current thread is available. // Let's go for the process token instead. if( !OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, phToken) ) return false; } else return false; } return true;}//-----------------------------------------------------------------------------// Name: enablePrivilege()// Desc: Since a MiniDump contains a lot of meta-data about the OS and // application state at the time of the dump, it is a rather privileged // operation. This means we need to set the SeDebugPrivilege to be able // to call MiniDumpWriteDump.//-----------------------------------------------------------------------------BOOL CMiniDumper::enablePrivilege( LPCTSTR pszPriv, HANDLE hToken, TOKEN_PRIVILEGES* ptpOld ){ BOOL bOk = FALSE; TOKEN_PRIVILEGES tp; tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; bOk = LookupPrivilegeValue( 0, pszPriv, &tp.Privileges[0].Luid ); if( bOk ) { DWORD cbOld = sizeof(*ptpOld); bOk = AdjustTokenPrivileges( hToken, FALSE, &tp, cbOld, ptpOld, &cbOld ); } return (bOk && (ERROR_NOT_ALL_ASSIGNED != GetLastError()));}//-----------------------------------------------------------------------------// Name: restorePrivilege()// Desc: //-----------------------------------------------------------------------------BOOL CMiniDumper::restorePrivilege( HANDLE hToken, TOKEN_PRIVILEGES* ptpOld ){ BOOL bOk = AdjustTokenPrivileges(hToken, FALSE, ptpOld, 0, NULL, NULL); return ( bOk && (ERROR_NOT_ALL_ASSIGNED != GetLastError()) );}//-----------------------------------------------------------------------------// Name: writeMiniDump()// Desc: //-----------------------------------------------------------------------------LONG CMiniDumper::writeMiniDump( _EXCEPTION_POINTERS *pExceptionInfo ){ LONG retval = EXCEPTION_CONTINUE_SEARCH; m_pExceptionInfo = pExceptionInfo; HANDLE hImpersonationToken = NULL; if( !getImpersonationToken( &hImpersonationToken ) ) return FALSE; // You have to find the right dbghelp.dll. // Look next to the EXE first since the one in System32 might be old (Win2k) HMODULE hDll = NULL; TCHAR szDbgHelpPath[MAX_PATH]; if( GetModuleFileName( NULL, m_szAppPath, _MAX_PATH ) ) { TCHAR *pSlash = _tcsrchr( m_szAppPath, '\\' ); if( pSlash ) { _tcscpy( m_szAppBaseName, pSlash + 1); *(pSlash+1) = 0; } _tcscpy( szDbgHelpPath, m_szAppPath ); _tcscat( szDbgHelpPath, _T("DBGHELP.DLL") ); hDll = ::LoadLibrary( szDbgHelpPath ); } if( hDll == NULL ) { // If we haven't found it yet - try one more time. hDll = ::LoadLibrary( _T("DBGHELP.DLL") ); } LPCTSTR szResult = NULL; if( hDll ) { // Get the address of the MiniDumpWriteDump function, which writes // user-mode mini-dump information to a specified file. MINIDUMPWRITEDUMP MiniDumpWriteDump = (MINIDUMPWRITEDUMP)::GetProcAddress( hDll, "MiniDumpWriteDump" ); if( MiniDumpWriteDump != NULL ) { TCHAR szScratch[USER_DATA_BUFFER_SIZE]; setMiniDumpFileName(); // Ask the user if he or she wants to save a mini-dump file... _tcssprintf( szScratch, _T("There was an unexpected error:\n\nWould you ") _T("like to create a mini-dump file?\n\n%s " ), m_szMiniDumpPath); // Create the mini-dump file... HANDLE hFile = ::CreateFile( m_szMiniDumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if( hFile != INVALID_HANDLE_VALUE ) { _MINIDUMP_EXCEPTION_INFORMATION ExInfo; ExInfo.ThreadId = ::GetCurrentThreadId(); ExInfo.ExceptionPointers = pExceptionInfo; ExInfo.ClientPointers = NULL; // We need the SeDebugPrivilege to be able to run MiniDumpWriteDump TOKEN_PRIVILEGES tp; BOOL bPrivilegeEnabled = enablePrivilege( SE_DEBUG_NAME, hImpersonationToken, &tp ); BOOL bOk; // DBGHELP.dll is not thread-safe, so we need to restrict access... EnterCriticalSection( s_pCriticalSection ); { // Write out the mini-dump data to the file... bOk = MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, NULL, NULL ); } LeaveCriticalSection( s_pCriticalSection ); // Restore the privileges when done if( bPrivilegeEnabled ) restorePrivilege( hImpersonationToken, &tp ); if( bOk ) { szResult = NULL; retval = EXCEPTION_EXECUTE_HANDLER; LogError("Fatal error occurred. Wrote dump file: %s.", m_szMiniDumpPath); } else { _tcssprintf( szScratch, _T("Failed to save the mini-dump file to '%s' (error %d)"), m_szMiniDumpPath, GetLastError() ); szResult = szScratch; } ::CloseHandle( hFile ); } else { _tcssprintf( szScratch, _T("Failed to create the mini-dump file '%s' (error %d)"), m_szMiniDumpPath, GetLastError() ); szResult = szScratch; } } else { szResult = _T( "Call to GetProcAddress failed to find MiniDumpWriteDump. ") _T("The DBGHELP.DLL is possibly outdated." ); } } else { szResult = _T( "Call to LoadLibrary failed to find DBGHELP.DLL." ); } if( szResult && m_bPromptUserForMiniDump ) { LogError("%s", szResult); } TerminateProcess( GetCurrentProcess(), 0 ); return retval;}
main.cpp
#include "MiniDumper.h" int main() { CMiniDumper dump(true); char *p=NULL; memcpy(p,"HELLO",strlen("HELLO")); return 0; }
编译环境:Win7_64bit+VS2008
阅读全文
0 0
- Windows程序开发之Dump文件生成
- windows程序崩溃生成dump文件
- windows程序崩溃生成dump文件
- windows程序崩溃生成dump文件
- windows生成dump文件
- windows下程序崩溃,生成dump文件分析
- 程序自动生成Dump文件
- 程序自动生成Dump文件
- 程序自动生成Dump文件
- 让程序生成dump文件
- 程序自动生成Dump文件
- 程序自动生成Dump文件
- 程序自动生成dump文件
- Linux下c/c++开发之程序崩溃(Segment fault)时内核转储文件(core dump)生成设置方法
- windows 平台下 生成Dump文件例子
- Windows下手动生成dump文件
- windows下生成core dump文件
- windows下生成core dump文件
- Freeradius Installation Guide on CentOS 7
- java Quartz定时器任务与Spring task定时的几种实现
- 边界跟踪、边缘检测、边缘连接
- javabean、xml、json、map之间的相互转换
- angular 验证(判断重复)
- Windows程序开发之Dump文件生成
- Mac OneNote 如何保存代码格式
- lebal 标签的 for 属性用法
- HTML笔记
- 2.5 方法、参数和返回值
- 修改其他的Json包为某一固定类型
- Angular1.4.6 & Bootstrap3.3.7搭建后台人员管理系统 1.0.0
- JAVA代码如何设置SPARK的日志打印级别
- Redis-Set类型常用操作命令