15#include "MiniDumper.h"
20 #define _tcssprintf wsprintf
21 #define tcsplitpath _wsplitpath
23 #define _tcssprintf sprintf
24 #define tcsplitpath _splitpath
27const int USER_DATA_BUFFER_SIZE = 4096;
32CMiniDumper* CMiniDumper::s_pMiniDumper = NULL;
33LPCRITICAL_SECTION CMiniDumper::s_pCriticalSection = NULL;
36typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess,
39 MINIDUMP_TYPE DumpType,
40 CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
41 CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
42 CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
48CMiniDumper::CMiniDumper(
bool bPromptUserForMiniDump )
51 assert( !s_pMiniDumper );
54 m_bPromptUserForMiniDump = bPromptUserForMiniDump;
62 ::SetUnhandledExceptionFilter( unhandledExceptionHandler );
70 s_pCriticalSection =
new CRITICAL_SECTION;
72 if( s_pCriticalSection )
73 InitializeCriticalSection( s_pCriticalSection );
80CMiniDumper::~CMiniDumper(
void )
82 if( s_pCriticalSection )
84 DeleteCriticalSection( s_pCriticalSection );
85 delete s_pCriticalSection;
93LONG CMiniDumper::unhandledExceptionHandler( _EXCEPTION_POINTERS *pExceptionInfo )
96 return EXCEPTION_CONTINUE_SEARCH;
98 return s_pMiniDumper->writeMiniDump( pExceptionInfo );
105void CMiniDumper::setMiniDumpFileName(
void )
108 time( ¤tTime );
110 wsprintf( m_szMiniDumpPath,
123bool CMiniDumper::getImpersonationToken( HANDLE* phToken )
127 if( !OpenThreadToken( GetCurrentThread(),
128 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
132 if( GetLastError() == ERROR_NO_TOKEN )
136 if( !OpenProcessToken( GetCurrentProcess(),
137 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
155BOOL CMiniDumper::enablePrivilege( LPCTSTR pszPriv, HANDLE hToken, TOKEN_PRIVILEGES* ptpOld )
160 tp.PrivilegeCount = 1;
161 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
162 bOk = LookupPrivilegeValue( 0, pszPriv, &tp.Privileges[0].Luid );
166 DWORD cbOld =
sizeof(*ptpOld);
167 bOk = AdjustTokenPrivileges( hToken, FALSE, &tp, cbOld, ptpOld, &cbOld );
170 return (bOk && (ERROR_NOT_ALL_ASSIGNED != GetLastError()));
177BOOL CMiniDumper::restorePrivilege( HANDLE hToken, TOKEN_PRIVILEGES* ptpOld )
179 BOOL bOk = AdjustTokenPrivileges(hToken, FALSE, ptpOld, 0, NULL, NULL);
180 return ( bOk && (ERROR_NOT_ALL_ASSIGNED != GetLastError()) );
187LONG CMiniDumper::writeMiniDump( _EXCEPTION_POINTERS *pExceptionInfo )
189 LONG retval = EXCEPTION_CONTINUE_SEARCH;
190 m_pExceptionInfo = pExceptionInfo;
192 HANDLE hImpersonationToken = NULL;
193 if( !getImpersonationToken( &hImpersonationToken ) )
200 TCHAR szDbgHelpPath[MAX_PATH];
202 if( GetModuleFileName( NULL, m_szAppPath, _MAX_PATH ) )
204 TCHAR *pSlash = wcsrchr( m_szAppPath,
'\\' );
208 _tcscpy_s( m_szAppBaseName, pSlash + 1);
212 wcscpy_s( szDbgHelpPath, m_szAppPath );
213 wcscat_s( szDbgHelpPath, L
"DBGHELP.DLL");
214 hDll = ::LoadLibrary( szDbgHelpPath );
220 hDll = ::LoadLibrary( L
"DBGHELP.DLL");
223 LPCTSTR szResult = NULL;
229 MINIDUMPWRITEDUMP MiniDumpWriteDump =
230 (MINIDUMPWRITEDUMP)::GetProcAddress( hDll,
"MiniDumpWriteDump" );
232 if( MiniDumpWriteDump != NULL )
234 TCHAR szScratch[USER_DATA_BUFFER_SIZE];
236 setMiniDumpFileName();
240 L
"There was an unexpected error:\n\nWould you "
241 L
"like to create a mini-dump file?\n\n%s ",
245 HANDLE hFile = ::CreateFile( m_szMiniDumpPath,
250 FILE_ATTRIBUTE_NORMAL,
253 if( hFile != INVALID_HANDLE_VALUE )
255 _MINIDUMP_EXCEPTION_INFORMATION ExInfo;
256 ExInfo.ThreadId = ::GetCurrentThreadId();
257 ExInfo.ExceptionPointers = pExceptionInfo;
258 ExInfo.ClientPointers = NULL;
262 BOOL bPrivilegeEnabled = enablePrivilege( SE_DEBUG_NAME, hImpersonationToken, &tp );
267 EnterCriticalSection( s_pCriticalSection );
270 bOk = MiniDumpWriteDump( GetCurrentProcess(),
271 GetCurrentProcessId(),
278 LeaveCriticalSection( s_pCriticalSection );
281 if( bPrivilegeEnabled )
282 restorePrivilege( hImpersonationToken, &tp );
287 retval = EXCEPTION_EXECUTE_HANDLER;
292 L
"Failed to save the mini-dump file to '%s' (error %d)",
296 szResult = szScratch;
299 ::CloseHandle( hFile );
304 L
"Failed to create the mini-dump file '%s' (error %d)",
308 szResult = szScratch;
313 szResult = L
"Call to GetProcAddress failed to find MiniDumpWriteDump. "
314 L
"The DBGHELP.DLL is possibly outdated." ;
319 szResult = L
"Call to LoadLibrary failed to find DBGHELP.DLL.";
322 if(m_bPromptUserForMiniDump)
325 ::MessageBox( NULL, szResult, NULL, MB_OK );
329 wsprintf(msg, _T(
"I'm Sorry, Application is Crash! The path: %s"), m_szMiniDumpPath);
330 ::MessageBox(NULL, msg, _T(
"Application Error"), MB_OK);
334 TerminateProcess( GetCurrentProcess(), 0 );