USER32: kill all wine processes when doing ExitWindowsEx (take 3)
Mike McCormack
mike at codeweavers.com
Thu Oct 28 22:26:30 CDT 2004
Reduced "complexity" by eliminating the list of process ids and only
keeping a list of process handles.
Mike
ChangeLog:
* kill all wine processes when doing ExitWindowsEx
-------------- next part --------------
Index: windows/user.c
===================================================================
RCS file: /home/wine/wine/windows/user.c,v
retrieving revision 1.101
diff -u -r1.101 user.c
--- windows/user.c 5 Mar 2004 20:44:15 -0000 1.101
+++ windows/user.c 29 Oct 2004 03:18:14 -0000
@@ -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"
@@ -294,6 +295,126 @@
/***********************************************************************
+ * 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++)
+ {
+ memset( &pe, 0, sizeof pe );
+ 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++)
+ {
+ memset( &pe, 0, sizeof pe );
+ 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.@)
*/
BOOL WINAPI ExitWindowsEx( UINT flags, DWORD reserved )
@@ -325,6 +446,9 @@
}
HeapFree( GetProcessHeap(), 0, list );
+ /* USER_DoShutdown will kill all processes except the current process */
+ USER_DoShutdown();
+
if (result) ExitKernel16();
return TRUE;
}
More information about the wine-patches
mailing list