mdump.cpp

Go to the documentation of this file.
00001 
00002 // #include <stdafx.h>
00003 #include "mdump.h"
00004 
00005 
00006 #include <assert.h>
00007 #include <string.h>
00008 #include <stdio.h>
00009 #include <mbstring.h>
00010 #include <wchar.h>
00011 #include <TCHAR.H>
00012 
00013 #include "../../ascstring.h"
00014 #include "../../strtmesg.h"
00015 
00016 
00017 // because the windows header are polluting the global namespace we can't include basestrm.h :-(
00018 extern int getSearchPathNum();
00019 extern ASCString getSearchPath ( int i );
00020 
00021 LPCSTR MiniDumper::m_szAppName;
00022 
00023 MiniDumper::MiniDumper( LPCSTR szAppName )
00024 {
00025         // if this assert fires then you have two instances of MiniDumper
00026         // which is not allowed
00027         assert( m_szAppName==NULL );
00028 
00029         m_szAppName = szAppName ? strdup(szAppName) : "Application";
00030 
00031         ::SetUnhandledExceptionFilter( TopLevelFilter );
00032 }
00033 
00034 LONG MiniDumper::TopLevelFilter( struct _EXCEPTION_POINTERS *pExceptionInfo )
00035 {
00036         LONG retval = EXCEPTION_CONTINUE_SEARCH;
00037         HWND hParent = NULL;                                            // find a better value for your app
00038 
00039         // firstly see if dbghelp.dll is around and has the function we need
00040         // look next to the EXE first, as the one in System32 might be old 
00041         // (e.g. Windows 2000)
00042         HMODULE hDll = NULL;
00043         char szDbgHelpPath[_MAX_PATH];
00044 
00045         if (GetModuleFileName( NULL, szDbgHelpPath, _MAX_PATH ))
00046         {
00047                 char *pSlash = _tcsrchr( szDbgHelpPath, '\\' );
00048                 if (pSlash)
00049                 {
00050                         _tcscpy( pSlash+1, "DBGHELP.DLL" );
00051                         hDll = ::LoadLibrary( szDbgHelpPath );
00052                 }
00053         }
00054 
00055         if (hDll==NULL)
00056         {
00057                 // load any version we can
00058                 hDll = ::LoadLibrary( "DBGHELP.DLL" );
00059         }
00060 
00061         LPCTSTR szResult = NULL;
00062 
00063         if (hDll)
00064         {
00065                 MINIDUMPWRITEDUMP pDump = (MINIDUMPWRITEDUMP)::GetProcAddress( hDll, "MiniDumpWriteDump" );
00066                 if (pDump)
00067                 {
00068                         char szDumpPath[_MAX_PATH];
00069                         char szScratch [_MAX_PATH];
00070 
00071          if ( getSearchPathNum() ) {
00072                                 _tcscpy( szDumpPath, getSearchPath(0).c_str() );
00073          } else {
00074                            // work out a good place for the dump file
00075                            if (!GetTempPath( _MAX_PATH, szDumpPath ))
00076                                    _tcscpy( szDumpPath, "c:\\temp\\" );
00077          }
00078 
00079                         _tcscat( szDumpPath, getFullVersionString() );
00080                         _tcscat( szDumpPath, m_szAppName );
00081                         _tcscat( szDumpPath, ".dmp" );
00082 
00083                         // ask the user if they want to save a dump file
00084                         // if (::MessageBox( NULL, "ASC has crashed. would you like to save a diagnostic file?", m_szAppName, MB_YESNO )==IDYES)
00085                         if ( true ) {
00086                                 // create the file
00087                                 HANDLE hFile = ::CreateFile( szDumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
00088 
00089                                 if (hFile!=INVALID_HANDLE_VALUE)
00090                                 {
00091                                         _MINIDUMP_EXCEPTION_INFORMATION ExInfo;
00092 
00093                                         ExInfo.ThreadId = ::GetCurrentThreadId();
00094                                         ExInfo.ExceptionPointers = pExceptionInfo;
00095                                         ExInfo.ClientPointers = NULL;
00096 
00097                                         // write the dump
00098                                         BOOL bOK = pDump( GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, NULL, NULL );
00099                                         if (bOK)
00100                                         {
00101                   sprintf( szScratch, "ASC has crashed :-(\nSaved dump file to '%s'\nPlease send it to bugs@asc-hq.org", szDumpPath );
00102                                                 szResult = szScratch;
00103                                                 retval = EXCEPTION_EXECUTE_HANDLER;
00104                                         }
00105                                         else
00106                                         {
00107                                                 sprintf( szScratch, "Failed to save dump file to '%s' (error %d)", szDumpPath, GetLastError() );
00108                                                 szResult = szScratch;
00109                                         }
00110                                         ::CloseHandle(hFile);
00111                          ::MessageBox( NULL, szResult, m_szAppName, MB_OK | MB_ICONERROR );
00112                return retval;
00113                                 }
00114                                 else
00115                                 {
00116                                         sprintf( szScratch, "Failed to create dump file '%s' (error %d)", szDumpPath, GetLastError() );
00117                                         szResult = szScratch;
00118                                 }
00119                         }
00120                 }
00121                 else
00122                 {
00123                         szResult = "DBGHELP.DLL too old";
00124                 ::MessageBox( NULL, szDbgHelpPath, m_szAppName, MB_OK | MB_ICONERROR);
00125               return retval;
00126                 }
00127         }
00128         else
00129         {
00130                 szResult = "DBGHELP.DLL not found";
00131         }
00132 
00133         if (szResult)
00134                 ::MessageBox( NULL, szResult, m_szAppName, MB_OK | MB_ICONERROR );
00135 
00136         return retval;
00137 }

Generated on Mon Jan 5 01:28:22 2009 for Advanced Strategic Command by  doxygen 1.5.1