reman3/Rayman_X/cpa/Appli/BinaryTool2/src/Process.cpp

711 lines
23 KiB
C++
Raw Blame History

#include "stdafx.h"
#include "GlobalData.h"
#include "Process.h"
#include "util.h"
#define C_szUserBreakString "\tUser break.\r\n"
#define C_lTimeIntervalForErrorChecking 2000
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Launch a new process using CreateProcess and return immediatly
// _szExeName contains the name of the executable with FULL PATH.
// Note: _szCommandLine can be NULL.
// return TRUE if process was created normally or FALSE if not.
// Also fill _p_Info with process informations (handle...)
// Display a dialog box to the user in case of error on CreateProcess.
BOOL fn_bSpawnProcess( char *_szExeName, char *_szCommandLine, LPPROCESS_INFORMATION _p_Info )
{
STARTUPINFO stWinInfo;
char szDirectory[512];
CString csMessage;
int iPathLength;
// Spawn process
GetStartupInfo( &stWinInfo );
// Get path of executable
iPathLength = strrchr( _szExeName, '\\' ) - _szExeName;
strncpy( szDirectory, _szExeName, iPathLength );
szDirectory[iPathLength] = 0;
// Create process.
if( ! CreateProcess( _szExeName, _szCommandLine, NULL, NULL, FALSE, 0, NULL, szDirectory, &stWinInfo, _p_Info ) )
{
csMessage = _T("Can't execute '");
csMessage += _szExeName;
csMessage += _T("' !\nMake sure path is correct and executable does exist.");
AfxMessageBox( csMessage, MB_OK | MB_ICONSTOP );
ZeroMemory( _p_Info, sizeof(_p_Info) );
return FALSE;
}
return TRUE;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void fn_vCloseProcessHandles( LPPROCESS_INFORMATION _p_stProcess )
{
if( _p_stProcess->hProcess )
CloseHandle( _p_stProcess->hProcess );
if( _p_stProcess->hThread )
CloseHandle( _p_stProcess->hThread );
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
tdeStatus fn_eSpawnAndWaitForProcess( char *_szExeName, char *_szCommandLine, HANDLE _hEventStop /*= INVALID_HANDLE_VALUE*/ )
{
HANDLE a_hObjectsToWaitFor[2];
int iNbObjectsToWaitFor;
DWORD dwWaitReturn, dwExitCode;
char szMessage[1024];
PROCESS_INFORMATION stProcess;
char szShortExeName[128];
fn_vGetShortExeName( szShortExeName, _szExeName );
// spawn process
if( ! fn_bSpawnProcess( _szExeName, _szCommandLine, &stProcess ) )
{
sprintf( szMessage, "\tError launching %s\r\n", _szExeName );
fn_vOutputLine( szMessage );
fn_vCloseProcessHandles( &stProcess );
return STATUS_C_Error;
}
// Prepare to wait for end of process
iNbObjectsToWaitFor = 0;
a_hObjectsToWaitFor[iNbObjectsToWaitFor++] = stProcess.hProcess;
// Test if we must wait for abort event too.
if( _hEventStop != INVALID_HANDLE_VALUE )
a_hObjectsToWaitFor[iNbObjectsToWaitFor++] = _hEventStop;
do
{
// Wait for process or abort
dwWaitReturn = WaitForMultipleObjects( iNbObjectsToWaitFor, a_hObjectsToWaitFor, FALSE, C_lTimeIntervalForErrorChecking );
// Test if user wants to stop (=abort)
if( iNbObjectsToWaitFor > 1 && (dwWaitReturn == WAIT_OBJECT_0+1 || dwWaitReturn == WAIT_ABANDONED_0+1) )
{
// Ask for confirmation
sprintf( szMessage, "Are you sure you want to terminate '%s' ?", _szExeName );
if( AfxMessageBox( szMessage, MB_YESNO | MB_ICONQUESTION ) == IDYES )
{
// Abort is confirmed, we kill the process
PostThreadMessage( stProcess.dwThreadId, WM_QUIT, 0, NULL );
dwWaitReturn = WaitForSingleObject( stProcess.hProcess, 3500 );
if( dwWaitReturn == WAIT_TIMEOUT )
TerminateProcess( stProcess.hProcess, 199 );
// We exit if process was killed
fn_vCloseProcessHandles( &stProcess );
fn_vOutputLine( C_szUserBreakString );
fn_bCloseSytemErrorDialogBox( szShortExeName, TRUE );
return STATUS_C_UserBreak;
}
else
g_stTheGlobalData.p_oMainDlg -> m_fn_vCancelStopWorkInProgress();
// User does not want to stop anymore, we go for another wait.
ResetEvent( _hEventStop );
}
else if( dwWaitReturn == WAIT_OBJECT_0 || dwWaitReturn == WAIT_ABANDONED_0 )
{
GetExitCodeProcess( stProcess.hProcess, &dwExitCode );
if( dwExitCode != 0 )
{
sprintf( szMessage, "\t'%s' has exited with error code %i\r\n", _szExeName, dwExitCode );
fn_vOutputLine( szMessage );
fn_vCloseProcessHandles( &stProcess );
return STATUS_C_Error;
}
// Process has exited normally. We exit the wait loop.
break;
}
else if( dwWaitReturn == WAIT_TIMEOUT )
{
// Here, the time has come to check if an error occured.
// We try to find and close any system error dialog box related with the exe
if( fn_bCloseSytemErrorDialogBox( szShortExeName ) )
{
// if we found one of these boxes, we kill the process and exit.
TerminateProcess( stProcess.hProcess, 199 );
fn_vCloseProcessHandles( &stProcess );
sprintf( szMessage, "\tError detected with '%s'\r\n", _szExeName );
fn_vOutputLine( szMessage );
return STATUS_C_Error;
}
// We found nothing... We go for another wait.
}
else
{
// Error.
fn_vOutputLine( "\r\n\tInternal error: Error on WaitForMultipleObjects !!!\r\n" );
fn_vCloseProcessHandles( &stProcess );
return STATUS_C_Error;
}
} while( 1 );
fn_vCloseProcessHandles( &stProcess );
// we deal we an enventual dialog box (saying "access violation" or whatever)
if( fn_bCloseSytemErrorDialogBox( szShortExeName ) )
{
// If there was an error dialog box, we return an error.
sprintf( szMessage, "\tError detected with '%s'\r\n", _szExeName );
fn_vOutputLine( szMessage );
return STATUS_C_Error;
}
return STATUS_C_OK;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
tdeStatus fn_eWaitForMultipleProcesses( int _iNbProcesses, LPPROCESS_INFORMATION _pa_stInfo, LPCTSTR _szExeNames[], int *_p_iProcessesEnded )
{
HANDLE a_hObjectsToWaitFor[64];
int i;
DWORD dwWaitReturn, dwExitCode;
char szMessage[1024];
// Prepare to wait for end of process
for( i=0; i<_iNbProcesses; i ++ )
{
a_hObjectsToWaitFor[i] = _pa_stInfo[i].hProcess;
}
// we must also wait for abort event.
a_hObjectsToWaitFor[_iNbProcesses] = g_stTheGlobalData.hEventStop;
// Wait for the end of one process or abort
dwWaitReturn = WaitForMultipleObjects( _iNbProcesses+1, a_hObjectsToWaitFor, FALSE, INFINITE );
// Test if user wants to stop (=abort)
if( dwWaitReturn == WAIT_OBJECT_0+_iNbProcesses || dwWaitReturn == WAIT_ABANDONED_0+_iNbProcesses )
{
// Abort is confirmed, we kill the process
for( i=0; i<_iNbProcesses; i ++ )
{
PostThreadMessage( _pa_stInfo[i].dwThreadId, WM_QUIT, 0, NULL );
}
dwWaitReturn = WaitForMultipleObjects( _iNbProcesses, a_hObjectsToWaitFor, TRUE, 3500 );
if( dwWaitReturn == WAIT_TIMEOUT )
{
for( i=0; i<_iNbProcesses; i ++ )
TerminateProcess( _pa_stInfo[i].hProcess, 199 );
}
// We exit if processes were killed
for( i=0; i<_iNbProcesses; i ++ )
fn_vCloseProcessHandles( &_pa_stInfo[i] );
fn_vOutputLine( C_szUserBreakString );
return STATUS_C_UserBreak;
}
else
{
for( i=0; i<_iNbProcesses; i ++ )
{
if( dwWaitReturn == WAIT_OBJECT_0+i )
{
// Mark witch process has exited.
*_p_iProcessesEnded = i;
GetExitCodeProcess( _pa_stInfo[i].hProcess, &dwExitCode );
fn_vCloseProcessHandles( &_pa_stInfo[i] );
if( dwExitCode != 0 )
{
sprintf( szMessage, "\t'%s' has exited with error code %i\r\n", _szExeNames[i], dwExitCode );
fn_vOutputLine( szMessage );
return STATUS_C_Error;
}
break;
}
}
if( i == _iNbProcesses )
{
// Error.
fn_vOutputLine( "\r\n\tInternal error: Error on WaitForMultipleObjects !!!\r\n" );
for( i=0; i<_iNbProcesses; i ++ )
fn_vCloseProcessHandles( &_pa_stInfo[i] );
return STATUS_C_Error;
}
}
return STATUS_C_OK;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
tdeStatus fn_eSpawnAndWaitForProcessWithTimeout( char *_szExeName, char *_szCommandLine, DWORD _dwMilliseconds /*=INFINITE*/ )
{
HANDLE a_hObjectsToWaitFor[2];
DWORD dwWaitReturn, dwExitCode;
char szMessage[1024];
PROCESS_INFORMATION stProcess;
DWORD dwStartTime = GetTickCount();
DWORD dwElapsedTime = 0;
char szShortExeName[128];
fn_vGetShortExeName( szShortExeName, _szExeName );
// spawn process
if( ! fn_bSpawnProcess( _szExeName, _szCommandLine, &stProcess ) )
{
sprintf( szMessage, "\tError launching %s\r\n", _szExeName );
fn_vOutputLine( szMessage );
fn_vCloseProcessHandles( &stProcess );
return STATUS_C_Error;
}
// Prepare to wait for end of process
a_hObjectsToWaitFor[0] = stProcess.hProcess;
a_hObjectsToWaitFor[1] = g_stTheGlobalData.hEventStop;
do
{
// Wait for process, abort or timeout
// We wait for 1500 millisecond, then we check for a system error dialog box.
dwWaitReturn = WaitForMultipleObjects( 2, a_hObjectsToWaitFor, FALSE, C_lTimeIntervalForErrorChecking );
dwElapsedTime = GetTickCount() - dwStartTime;
// If total time is greater than user timeout, we kill the process
if( dwElapsedTime >= _dwMilliseconds )
{
fn_vOutputLine( "\t*** Timeout! Killing process...***\r\n" );
PostThreadMessage( stProcess.dwThreadId, WM_QUIT, 0, NULL );
dwWaitReturn = WaitForSingleObject( stProcess.hProcess, 1500 );
if( dwWaitReturn == WAIT_TIMEOUT )
TerminateProcess( stProcess.hProcess, 199 );
fn_vCloseProcessHandles( &stProcess );
// Ok, now we deal we an enventual dialog box (saying "acces violation" or whatever)
fn_bCloseSytemErrorDialogBox( szShortExeName, TRUE );
// We exit
return STATUS_C_Error;
}
// Test if user wants to stop (=abort)
if( dwWaitReturn == WAIT_OBJECT_0+1 || dwWaitReturn == WAIT_ABANDONED_0+1 )
{
// Ask for confirmation
sprintf( szMessage, "Are you sure you want to terminate '%s' ?", _szExeName );
if( AfxMessageBox( szMessage, MB_YESNO | MB_ICONQUESTION ) == IDYES )
{
// Abort is confirmed, we kill the process
PostThreadMessage( stProcess.dwThreadId, WM_QUIT, 0, NULL );
dwWaitReturn = WaitForSingleObject( stProcess.hProcess, 3500 );
if( dwWaitReturn == WAIT_TIMEOUT )
TerminateProcess( stProcess.hProcess, 199 );
// We exit if process was killed
fn_vCloseProcessHandles( &stProcess );
fn_vOutputLine( C_szUserBreakString );
// we deal we an enventual dialog box (saying "acces violation" or whatever)
fn_bCloseSytemErrorDialogBox( szShortExeName, TRUE );
return STATUS_C_UserBreak;
}
else
g_stTheGlobalData.p_oMainDlg -> m_fn_vCancelStopWorkInProgress();
// User does not want to stop anymore, we go for another wait.
ResetEvent( g_stTheGlobalData.hEventStop );
}
else if( dwWaitReturn == WAIT_OBJECT_0 || dwWaitReturn == WAIT_ABANDONED_0 )
{
GetExitCodeProcess( stProcess.hProcess, &dwExitCode );
if( dwExitCode != 0 )
{
sprintf( szMessage, "\t'%s' has exited with error code %i\r\n", _szExeName, dwExitCode );
fn_vOutputLine( szMessage );
fn_vCloseProcessHandles( &stProcess );
// we deal we an enventual dialog box (saying "acces violation" or whatever)
fn_bCloseSytemErrorDialogBox( szShortExeName );
return STATUS_C_Error;
}
// Process has exited normally. We exit the wait loop.
break;
}
else if( dwWaitReturn == WAIT_TIMEOUT )
{
// Here, the time has come to check if an error occured.
// We try to find and close any system error dialog box related with the exe
if( fn_bCloseSytemErrorDialogBox( szShortExeName ) )
{
// if we found one of these boxes, we kill the process and exit.
TerminateProcess( stProcess.hProcess, 199 );
fn_vCloseProcessHandles( &stProcess );
sprintf( szMessage, "\tError detected with '%s'\r\n", _szExeName );
fn_vOutputLine( szMessage );
return STATUS_C_Error;
}
// We found nothing... We go for another wait.
}
else
{
// Error.
fn_vOutputLine( "\r\n\tInternal error: Error on WaitForMultipleObjects !!!\r\n" );
fn_vCloseProcessHandles( &stProcess );
return STATUS_C_Error;
}
} while( 1 );
fn_vCloseProcessHandles( &stProcess );
// we deal we an enventual dialog box (saying "access violation" or whatever)
if( fn_bCloseSytemErrorDialogBox( szShortExeName ) )
{
// If there was an error dialog box, we return an error.
sprintf( szMessage, "\tError detected with '%s'\r\n", _szExeName );
fn_vOutputLine( szMessage );
return STATUS_C_Error;
}
return STATUS_C_OK;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
tdeStatus fn_eSpawnAndWaitForProcessWithInputEvents( char *_szExeName, char *_szCommandLine )
{
HANDLE a_hObjectsToWaitFor[32];
DWORD dwWaitReturn, dwExitCode;
char szMessage[1024];
PROCESS_INFORMATION stProcess;
MSG stMsg;
char szShortExeName[128];
fn_vGetShortExeName( szShortExeName, _szExeName );
// spawn process
if( ! fn_bSpawnProcess( _szExeName, _szCommandLine, &stProcess ) )
{
sprintf( szMessage, "\tError launching %s\r\n", _szExeName );
fn_vOutputLine( szMessage );
fn_vCloseProcessHandles( &stProcess );
return STATUS_C_Error;
}
// Prepare to wait for end of process
a_hObjectsToWaitFor[0] = stProcess.hProcess;
a_hObjectsToWaitFor[1] = g_stTheGlobalData.hEventStop;
do
{
// Wait for process or abort
dwWaitReturn = MsgWaitForMultipleObjects( 2, a_hObjectsToWaitFor, FALSE, C_lTimeIntervalForErrorChecking, QS_ALLINPUT );
// Test if user wants to stop (=abort)
if( dwWaitReturn == WAIT_OBJECT_0+1 || dwWaitReturn == WAIT_ABANDONED_0+1 )
{
// Ask for confirmation
sprintf( szMessage, "Are you sure you want to terminate '%s' ?", _szExeName );
if( AfxMessageBox( szMessage, MB_YESNO | MB_ICONQUESTION ) == IDYES )
{
// Abort is confirmed, we kill the process
PostThreadMessage( stProcess.dwThreadId, WM_QUIT, 0, NULL );
dwWaitReturn = WaitForSingleObject( stProcess.hProcess, 3500 );
if( dwWaitReturn == WAIT_TIMEOUT )
TerminateProcess( stProcess.hProcess, 199 );
// We exit if process was killed
fn_vCloseProcessHandles( &stProcess );
fn_bCloseSytemErrorDialogBox( szShortExeName, TRUE );
fn_vOutputLine( C_szUserBreakString );
return STATUS_C_UserBreak;
}
else
g_stTheGlobalData.p_oMainDlg -> m_fn_vCancelStopWorkInProgress();
// User does not want to stop anymore, we go for another wait.
ResetEvent( g_stTheGlobalData.hEventStop );
}
else if( dwWaitReturn == WAIT_OBJECT_0 || dwWaitReturn == WAIT_ABANDONED_0 )
{
GetExitCodeProcess( stProcess.hProcess, &dwExitCode );
if( dwExitCode != 0 )
{
sprintf( szMessage, "\t'%s' has exited with error code %i\r\n", _szExeName, dwExitCode );
fn_vOutputLine( szMessage );
fn_vCloseProcessHandles( &stProcess );
return STATUS_C_Error;
}
// Process has exited normally. We exit the wait loop.
break;
}
else if( dwWaitReturn == WAIT_OBJECT_0 + 2 )
{
// Else, a user event has arrived: treat it.
while( PeekMessage( &stMsg, g_stTheGlobalData.p_oMainDlg -> m_hWnd, 0, 0, PM_REMOVE ) )
if( ! g_stTheGlobalData.p_oMainDlg -> PreTranslateMessage( &stMsg ) )
DispatchMessage( &stMsg );
}
else if( dwWaitReturn == WAIT_TIMEOUT )
{
// Here, the time has come to check if an error occured.
// We try to find and close any system error dialog box related with the exe
if( fn_bCloseSytemErrorDialogBox( szShortExeName ) )
{
// if we found one of these boxes, we kill the process and exit.
TerminateProcess( stProcess.hProcess, 199 );
fn_vCloseProcessHandles( &stProcess );
sprintf( szMessage, "\tError detected with '%s'\r\n", _szExeName );
fn_vOutputLine( szMessage );
return STATUS_C_Error;
}
// We found nothing... We go for another wait.
}
else
{
// Error.
fn_vOutputLine( "\r\n\tInternal error: Error on MsgWaitForMultipleObjects !!!\r\n" );
fn_vCloseProcessHandles( &stProcess );
return STATUS_C_Error;
}
} while( 1 );
fn_vCloseProcessHandles( &stProcess );
// we deal we an enventual dialog box (saying "access violation" or whatever)
if( fn_bCloseSytemErrorDialogBox( szShortExeName ) )
{
// If there was an error dialog box, we return an error.
sprintf( szMessage, "\tError detected with '%s'\r\n", _szExeName );
fn_vOutputLine( szMessage );
return STATUS_C_Error;
}
return STATUS_C_OK;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
tdeStatus fn_eSpawnThreadAndWaitWithInputEvents( AFX_THREADPROC _p_fn_uiThread, LPVOID _p_vParamForThread )
{
HANDLE a_hEvents[64];
DWORD dwWaitReturn;
MSG stMessage;
DWORD dwExitCode = 0;
CWinThread *p_oThread = AfxBeginThread( _p_fn_uiThread, _p_vParamForThread );
if( p_oThread == NULL )
{
AfxMessageBox( "Unable to create thread !.", MB_OK | MB_ICONEXCLAMATION );
return STATUS_C_Error;
}
// Disable autodelete (to use handle to thread after it is terminated).
p_oThread->m_bAutoDelete = FALSE;
// Now, we enter wait loop that wait either for thread end or for input message
a_hEvents[0] = p_oThread->m_hThread;
while( 1 )
{
dwWaitReturn = MsgWaitForMultipleObjects( 1, a_hEvents, FALSE, INFINITE, QS_ALLINPUT );
// If an input event has arrived, we dispatch it.
if( dwWaitReturn == WAIT_OBJECT_0 + 1 )
{
while( PeekMessage( &stMessage, g_stTheGlobalData.p_oMainDlg->m_hWnd, 0, 0, PM_REMOVE ) )
if( g_stTheGlobalData.p_oMainDlg -> PreTranslateMessage( &stMessage ) == 0 )
DispatchMessage( &stMessage );
}
// if thread has exited
else if( dwWaitReturn == WAIT_OBJECT_0 || dwWaitReturn == WAIT_ABANDONED_0 )
{
break;
}
else
{
// Error.
TCHAR szMessage[1024];
::FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
szMessage, 1024, NULL );
fn_vOutputLine( "\r\n\tInternal error: Error on MsgWaitForMultipleObjects :\r\n\t" );
fn_vOutputLine( szMessage );
fn_vOutputLine( "\r\n" );
delete p_oThread;
return STATUS_C_Error;
}
}
GetExitCodeThread( p_oThread->m_hThread, &dwExitCode );
// if( dwExitCode == STATUS_C_UserBreak )
// fn_vOutputLine( C_szUserBreakString );
delete p_oThread;
return (tdeStatus)dwExitCode;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
typedef struct tdstEnumWinStruct_
{
char *p_szExeName;
BOOL bActionDone;
UINT uiNumberOfButton;
} tdstEnumWinStruct;
// Callback to enumerate all controls in a window.
BOOL CALLBACK EnumChildWindowProc( HWND _hwnd, LPARAM _p_stParam )
{
char szTitle[512];
tdstEnumWinStruct *p_stEnumChild = (tdstEnumWinStruct *)_p_stParam;
DWORD dwID = GetClassLong( _hwnd, GCW_ATOM );
// We only check statics
switch( dwID )
{
case 0xC01B :
GetWindowText( _hwnd, szTitle, 512 );
// Check if caption contains the name of the exe
if( stristr( szTitle, p_stEnumChild->p_szExeName ) != NULL )
{
// Name is detected
p_stEnumChild->bActionDone = TRUE;
}
break;
case 0xC015:
p_stEnumChild->uiNumberOfButton++;
break;
default:
break;
}
return TRUE;
}
BOOL fn_bCheckWindow( HWND _hMessageBox, char *_szString, UINT *_p_uiNbButtons = NULL )
{
tdstEnumWinStruct stEnumChild;
stEnumChild.p_szExeName = _szString;
stEnumChild.bActionDone = FALSE;
stEnumChild.uiNumberOfButton = 0;
// Search in controls if one of them contains the given string
EnumChildWindows( _hMessageBox, EnumChildWindowProc, (LPARAM)&stEnumChild );
if( _p_uiNbButtons )
*_p_uiNbButtons = stEnumChild.uiNumberOfButton;
return stEnumChild.bActionDone;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Callback to enumerate all windows.
// (called by fn_bCloseSytemErrorDialogBox)
BOOL CALLBACK EnumWindowProc( HWND _hwnd, LPARAM _p_stParam )
{
char szTitle[512];
DWORD dwID = GetClassLong( _hwnd, GCW_ATOM );
tdstEnumWinStruct *p_stEnumWin = (tdstEnumWinStruct *)_p_stParam;
UINT uiNbButtons;
GetWindowText( _hwnd, szTitle, 512 );
// If window is a dialog box
if( dwID == 0x8002 )
{
// Check if it's an "application error" box.
if( stristr( szTitle, p_stEnumWin->p_szExeName )
&& (stristr( szTitle, "erreur d'application" ) || stristr( szTitle, "application error" )) )
{
// Now, we close that box !
::PostMessage( _hwnd, WM_CLOSE, 0, 0 );
p_stEnumWin->bActionDone = TRUE;
// Return FALSE to stop enumeration
return FALSE;
}
// Else, it may be an assert box.
else if( (stristr( szTitle, "Debug Lib" ) || stristr( szTitle, "Runtime Lib" ))
&& fn_bCheckWindow( _hwnd, "??" )
&& fn_bCheckWindow( _hwnd, p_stEnumWin->p_szExeName, &uiNbButtons )
&& uiNbButtons == 3 )
{
::PostMessage( _hwnd, WM_CLOSE, 0, 0 );
p_stEnumWin->bActionDone = TRUE;
// Return FALSE to stop enumeration
return FALSE;
}
// Check if it's an "illegal operation" box.
else
{
char *p_szExtension = strrchr( p_stEnumWin->p_szExeName, '.' );
if( p_szExtension ) *p_szExtension = 0;
if( stristr( szTitle, p_stEnumWin->p_szExeName )
&& fn_bCheckWindow( _hwnd, "Op<EFBFBD>ration non conforme", &uiNbButtons )
&& uiNbButtons >= 2 && uiNbButtons < 4 )
{
// Now, we close that box !
::PostMessage( _hwnd, WM_CLOSE, 0, 0 );
p_stEnumWin->bActionDone = TRUE;
// Return FALSE to stop enumeration
return FALSE;
}
if( p_szExtension ) *p_szExtension = '.';
}
}
// We also handle dr watson's windows...
else if( stristr( szTitle, "Watson" ) != NULL )
{
// Check if this dr. Watson's window talks about us !
if( fn_bCheckWindow( _hwnd, p_stEnumWin->p_szExeName ) )
{
::PostMessage( _hwnd, WM_CLOSE, 0, 0 );
p_stEnumWin->bActionDone = TRUE;
// Return FALSE to stop enumeration
return FALSE;
}
}
// Window not found, we continue
return TRUE;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Get all windows, check if this is a system or dr. watson's window
// and it is related to ExeName, then eventually close it.
// Return TRUE if a window was closed, FALSE otherwise.
BOOL fn_bCloseSytemErrorDialogBox( char *_szExeName, BOOL bForceClose /*=FALSE*/)
{
tdstEnumWinStruct stEnumWin;
if( ! g_stTheGlobalData.bAutoDetectErrors && ! bForceClose )
return FALSE;
stEnumWin.p_szExeName = _szExeName;
stEnumWin.bActionDone = FALSE;
EnumWindows( EnumWindowProc, (LPARAM)&stEnumWin );
return stEnumWin.bActionDone;
}