//----------------------------------------------------------------------------- // Name: setMiniDumpFileName() // Desc: //----------------------------------------------------------------------------- void KG3DCritDumper::setMiniDumpFileName( void ) { time_t currentTime; time( ¤tTime ); _tcssprintf( m_szMiniDumpPath, _T( "%s%s.%ld.dmp" ), m_szAppPath, m_szAppBaseName, currentTime ); }
// // MiniDumper::WriteMiniDump - Chapter 21, page 814 // LONG MiniDumper::WriteMiniDump(_EXCEPTION_POINTERS *pExceptionInfo ) { time( &m_lTime ); LONG retval = EXCEPTION_CONTINUE_SEARCH; m_pExceptionInfo = pExceptionInfo; // 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) { #ifdef _VS2005_ _tcscpy_s( m_szAppBaseName, pSlash + 1); #else _tcscpy( m_szAppBaseName, pSlash + 1 ); #endif *(pSlash+1) = 0; } #ifdef _VS2005_ _tcscpy_s( szDbgHelpPath, m_szAppPath ); _tcscat_s( szDbgHelpPath, _T("DBGHELP.DLL") ); #else _tcscpy( szDbgHelpPath, m_szAppPath ); _tcscat( szDbgHelpPath, _T("DBGHELP.DLL") ); #endif 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) { MINIDUMPWRITEDUMP pMiniDumpWriteDump = (MINIDUMPWRITEDUMP)::GetProcAddress( hDll, "MiniDumpWriteDump" ); if (pMiniDumpWriteDump) { TCHAR szScratch [USER_DATA_BUFFER_SIZE]; VSetDumpFileName(); // ask the user if they want to save a dump file _tcssprintf(szScratch, _T("There was an unexpected error:\n\n%s\nWould you like to save a diagnostic file?\n\nFilename: %s"), VGetUserMessage(), m_szDumpPath); if (m_bHeadless || (::MessageBox( NULL, szScratch, NULL, MB_YESNO )==IDYES)) { // create the file HANDLE hFile = ::CreateFile( m_szDumpPath, 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; // write the dump BOOL bOK = pMiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, VGetUserStreamArray(), NULL ); if (bOK) { szResult = NULL; retval = EXCEPTION_EXECUTE_HANDLER; } else { _tcssprintf( szScratch, _T("Failed to save dump file to '%s' (error %d)"), m_szDumpPath, GetLastError() ); szResult = szScratch; } ::CloseHandle(hFile); } else { _tcssprintf( szScratch, _T("Failed to create dump file '%s' (error %d)"), m_szDumpPath, GetLastError() ); szResult = szScratch; } } } else { szResult = _T("DBGHELP.DLL too old"); } } else { szResult = _T("DBGHELP.DLL not found"); } if (szResult && !m_bHeadless) ::MessageBox( NULL, szResult, NULL, MB_OK ); TerminateProcess(GetCurrentProcess(), 0); // MLM Note: ExitThread will work, and it allows the MiniDumper to kill a crashed thread // without affecting the rest of the application. The question of the day: // Is That A Good Idea??? Answer: ABSOLUTELY NOT!!!!!!! // //ExitThread(0); return retval; }
//----------------------------------------------------------------------------- // Name: writeMiniDump() // Desc: //----------------------------------------------------------------------------- LONG KG3DCritDumper::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 " "like to create a mini-dump file?\n\n%s " ), m_szMiniDumpPath); if( !m_bPromptUserForMiniDump )//|| (::MessageBox( NULL, szScratch, NULL, MB_YESNO )==IDYES) ) { // 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; } 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. " "The DBGHELP.DLL is possibly outdated." ); } } else { szResult = _T( "Call to LoadLibrary failed to find DBGHELP.DLL." ); } // if( szResult && m_bPromptUserForMiniDump ) // ::MessageBox( NULL, szResult, NULL, MB_OK ); TerminateProcess( GetCurrentProcess(), 0 ); return retval; }
// // MiniDumper::VSetDumpFileName - Chapter 21, page 817 // void MiniDumper::VSetDumpFileName(void) { _tcssprintf(m_szDumpPath, _T("%s%s.%ld.dmp"), m_szAppPath, m_szAppBaseName, m_lTime); }