[PATCH v2] taskmgr/endproc.c: Implement ProcessPage_OnEndProcessTree()

Akarsha Sehwag akarsha15010 at iiitd.ac.in
Sat Apr 29 17:08:19 CDT 2017


Fixes https://bugs.winehq.org/show_bug.cgi?id=39640

Implemented ProcessPage_OnEndProcessTree(). It now kills all the child processes along with the specified process.

Signed-off-by: Akarsha Sehwag <akarsha15010 at iiitd.ac.in>
---
 programs/taskmgr/endproc.c | 125 +++++++++++++++++++++++++++++++++++++--------
 1 file changed, 105 insertions(+), 20 deletions(-)

diff --git a/programs/taskmgr/endproc.c b/programs/taskmgr/endproc.c
index 89c2d7b..60df0d7 100644
--- a/programs/taskmgr/endproc.c
+++ b/programs/taskmgr/endproc.c
@@ -31,11 +31,18 @@
 #include "wine/unicode.h"
 #include "taskmgr.h"
 #include "perfdata.h"
+#include "tlhelp32.h"
 
 static WCHAR wszWarnMsg[511];
 static WCHAR wszWarnTitle[255];
 static WCHAR wszUnable2Terminate[255];
 
+typedef struct process_list {
+    DWORD       *pid;
+    SIZE_T      count;      /* index to maintain the last entry of the array */
+    SIZE_T      size;
+} process_list;
+
 static void load_message_strings(void)
 {
     LoadStringW(hInst, IDS_TERMINATE_MESSAGE, wszWarnMsg, sizeof(wszWarnMsg)/sizeof(WCHAR));
@@ -43,6 +50,22 @@ static void load_message_strings(void)
     LoadStringW(hInst, IDS_WARNING_TITLE, wszWarnTitle, sizeof(wszWarnTitle)/sizeof(WCHAR));
 }
 
+static void kill_process(HANDLE hProcess, WCHAR *wstrErrorText)
+{
+    if (!hProcess)
+    {
+        GetLastErrorText(wstrErrorText, sizeof(wstrErrorText)/sizeof(WCHAR));
+        MessageBoxW(hMainWnd, wstrErrorText, wszUnable2Terminate, MB_OK|MB_ICONSTOP);
+        return;
+    }
+
+    if (!TerminateProcess(hProcess, 0))
+    {
+        GetLastErrorText(wstrErrorText, sizeof(wstrErrorText)/sizeof(WCHAR));
+        MessageBoxW(hMainWnd, wstrErrorText, wszUnable2Terminate, MB_OK|MB_ICONSTOP);
+    }
+}    
+
 void ProcessPage_OnEndProcess(void)
 {
     LVITEMW          lvitem;
@@ -54,7 +77,7 @@ void ProcessPage_OnEndProcess(void)
     load_message_strings();
 
     Count = SendMessageW(hProcessPageListCtrl, LVM_GETITEMCOUNT, 0, 0);
-    for (Index=0; Index<Count; Index++)
+    for (Index=0; Index < Count; Index++)
     {
         lvitem.mask = LVIF_STATE;
         lvitem.stateMask = LVIS_SELECTED;
@@ -77,20 +100,68 @@ void ProcessPage_OnEndProcess(void)
 
     hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, dwProcessId);
 
-    if (!hProcess)
+    kill_process(hProcess, wstrErrorText);
+    CloseHandle(hProcess);
+}
+
+static BOOL init_process_list(process_list *list)
+{
+    list->size = 4;            /* initialise size with 4. Will increase if necessary */
+    list->pid = HeapAlloc(GetProcessHeap(), 0, list->size * sizeof(*list->pid));
+    list->count = 0;
+
+    return list->pid != NULL;
+}
+
+static BOOL process_list_append(process_list *list, DWORD id)
+{
+    INT *temp;
+    if (list->count == list->size)
     {
-        GetLastErrorText(wstrErrorText, sizeof(wstrErrorText)/sizeof(WCHAR));
-        MessageBoxW(hMainWnd, wstrErrorText,wszUnable2Terminate, MB_OK|MB_ICONSTOP);
-        return;
+        list->size *= 2;
+        temp = HeapReAlloc(GetProcessHeap(), 0, list->pid, list->size * sizeof(*list->pid));
+        if(!temp)
+            return FALSE;
+        
+        list->pid = temp;
     }
+    list->pid[list->count++] = id;
+    return TRUE;
+}   
 
