diff --git a/programs/taskmgr/endproc.c b/programs/taskmgr/endproc.c index 89c2d7b..c890f06 100644 --- a/programs/taskmgr/endproc.c +++ b/programs/taskmgr/endproc.c @@ -31,17 +31,42 @@ #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; /*dynamic array to store the process IDs*/ + SIZE_T count; /*index to maintain the last entry of the array;*/ + SIZE_T size; /*the current size of the pid array*/ +} process_list; + static void load_message_strings(void) { LoadStringW(hInst, IDS_TERMINATE_MESSAGE, wszWarnMsg, sizeof(wszWarnMsg)/sizeof(WCHAR)); LoadStringW(hInst, IDS_TERMINATE_UNABLE2TERMINATE, wszUnable2Terminate, sizeof(wszUnable2Terminate)/sizeof(WCHAR)); 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) { @@ -77,22 +102,71 @@ void ProcessPage_OnEndProcess(void) hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, dwProcessId); - if (!hProcess) - { - GetLastErrorText(wstrErrorText, sizeof(wstrErrorText)/sizeof(WCHAR)); - MessageBoxW(hMainWnd, wstrErrorText,wszUnable2Terminate, MB_OK|MB_ICONSTOP); - return; + + kill_process(hProcess, wstrErrorText); + + CloseHandle(hProcess); +} + + +static INT init_process_list(process_list *list) { + list->size = 4; /*initialise size with 4. Will increase if necessary.*/ + list->pid = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, list->size * sizeof(*(list->pid))); + list->count = 0; + + if(list->pid == NULL) + return 0; + + return 1; +} + +static INT process_list_append(process_list *list, DWORD id) { + if(list->count == list->size){ + list->size *= 2; + list->pid = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, list->pid, list->size * sizeof(*(list->pid))); + if(!list->pid) + return 0; } + list->pid[list->count] = id; + list->count += 1; + return 1; +} - 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)) + 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) { LVITEMW lvitem; @@ -100,6 +174,9 @@ void ProcessPage_OnEndProcessTree(void) DWORD dwProcessId; HANDLE hProcess; WCHAR wstrErrorText[256]; + process_list list; + SIZE_T i; + HANDLE snapshot; load_message_strings(); @@ -125,20 +202,32 @@ void ProcessPage_OnEndProcessTree(void) if (MessageBoxW(hMainWnd, wszWarnMsg, wszWarnTitle, MB_YESNO|MB_ICONWARNING) != IDYES) return; - hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, dwProcessId); - if (!hProcess) + if(!init_process_list(&list)) + return; + + if(!process_list_append(&list, dwProcessId)) + return; + + 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; } - if (!TerminateProcess(hProcess, 0)) - { - GetLastErrorText(wstrErrorText, sizeof(wstrErrorText)/sizeof(WCHAR)); - MessageBoxW(hMainWnd, wstrErrorText,wszUnable2Terminate, MB_OK|MB_ICONSTOP); + enum_process_children(snapshot, &list, dwProcessId); + + CloseHandle(snapshot); + + for(i = 0; i < list.count; ++i) { + hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, list.pid[i]); + + kill_process(hProcess, wstrErrorText); + + CloseHandle(hProcess); } - CloseHandle(hProcess); + free_process_list(&list); }