Kill all wine processes when doing ExitWindowsEx.

This commit is contained in:
Mike McCormack 2004-10-29 21:26:33 +00:00 committed by Alexandre Julliard
parent 09a2eab38d
commit e1d1d34c9d
1 changed files with 122 additions and 0 deletions

View File

@ -30,6 +30,7 @@
#include "wine/winuser16.h"
#include "winreg.h"
#include "winternl.h"
#include "tlhelp32.h"
#include "user.h"
#include "win.h"
#include "controls.h"
@ -293,6 +294,124 @@ BOOL16 WINAPI ExitWindowsExec16( LPCSTR lpszExe, LPCSTR lpszParams )
}
/***********************************************************************
* USER_GetProcessHandleList(Internal)
*/
static HANDLE *USER_GetProcessHandleList(void)
{
DWORD count, i, n;
HANDLE *list;
PROCESSENTRY32 pe;
HANDLE hSnapshot;
BOOL r;
hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if (!hSnapshot)
{
ERR("cannot create snapshot\n");
return FALSE;
}
/* count the number of processes plus one */
for (count=0; ;count++)
{
pe.dwSize = sizeof pe;
if (count)
r = Process32Next( hSnapshot, &pe );
else
r = Process32First( hSnapshot, &pe );
if (!r)
break;
}
/* allocate memory make a list of the process handles */
list = HeapAlloc( GetProcessHeap(), 0, (count+1)*sizeof(HANDLE) );
n=0;
for (i=0; i<count; i++)
{
pe.dwSize = sizeof pe;
if (i)
r = Process32Next( hSnapshot, &pe );
else
r = Process32First( hSnapshot, &pe );
if (!r)
break;
/* don't kill outselves */
if (GetCurrentProcessId() == pe.th32ProcessID )
continue;
/* open the process so we don't can track it */
list[n] = OpenProcess( PROCESS_QUERY_INFORMATION|
PROCESS_TERMINATE,
FALSE, pe.th32ProcessID );
/* check it didn't terminate already */
if( list[n] )
n++;
}
list[n]=0;
CloseHandle( hSnapshot );
if (!r)
ERR("Error enumerating processes\n");
TRACE("return %lu processes\n", n);
return list;
}
/***********************************************************************
* USER_KillProcesses (Internal)
*/
static DWORD USER_KillProcesses(void)
{
DWORD n, r, i;
HANDLE *handles;
const DWORD dwShutdownTimeout = 10000;
TRACE("terminating other processes\n");
/* kill it and add it to our list of object to wait on */
handles = USER_GetProcessHandleList();
for (n=0; handles && handles[n]; n++)
TerminateProcess( handles[n], 0 );
/* wait for processes to exit */
for (i=0; i<n; i+=MAXIMUM_WAIT_OBJECTS)
{
int n_objs = ((n-i)>MAXIMUM_WAIT_OBJECTS) ? MAXIMUM_WAIT_OBJECTS : (n-i);
r = WaitForMultipleObjects( n_objs, &handles[i], TRUE, dwShutdownTimeout );
if (r==WAIT_TIMEOUT)
ERR("wait failed!\n");
}
/* close the handles */
for (i=0; i<n; i++)
CloseHandle( handles[i] );
HeapFree( GetProcessHeap(), 0, handles );
return n;
}
/***********************************************************************
* USER_DoShutdown (Internal)
*/
static void USER_DoShutdown(void)
{
DWORD i, n;
const DWORD nRetries = 10;
for (i=0; i<nRetries; i++)
{
n = USER_KillProcesses();
TRACE("Killed %ld processes, attempt %ld\n", n, i);
if(!n)
break;
}
}
/***********************************************************************
* ExitWindowsEx (USER32.@)
*/
@ -325,6 +444,9 @@ BOOL WINAPI ExitWindowsEx( UINT flags, DWORD reserved )
}
HeapFree( GetProcessHeap(), 0, list );
/* USER_DoShutdown will kill all processes except the current process */
USER_DoShutdown();
if (result) ExitKernel16();
return TRUE;
}