-    if (!TerminateProcess(hProcess, 0))
+static void free_process_list(process_list *list)
+{
+    HeapFree(GetProcessHeap(), 0, list->pid);
+}
+
+static void enum_process_children(HANDLE snapshot, process_list *list, DWORD pid) 
+{
+    PROCESSENTRY32 entry;
+    SIZE_T start, end, i;
+    
+    start = list->count;
+    entry.dwSize = sizeof(entry);
+
+    if(!Process32First(snapshot, &entry))
+        return;
+
+    do 
+    {   
+        if(entry.th32ParentProcessID == pid)
+        {
+            if(!process_list_append(list, entry.th32ProcessID))
+            {
+                free_process_list(list);
+                return;
+            }
+        }
+    } while (Process32Next(snapshot, &entry));
+
+    end = list->count;
+    for (i = start; i < end; ++i)
     {
-        GetLastErrorText(wstrErrorText, sizeof(wstrErrorText)/sizeof(WCHAR));
-        MessageBoxW(hMainWnd, wstrErrorText,wszUnable2Terminate, MB_OK|MB_ICONSTOP);
+        enum_process_children(snapshot, list, list->pid[i]);
     }
-
-    CloseHandle(hProcess);
 }
 
 void ProcessPage_OnEndProcessTree(void)
@@ -100,11 +171,14 @@ void ProcessPage_OnEndProcessTree(void)
     DWORD            dwProcessId;
     HANDLE           hProcess;
     WCHAR            wstrErrorText[256];
+    process_list     list;
+    SIZE_T           i;
+    HANDLE           snapshot;
 
     load_message_strings();
 
     Count = SendMessageW(hProcessPageListCtrl, LVM_GETITEMCOUNT, 0, 0);
-    for (Index=0; Index<Count; Index++)
+    for (Index = 0; Index < Count; Index++)
     {
         lvitem.mask = LVIF_STATE;
         lvitem.stateMask = LVIS_SELECTED;
@@ -116,7 +190,6 @@ void ProcessPage_OnEndProcessTree(void)
         if (lvitem.state & LVIS_SELECTED)
             break;
     }
-
     Count = SendMessageW(hProcessPageListCtrl, LVM_GETSELECTEDCOUNT, 0, 0);
     dwProcessId = PerfDataGetProcessId(Index);
     if ((Count != 1) || (dwProcessId == 0))
@@ -125,20 +198,32 @@ void ProcessPage_OnEndProcessTree(void)
     if (MessageBoxW(hMainWnd, wszWarnMsg, wszWarnTitle, MB_YESNO|MB_ICONWARNING) != IDYES)
         return;
 
-    hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, dwProcessId);
+    if (!init_process_list(&list))
+        return;
 
-    if (!hProcess)
+    if (!process_list_append(&list, dwProcessId))
     {
-        GetLastErrorText(wstrErrorText, sizeof(wstrErrorText)/sizeof(WCHAR));
-        MessageBoxW(hMainWnd, wstrErrorText,wszUnable2Terminate, MB_OK|MB_ICONSTOP);
+        free_process_list(&list);
         return;
     }
 
-    if (!TerminateProcess(hProcess, 0))
+    snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+
+    if (snapshot == INVALID_HANDLE_VALUE)
     {
-        GetLastErrorText(wstrErrorText, sizeof(wstrErrorText)/sizeof(WCHAR));
-        MessageBoxW(hMainWnd, wstrErrorText,wszUnable2Terminate, MB_OK|MB_ICONSTOP);
+        free_process_list(&list);
+        return;
     }
+    enum_process_children(snapshot, &list, dwProcessId);
+    
+    CloseHandle(snapshot);
 
-    CloseHandle(hProcess);
+    for (i = 0; i < list.count; ++i)
+    {
+        hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, list.pid[i]);        
+
+        kill_process(hProcess, wstrErrorText);
+        CloseHandle(hProcess);
+    }
+    free_process_list(&list);
 }
-- 
2.9.3




More information about the wine-patches mailing list