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