711 lines
23 KiB
C++
711 lines
23 KiB
C++
#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;
|
||
}
|
||
|