18#include "MiniDumper.h"
23 #define _tcssprintf wsprintf
24 #define tcsplitpath _wsplitpath
26 #define _tcssprintf sprintf
27 #define tcsplitpath _splitpath
30const int USER_DATA_BUFFER_SIZE = 4096;
35CMiniDumper* CMiniDumper::s_pMiniDumper = NULL;
36LPCRITICAL_SECTION CMiniDumper::s_pCriticalSection = NULL;
39typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess,
42 MINIDUMP_TYPE DumpType,
43 CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
44 CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
45 CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
51CMiniDumper::CMiniDumper(
bool bPromptUserForMiniDump )
54 assert( !s_pMiniDumper );
57 m_bPromptUserForMiniDump = bPromptUserForMiniDump;
65 ::SetUnhandledExceptionFilter( unhandledExceptionHandler );
73 s_pCriticalSection =
new CRITICAL_SECTION;
75 if( s_pCriticalSection )
76 InitializeCriticalSection( s_pCriticalSection );
83CMiniDumper::~CMiniDumper(
void )
85 if( s_pCriticalSection )
87 DeleteCriticalSection( s_pCriticalSection );
88 delete s_pCriticalSection;
96LONG CMiniDumper::unhandledExceptionHandler( _EXCEPTION_POINTERS *pExceptionInfo )
99 return EXCEPTION_CONTINUE_SEARCH;
101 return s_pMiniDumper->writeMiniDump( pExceptionInfo );
108void CMiniDumper::setMiniDumpFileName(
void )
111 time( ¤tTime );
113 wsprintf( m_szMiniDumpPath,
126bool CMiniDumper::getImpersonationToken( HANDLE* phToken )
130 if( !OpenThreadToken( GetCurrentThread(),
131 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
135 if( GetLastError() == ERROR_NO_TOKEN )
139 if( !OpenProcessToken( GetCurrentProcess(),
140 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
158BOOL CMiniDumper::enablePrivilege( LPCTSTR pszPriv, HANDLE hToken, TOKEN_PRIVILEGES* ptpOld )
163 tp.PrivilegeCount = 1;
164 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
165 bOk = LookupPrivilegeValue( 0, pszPriv, &tp.Privileges[0].Luid );
169 DWORD cbOld =
sizeof(*ptpOld);
170 bOk = AdjustTokenPrivileges( hToken, FALSE, &tp, cbOld, ptpOld, &cbOld );
173 return (bOk && (ERROR_NOT_ALL_ASSIGNED != GetLastError()));
180BOOL CMiniDumper::restorePrivilege( HANDLE hToken, TOKEN_PRIVILEGES* ptpOld )
182 BOOL bOk = AdjustTokenPrivileges(hToken, FALSE, ptpOld, 0, NULL, NULL);
183 return ( bOk && (ERROR_NOT_ALL_ASSIGNED != GetLastError()) );
190LONG CMiniDumper::writeMiniDump( _EXCEPTION_POINTERS *pExceptionInfo )
192 LONG retval = EXCEPTION_CONTINUE_SEARCH;
193 m_pExceptionInfo = pExceptionInfo;
195 HANDLE hImpersonationToken = NULL;
196 if( !getImpersonationToken( &hImpersonationToken ) )
203 TCHAR szDbgHelpPath[MAX_PATH];
205 if( GetModuleFileName( NULL, m_szAppPath, _MAX_PATH ) )
207 TCHAR *pSlash = wcsrchr( m_szAppPath,
'\\' );
211 _tcscpy_s( m_szAppBaseName, pSlash + 1);
215 wcscpy_s( szDbgHelpPath, m_szAppPath );
216 wcscat_s( szDbgHelpPath, L
"DBGHELP.DLL");
217 hDll = ::LoadLibrary( szDbgHelpPath );
223 hDll = ::LoadLibrary( L
"DBGHELP.DLL");
226 LPCTSTR szResult = NULL;
232 MINIDUMPWRITEDUMP MiniDumpWriteDump =
233 (MINIDUMPWRITEDUMP)::GetProcAddress( hDll,
"MiniDumpWriteDump" );
235 if( MiniDumpWriteDump != NULL )
237 TCHAR szScratch[USER_DATA_BUFFER_SIZE];
239 setMiniDumpFileName();
243 L
"There was an unexpected error:\n\nWould you "
244 L
"like to create a mini-dump file?\n\n%s ",
248 HANDLE hFile = ::CreateFile( m_szMiniDumpPath,
253 FILE_ATTRIBUTE_NORMAL,
256 if( hFile != INVALID_HANDLE_VALUE )
258 _MINIDUMP_EXCEPTION_INFORMATION ExInfo;
259 ExInfo.ThreadId = ::GetCurrentThreadId();
260 ExInfo.ExceptionPointers = pExceptionInfo;
261 ExInfo.ClientPointers = NULL;
265 BOOL bPrivilegeEnabled = enablePrivilege( SE_DEBUG_NAME, hImpersonationToken, &tp );
270 EnterCriticalSection( s_pCriticalSection );
273 bOk = MiniDumpWriteDump( GetCurrentProcess(),
274 GetCurrentProcessId(),
281 LeaveCriticalSection( s_pCriticalSection );
284 if( bPrivilegeEnabled )
285 restorePrivilege( hImpersonationToken, &tp );
290 retval = EXCEPTION_EXECUTE_HANDLER;
295 L
"Failed to save the mini-dump file to '%s' (error %d)",
299 szResult = szScratch;
302 ::CloseHandle( hFile );
307 L
"Failed to create the mini-dump file '%s' (error %d)",
311 szResult = szScratch;
316 szResult = L
"Call to GetProcAddress failed to find MiniDumpWriteDump. "
317 L
"The DBGHELP.DLL is possibly outdated." ;
322 szResult = L
"Call to LoadLibrary failed to find DBGHELP.DLL.";
325 if(m_bPromptUserForMiniDump)
328 ::MessageBox( NULL, szResult, NULL, MB_OK );
332 wsprintf(msg, _T(
"I'm Sorry, Application is Crash! The path: %s"), m_szMiniDumpPath);
333 ::MessageBox(NULL, msg, _T(
"Application Error"), MB_OK);
337 TerminateProcess( GetCurrentProcess(), 0 );