// The code that does the real assertion work. BOOL __stdcall RealAssert ( DWORD dwOverrideOpts , LPCSTR szMsg , BOOL bAllowHalts ) { // The buffer used for the final message text. static char szBuff [ DIAGASSERT_BUFFSIZE ] ; // The current position in szBuff ; LPSTR pCurrPos = szBuff ; // The module name. char szModName[ MAX_PATH + 1 ] ; // The decoded message from FormatMessage LPSTR szFmtMsg = NULL ; // The options. DWORD dwOpts = dwOverrideOpts ; // The last error value. (Which is preserved across the call). DWORD dwLastErr = GetLastError ( ) ; if ( DA_USEDEFAULTS == dwOverrideOpts ) { dwOpts = g_DiagAssertOptions ; } // Look in any specified modules for the code. HINSTVECTOR::iterator loop ; for ( loop = g_HMODVector.begin ( ) ; loop != g_HMODVector.end ( ) ; loop++ ) { if ( 0 != FormatMessageA ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE , *loop , dwLastErr , 0 , (LPSTR)&szFmtMsg , 0 , NULL )) { break ; } } // If the message was not translated, just look in the system. if ( NULL == szFmtMsg ) { FormatMessageA ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM , NULL , dwLastErr , 0 , (LPSTR)&szFmtMsg , 0 , NULL ) ; } // Make sure the message got translated into something. LPSTR szRealLastErr ; if ( NULL != szFmtMsg ) { szRealLastErr = szFmtMsg ; } else { szRealLastErr = "**Last error code does not exist!!!!" ; } // Get the module name. if ( 0 == GetModuleFileNameA ( NULL , szModName , MAX_PATH ) ) { lstrcpy ( szModName , "<unknown application>" ) ; } // Build the message. pCurrPos += (wsprintfA ( szBuff , "Debug Assertion Failed!\n\n" "Program : %s\n" "%s\n" "Last Error (0x%08X) : %s\n" , szModName , szMsg , dwLastErr , szFmtMsg ) ) ; // Get rid of the allocated memory from FormatMessage. if ( NULL != szFmtMsg ) { LocalFree ( (LPVOID)szFmtMsg ) ; } // Am I supposed to show the stack trace too? if ( DA_SHOWSTACKTRACE == ( DA_SHOWSTACKTRACE & dwOpts ) ) { DoStackTrace ( pCurrPos , sizeof ( szBuff ) - ((DWORD)pCurrPos-(DWORD)szBuff) ) ; } // Is this supposed to go to ODS? if ( DA_SHOWODS == ( DA_SHOWODS & dwOpts ) ) { OutputDebugStringA ( szBuff ) ; } // If the file handle is something, write to it. I do not do any // error checking on purpose. if ( INVALID_HANDLE_VALUE != g_hAssertFile ) { DWORD dwWritten ; WriteFile ( g_hAssertFile , szBuff , lstrlenA ( szBuff ) , &dwWritten , NULL ) ; } // Check out the kind of buttons I am supposed to do. UINT uiType = MB_TASKMODAL | MB_SETFOREGROUND | MB_ICONERROR ; if ( TRUE == bAllowHalts ) { uiType |= MB_ABORTRETRYIGNORE ; } else { uiType |= MB_OK ; } // By default, treat the return as an IGNORE. This works best in // the case the user does not want the MessageBox. int iRet = IDIGNORE ; if ( DA_SHOWMSGBOX == ( DA_SHOWMSGBOX & dwOpts ) ) { HWND hWndParent = GetActiveWindow ( ) ; if ( NULL != hWndParent ) { hWndParent = GetLastActivePopup ( hWndParent ) ; } iRet = MessageBoxA ( hWndParent , szBuff , "ASSERTION FAILURE..." , uiType ) ; } // Put the incoming last error back. SetLastError ( dwLastErr ) ; // Figure out what to do on the return. if ( ( IDIGNORE == iRet ) || ( IDOK == iRet ) ) { return ( FALSE ) ; } if ( IDRETRY == iRet ) { // This will trigger DebugBreak!! return ( TRUE ) ; } // The return has to be Abort.... ExitProcess ( (UINT)-1 ) ; return ( TRUE ) ; }
BOOL __stdcall AddDiagAssertModule ( HMODULE hMod ) { g_HMODVector.push_back ( hMod ) ; return ( TRUE ) ; }
BOOL BUGSUTIL_DLLINTERFACE __stdcall AddDiagAssertModule ( HMODULE hMod ) { g_HMODVector.push_back ( hMod ) ; return ( TRUE ) ; }