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 );