Needed for Epic Online Services updater which invokes taskkill with /T flag and fails to replace a file if that didn't actually killed the processes.
There is apparently a bit of refactoring on the way, with most notably using toolhelp snapshot instead of EnumProcesses(). That is more convenient for finding child processes (instead of performing a separate query for parent pid), but I also think that is more consistent in general and gets rid of existing separate query for process name.
From: Paul Gofman pgofman@codeweavers.com
--- programs/taskkill/taskkill.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-)
diff --git a/programs/taskkill/taskkill.c b/programs/taskkill/taskkill.c index 424e87b9a44..44ed4c79119 100644 --- a/programs/taskkill/taskkill.c +++ b/programs/taskkill/taskkill.c @@ -58,13 +58,13 @@ static int taskkill_vprintfW(const WCHAR *msg, va_list va_args) */ len = WideCharToMultiByte(GetOEMCP(), 0, msg_buffer, wlen, NULL, 0, NULL, NULL); - msgA = HeapAlloc(GetProcessHeap(), 0, len); + msgA = malloc(len); if (!msgA) return 0;
WideCharToMultiByte(GetOEMCP(), 0, msg_buffer, wlen, msgA, len, NULL, NULL); WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), msgA, len, &count, FALSE); - HeapFree(GetProcessHeap(), 0, msgA); + free(msgA); }
return count; @@ -127,7 +127,7 @@ static DWORD *enumerate_processes(DWORD *list_count) { DWORD *pid_list, alloc_bytes = 1024 * sizeof(*pid_list), needed_bytes;
- pid_list = HeapAlloc(GetProcessHeap(), 0, alloc_bytes); + pid_list = malloc(alloc_bytes); if (!pid_list) return NULL;
@@ -137,7 +137,7 @@ static DWORD *enumerate_processes(DWORD *list_count)
if (!EnumProcesses(pid_list, alloc_bytes, &needed_bytes)) { - HeapFree(GetProcessHeap(), 0, pid_list); + free(pid_list); return NULL; }
@@ -150,10 +150,10 @@ static DWORD *enumerate_processes(DWORD *list_count) break;
alloc_bytes *= 2; - realloc_list = HeapReAlloc(GetProcessHeap(), 0, pid_list, alloc_bytes); + realloc_list = realloc(pid_list, alloc_bytes); if (!realloc_list) { - HeapFree(GetProcessHeap(), 0, pid_list); + free(pid_list); return NULL; } pid_list = realloc_list; @@ -288,7 +288,7 @@ static int send_close_messages(void) } }
- HeapFree(GetProcessHeap(), 0, pid_list); + free(pid_list); return status_code; }
@@ -403,7 +403,7 @@ static int terminate_processes(void) } }
- HeapFree(GetProcessHeap(), 0, pid_list); + free(pid_list); return status_code; }
@@ -413,8 +413,7 @@ static BOOL add_to_task_list(WCHAR *name)
if (!task_list) { - task_list = HeapAlloc(GetProcessHeap(), 0, - list_size * sizeof(*task_list)); + task_list = malloc(list_size * sizeof(*task_list)); if (!task_list) return FALSE; } @@ -423,8 +422,7 @@ static BOOL add_to_task_list(WCHAR *name) void *realloc_list;
list_size *= 2; - realloc_list = HeapReAlloc(GetProcessHeap(), 0, task_list, - list_size * sizeof(*task_list)); + realloc_list = realloc(task_list, list_size * sizeof(*task_list)); if (!realloc_list) return FALSE;
@@ -521,7 +519,7 @@ int __cdecl wmain(int argc, WCHAR *argv[])
if (!process_arguments(argc, argv)) { - HeapFree(GetProcessHeap(), 0, task_list); + free(task_list); return 1; }
@@ -530,6 +528,6 @@ int __cdecl wmain(int argc, WCHAR *argv[]) else status_code = send_close_messages();
- HeapFree(GetProcessHeap(), 0, task_list); + free(task_list); return status_code; }
From: Paul Gofman pgofman@codeweavers.com
--- programs/taskkill/taskkill.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-)
diff --git a/programs/taskkill/taskkill.c b/programs/taskkill/taskkill.c index 44ed4c79119..ad5f8e389f7 100644 --- a/programs/taskkill/taskkill.c +++ b/programs/taskkill/taskkill.c @@ -136,10 +136,7 @@ static DWORD *enumerate_processes(DWORD *list_count) DWORD *realloc_list;
if (!EnumProcesses(pid_list, alloc_bytes, &needed_bytes)) - { - free(pid_list); return NULL; - }
/* EnumProcesses can't signal an insufficient buffer condition, so the * only way to possibly determine whether a larger buffer is required @@ -152,10 +149,7 @@ static DWORD *enumerate_processes(DWORD *list_count) alloc_bytes *= 2; realloc_list = realloc(pid_list, alloc_bytes); if (!realloc_list) - { - free(pid_list); return NULL; - } pid_list = realloc_list; }
@@ -288,7 +282,6 @@ static int send_close_messages(void) } }
- free(pid_list); return status_code; }
@@ -403,7 +396,6 @@ static int terminate_processes(void) } }
- free(pid_list); return status_code; }
@@ -515,19 +507,10 @@ static BOOL process_arguments(int argc, WCHAR *argv[])
int __cdecl wmain(int argc, WCHAR *argv[]) { - int status_code = 0; - if (!process_arguments(argc, argv)) - { - free(task_list); return 1; - }
if (force_termination) - status_code = terminate_processes(); - else - status_code = send_close_messages(); - - free(task_list); - return status_code; + return terminate_processes(); + return send_close_messages(); }
From: Paul Gofman pgofman@codeweavers.com
--- programs/taskkill/taskkill.c | 38 ++++++++++++++---------------------- 1 file changed, 15 insertions(+), 23 deletions(-)
diff --git a/programs/taskkill/taskkill.c b/programs/taskkill/taskkill.c index ad5f8e389f7..595bfa659af 100644 --- a/programs/taskkill/taskkill.c +++ b/programs/taskkill/taskkill.c @@ -33,6 +33,8 @@ static BOOL force_termination = FALSE; static WCHAR **task_list; static unsigned int task_count;
+static DWORD *pid_list, pid_list_size; + struct pid_close_info { DWORD pid; @@ -123,20 +125,20 @@ static BOOL CALLBACK pid_enum_proc(HWND hwnd, LPARAM lParam) return TRUE; }
-static DWORD *enumerate_processes(DWORD *list_count) +static BOOL enumerate_processes(void) { - DWORD *pid_list, alloc_bytes = 1024 * sizeof(*pid_list), needed_bytes; + DWORD alloc_bytes = 1024 * sizeof(*pid_list), needed_bytes;
pid_list = malloc(alloc_bytes); if (!pid_list) - return NULL; + return FALSE;
for (;;) { DWORD *realloc_list;
if (!EnumProcesses(pid_list, alloc_bytes, &needed_bytes)) - return NULL; + return FALSE;
/* EnumProcesses can't signal an insufficient buffer condition, so the * only way to possibly determine whether a larger buffer is required @@ -149,12 +151,12 @@ static DWORD *enumerate_processes(DWORD *list_count) alloc_bytes *= 2; realloc_list = realloc(pid_list, alloc_bytes); if (!realloc_list) - return NULL; + return FALSE; pid_list = realloc_list; }
- *list_count = needed_bytes / sizeof(*pid_list); - return pid_list; + pid_list_size = needed_bytes / sizeof(*pid_list); + return TRUE; }
static BOOL get_process_name_from_pid(DWORD pid, WCHAR *buf, DWORD chars) @@ -199,18 +201,10 @@ static BOOL get_process_name_from_pid(DWORD pid, WCHAR *buf, DWORD chars) * system processes. */ static int send_close_messages(void) { - DWORD *pid_list, pid_list_size; DWORD self_pid = GetCurrentProcessId(); unsigned int i; int status_code = 0;
- pid_list = enumerate_processes(&pid_list_size); - if (!pid_list) - { - taskkill_message(STRING_ENUM_FAILED); - return 1; - } - for (i = 0; i < task_count; i++) { WCHAR *p = task_list[i]; @@ -287,18 +281,10 @@ static int send_close_messages(void)
static int terminate_processes(void) { - DWORD *pid_list, pid_list_size; DWORD self_pid = GetCurrentProcessId(); unsigned int i; int status_code = 0;
- pid_list = enumerate_processes(&pid_list_size); - if (!pid_list) - { - taskkill_message(STRING_ENUM_FAILED); - return 1; - } - for (i = 0; i < task_count; i++) { WCHAR *p = task_list[i]; @@ -510,6 +496,12 @@ int __cdecl wmain(int argc, WCHAR *argv[]) if (!process_arguments(argc, argv)) return 1;
+ if (!enumerate_processes()) + { + taskkill_message(STRING_ENUM_FAILED); + return 1; + } + if (force_termination) return terminate_processes(); return send_close_messages();
From: Paul Gofman pgofman@codeweavers.com
--- programs/taskkill/taskkill.c | 234 ++++++++++++----------------------- 1 file changed, 82 insertions(+), 152 deletions(-)
diff --git a/programs/taskkill/taskkill.c b/programs/taskkill/taskkill.c index 595bfa659af..d2e1dd54209 100644 --- a/programs/taskkill/taskkill.c +++ b/programs/taskkill/taskkill.c @@ -185,6 +185,55 @@ static BOOL get_process_name_from_pid(DWORD pid, WCHAR *buf, DWORD chars) return TRUE; }
+static BOOL get_task_pid(const WCHAR *str, BOOL *is_numeric, WCHAR *process_name, int *status_code, DWORD *pid) +{ + DWORD self_pid = GetCurrentProcessId(); + const WCHAR *p = str; + unsigned int i; + + *is_numeric = TRUE; + while (*p) + { + if (!iswdigit(*p++)) + { + *is_numeric = FALSE; + break; + } + } + + if (*is_numeric) + { + *pid = wcstol(str, NULL, 10); + if (*pid == self_pid) + { + taskkill_message(STRING_SELF_TERMINATION); + *status_code = 1; + return FALSE; + } + return TRUE; + } + + for (i = 0; i < pid_list_size; ++i) + { + if (get_process_name_from_pid(pid_list[i], process_name, MAX_PATH) && + !wcsicmp(process_name, str)) + { + if (pid_list[i] == self_pid) + { + taskkill_message(STRING_SELF_TERMINATION); + *status_code = 1; + return FALSE; + } + *pid = pid_list[i]; + return TRUE; + } + } + + taskkill_message_printfW(STRING_SEARCH_FAILED, str); + *status_code = 128; + return FALSE; +} + /* The implemented task enumeration and termination behavior does not * exactly match native behavior. On Windows: * @@ -201,79 +250,29 @@ static BOOL get_process_name_from_pid(DWORD pid, WCHAR *buf, DWORD chars) * system processes. */ static int send_close_messages(void) { - DWORD self_pid = GetCurrentProcessId(); + WCHAR process_name[MAX_PATH]; + struct pid_close_info info; unsigned int i; int status_code = 0; + BOOL is_numeric;
for (i = 0; i < task_count; i++) { - WCHAR *p = task_list[i]; - BOOL is_numeric = TRUE; - - /* Determine whether the string is not numeric. */ - while (*p) - { - if (!iswdigit(*p++)) - { - is_numeric = FALSE; - break; - } - } + if (!get_task_pid(task_list[i], &is_numeric, process_name, &status_code, &info.pid)) + continue;
- if (is_numeric) + info.found = FALSE; + EnumWindows(pid_enum_proc, (LPARAM)&info); + if (info.found) { - DWORD pid = wcstol(task_list[i], NULL, 10); - struct pid_close_info info = { pid }; - - if (pid == self_pid) - { - taskkill_message(STRING_SELF_TERMINATION); - status_code = 1; - continue; - } - - EnumWindows(pid_enum_proc, (LPARAM)&info); - if (info.found) - taskkill_message_printfW(STRING_CLOSE_PID_SEARCH, pid); + if (is_numeric) + taskkill_message_printfW(STRING_CLOSE_PID_SEARCH, info.pid); else - { - taskkill_message_printfW(STRING_SEARCH_FAILED, task_list[i]); - status_code = 128; - } - } - else - { - DWORD index; - BOOL found_process = FALSE; - - for (index = 0; index < pid_list_size; index++) - { - WCHAR process_name[MAX_PATH]; - - if (get_process_name_from_pid(pid_list[index], process_name, MAX_PATH) && - !wcsicmp(process_name, task_list[i])) - { - struct pid_close_info info = { pid_list[index] }; - - found_process = TRUE; - if (pid_list[index] == self_pid) - { - taskkill_message(STRING_SELF_TERMINATION); - status_code = 1; - continue; - } - - EnumWindows(pid_enum_proc, (LPARAM)&info); - taskkill_message_printfW(STRING_CLOSE_PROC_SRCH, process_name, pid_list[index]); - } - } - - if (!found_process) - { - taskkill_message_printfW(STRING_SEARCH_FAILED, task_list[i]); - status_code = 128; - } + taskkill_message_printfW(STRING_CLOSE_PROC_SRCH, process_name, info.pid); + continue; } + taskkill_message_printfW(STRING_SEARCH_FAILED, task_list[i]); + status_code = 128; }
return status_code; @@ -281,107 +280,38 @@ static int send_close_messages(void)
static int terminate_processes(void) { - DWORD self_pid = GetCurrentProcessId(); + WCHAR process_name[MAX_PATH]; unsigned int i; int status_code = 0; + BOOL is_numeric; + HANDLE process; + DWORD pid;
for (i = 0; i < task_count; i++) { - WCHAR *p = task_list[i]; - BOOL is_numeric = TRUE; + if (!get_task_pid(task_list[i], &is_numeric, process_name, &status_code, &pid)) + continue;
- /* Determine whether the string is not numeric. */ - while (*p) + process = OpenProcess(PROCESS_TERMINATE, FALSE, pid); + if (!process) { - if (!iswdigit(*p++)) - { - is_numeric = FALSE; - break; - } + taskkill_message_printfW(STRING_SEARCH_FAILED, task_list[i]); + status_code = 128; + continue; } - - if (is_numeric) + if (!TerminateProcess(process, 1)) { - DWORD pid = wcstol(task_list[i], NULL, 10); - HANDLE process; - - if (pid == self_pid) - { - taskkill_message(STRING_SELF_TERMINATION); - status_code = 1; - continue; - } - - process = OpenProcess(PROCESS_TERMINATE, FALSE, pid); - if (!process) - { - taskkill_message_printfW(STRING_SEARCH_FAILED, task_list[i]); - status_code = 128; - continue; - } - - if (!TerminateProcess(process, 1)) - { - taskkill_message_printfW(STRING_TERMINATE_FAILED, task_list[i]); - status_code = 1; - CloseHandle(process); - continue; - } - - taskkill_message_printfW(STRING_TERM_PID_SEARCH, pid); + taskkill_message_printfW(STRING_TERMINATE_FAILED, task_list[i]); + status_code = 1; CloseHandle(process); + continue; } + if (is_numeric) + taskkill_message_printfW(STRING_TERM_PID_SEARCH, pid); else - { - DWORD index; - BOOL found_process = FALSE; - - for (index = 0; index < pid_list_size; index++) - { - WCHAR process_name[MAX_PATH]; - - if (get_process_name_from_pid(pid_list[index], process_name, MAX_PATH) && - !wcsicmp(process_name, task_list[i])) - { - HANDLE process; - - if (pid_list[index] == self_pid) - { - taskkill_message(STRING_SELF_TERMINATION); - status_code = 1; - continue; - } - - process = OpenProcess(PROCESS_TERMINATE, FALSE, pid_list[index]); - if (!process) - { - taskkill_message_printfW(STRING_SEARCH_FAILED, task_list[i]); - status_code = 128; - continue; - } - - if (!TerminateProcess(process, 1)) - { - taskkill_message_printfW(STRING_TERMINATE_FAILED, task_list[i]); - status_code = 1; - CloseHandle(process); - continue; - } - - found_process = TRUE; - taskkill_message_printfW(STRING_TERM_PROC_SEARCH, task_list[i], pid_list[index]); - CloseHandle(process); - } - } - - if (!found_process) - { - taskkill_message_printfW(STRING_SEARCH_FAILED, task_list[i]); - status_code = 128; - } - } + taskkill_message_printfW(STRING_TERM_PROC_SEARCH, task_list[i], pid); + CloseHandle(process); } - return status_code; }
From: Paul Gofman pgofman@codeweavers.com
--- programs/taskkill/taskkill.c | 99 ++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 54 deletions(-)
diff --git a/programs/taskkill/taskkill.c b/programs/taskkill/taskkill.c index d2e1dd54209..b60b5486f87 100644 --- a/programs/taskkill/taskkill.c +++ b/programs/taskkill/taskkill.c @@ -21,7 +21,7 @@
#include <stdlib.h> #include <windows.h> -#include <psapi.h> +#include <tlhelp32.h> #include <wine/debug.h>
#include "taskkill.h" @@ -33,7 +33,13 @@ static BOOL force_termination = FALSE; static WCHAR **task_list; static unsigned int task_count;
-static DWORD *pid_list, pid_list_size; +static struct +{ + PROCESSENTRY32W p; + BOOL matched; +} +*process_list; +static unsigned int process_count;
struct pid_close_info { @@ -127,61 +133,36 @@ static BOOL CALLBACK pid_enum_proc(HWND hwnd, LPARAM lParam)
static BOOL enumerate_processes(void) { - DWORD alloc_bytes = 1024 * sizeof(*pid_list), needed_bytes; + unsigned int alloc_count = 128; + void *realloc_list; + HANDLE snapshot;
- pid_list = malloc(alloc_bytes); - if (!pid_list) + snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (snapshot == INVALID_HANDLE_VALUE) return FALSE;
- for (;;) - { - DWORD *realloc_list; - - if (!EnumProcesses(pid_list, alloc_bytes, &needed_bytes)) - return FALSE; - - /* EnumProcesses can't signal an insufficient buffer condition, so the - * only way to possibly determine whether a larger buffer is required - * is to see whether the written number of bytes is the same as the - * buffer size. If so, the buffer will be reallocated to twice the - * size. */ - if (alloc_bytes != needed_bytes) - break; - - alloc_bytes *= 2; - realloc_list = realloc(pid_list, alloc_bytes); - if (!realloc_list) - return FALSE; - pid_list = realloc_list; - } - - pid_list_size = needed_bytes / sizeof(*pid_list); - return TRUE; -} - -static BOOL get_process_name_from_pid(DWORD pid, WCHAR *buf, DWORD chars) -{ - HANDLE process; - HMODULE module; - DWORD required_size; - - process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); - if (!process) + process_list = malloc(alloc_count * sizeof(*process_list)); + if (!process_list) return FALSE;
- if (!EnumProcessModules(process, &module, sizeof(module), &required_size)) - { - CloseHandle(process); + process_list[0].p.dwSize = sizeof(process_list[0].p); + if (!Process32FirstW(snapshot, &process_list[0].p)) return FALSE; - }
- if (!GetModuleBaseNameW(process, module, buf, chars)) + do { - CloseHandle(process); - return FALSE; - } - - CloseHandle(process); + process_list[process_count++].matched = FALSE; + if (process_count == alloc_count) + { + alloc_count *= 2; + realloc_list = realloc(process_list, alloc_count * sizeof(*process_list)); + if (!realloc_list) + return FALSE; + process_list = realloc_list; + } + process_list[process_count].p.dwSize = sizeof(process_list[process_count].p); + } while (Process32NextW(snapshot, &process_list[process_count].p)); + CloseHandle(snapshot); return TRUE; }
@@ -204,6 +185,14 @@ static BOOL get_task_pid(const WCHAR *str, BOOL *is_numeric, WCHAR *process_name if (*is_numeric) { *pid = wcstol(str, NULL, 10); + for (i = 0; i < process_count; ++i) + { + if (process_list[i].p.th32ProcessID == *pid) + break; + } + if (i == process_count || process_list[i].matched) + goto not_found; + process_list[i].matched = TRUE; if (*pid == self_pid) { taskkill_message(STRING_SELF_TERMINATION); @@ -213,22 +202,24 @@ static BOOL get_task_pid(const WCHAR *str, BOOL *is_numeric, WCHAR *process_name return TRUE; }
- for (i = 0; i < pid_list_size; ++i) + for (i = 0; i < process_count; ++i) { - if (get_process_name_from_pid(pid_list[i], process_name, MAX_PATH) && - !wcsicmp(process_name, str)) + if (!wcsicmp(process_list[i].p.szExeFile, str) && !process_list[i].matched) { - if (pid_list[i] == self_pid) + process_list[i].matched = TRUE; + if (process_list[i].p.th32ProcessID == self_pid) { taskkill_message(STRING_SELF_TERMINATION); *status_code = 1; return FALSE; } - *pid = pid_list[i]; + *pid = process_list[i].p.th32ProcessID; + wcscpy(process_name, process_list[i].p.szExeFile); return TRUE; } }
+not_found: taskkill_message_printfW(STRING_SEARCH_FAILED, str); *status_code = 128; return FALSE;
From: Paul Gofman pgofman@codeweavers.com
--- programs/taskkill/taskkill.c | 82 +++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 30 deletions(-)
diff --git a/programs/taskkill/taskkill.c b/programs/taskkill/taskkill.c index b60b5486f87..c32c380f001 100644 --- a/programs/taskkill/taskkill.c +++ b/programs/taskkill/taskkill.c @@ -37,6 +37,7 @@ static struct { PROCESSENTRY32W p; BOOL matched; + BOOL is_numeric; } *process_list; static unsigned int process_count; @@ -151,6 +152,7 @@ static BOOL enumerate_processes(void)
do { + process_list[process_count].is_numeric = FALSE; process_list[process_count++].matched = FALSE; if (process_count == alloc_count) { @@ -166,40 +168,42 @@ static BOOL enumerate_processes(void) return TRUE; }
-static BOOL get_task_pid(const WCHAR *str, BOOL *is_numeric, WCHAR *process_name, int *status_code, DWORD *pid) +static void mark_task_process(const WCHAR *str, int *status_code) { DWORD self_pid = GetCurrentProcessId(); const WCHAR *p = str; + BOOL is_numeric; unsigned int i; + DWORD pid;
- *is_numeric = TRUE; + is_numeric = TRUE; while (*p) { if (!iswdigit(*p++)) { - *is_numeric = FALSE; + is_numeric = FALSE; break; } }
- if (*is_numeric) + if (is_numeric) { - *pid = wcstol(str, NULL, 10); + pid = wcstol(str, NULL, 10); for (i = 0; i < process_count; ++i) { - if (process_list[i].p.th32ProcessID == *pid) + if (process_list[i].p.th32ProcessID == pid) break; } if (i == process_count || process_list[i].matched) goto not_found; process_list[i].matched = TRUE; - if (*pid == self_pid) + process_list[i].is_numeric = TRUE; + if (pid == self_pid) { taskkill_message(STRING_SELF_TERMINATION); *status_code = 1; - return FALSE; } - return TRUE; + return; }
for (i = 0; i < process_count; ++i) @@ -211,18 +215,27 @@ static BOOL get_task_pid(const WCHAR *str, BOOL *is_numeric, WCHAR *process_name { taskkill_message(STRING_SELF_TERMINATION); *status_code = 1; - return FALSE; } - *pid = process_list[i].p.th32ProcessID; - wcscpy(process_name, process_list[i].p.szExeFile); - return TRUE; + return; } }
not_found: taskkill_message_printfW(STRING_SEARCH_FAILED, str); *status_code = 128; - return FALSE; +} + +static void taskkill_message_print_process(int msg, unsigned int index) +{ + WCHAR pid_str[16]; + + if (!process_list[index].is_numeric) + { + taskkill_message_printfW(msg, process_list[index].p.szExeFile); + return; + } + wsprintfW(pid_str, L"%lu", process_list[index].p.th32ProcessID); + taskkill_message_printfW(msg, pid_str); }
/* The implemented task enumeration and termination behavior does not @@ -241,28 +254,28 @@ not_found: * system processes. */ static int send_close_messages(void) { - WCHAR process_name[MAX_PATH]; + const WCHAR *process_name; struct pid_close_info info; unsigned int i; int status_code = 0; - BOOL is_numeric;
for (i = 0; i < task_count; i++) { - if (!get_task_pid(task_list[i], &is_numeric, process_name, &status_code, &info.pid)) + if (!process_list[i].matched) continue; - + info.pid = process_list[i].p.th32ProcessID; + process_name = process_list[i].p.szExeFile; info.found = FALSE; EnumWindows(pid_enum_proc, (LPARAM)&info); if (info.found) { - if (is_numeric) + if (process_list[i].is_numeric) taskkill_message_printfW(STRING_CLOSE_PID_SEARCH, info.pid); else taskkill_message_printfW(STRING_CLOSE_PROC_SRCH, process_name, info.pid); continue; } - taskkill_message_printfW(STRING_SEARCH_FAILED, task_list[i]); + taskkill_message_print_process(STRING_SEARCH_FAILED, i); status_code = 128; }
@@ -271,36 +284,37 @@ static int send_close_messages(void)
static int terminate_processes(void) { - WCHAR process_name[MAX_PATH]; + const WCHAR *process_name; unsigned int i; int status_code = 0; - BOOL is_numeric; HANDLE process; DWORD pid;
- for (i = 0; i < task_count; i++) + for (i = 0; i < process_count; i++) { - if (!get_task_pid(task_list[i], &is_numeric, process_name, &status_code, &pid)) + if (!process_list[i].matched) continue;
+ pid = process_list[i].p.th32ProcessID; + process_name = process_list[i].p.szExeFile; process = OpenProcess(PROCESS_TERMINATE, FALSE, pid); if (!process) { - taskkill_message_printfW(STRING_SEARCH_FAILED, task_list[i]); + taskkill_message_print_process(STRING_SEARCH_FAILED, i); status_code = 128; continue; } if (!TerminateProcess(process, 1)) { - taskkill_message_printfW(STRING_TERMINATE_FAILED, task_list[i]); + taskkill_message_print_process(STRING_TERMINATE_FAILED, i); status_code = 1; CloseHandle(process); continue; } - if (is_numeric) + if (process_list[i].is_numeric) taskkill_message_printfW(STRING_TERM_PID_SEARCH, pid); else - taskkill_message_printfW(STRING_TERM_PROC_SEARCH, task_list[i], pid); + taskkill_message_printfW(STRING_TERM_PROC_SEARCH, process_name, pid); CloseHandle(process); } return status_code; @@ -414,6 +428,9 @@ static BOOL process_arguments(int argc, WCHAR *argv[])
int __cdecl wmain(int argc, WCHAR *argv[]) { + int search_status = 0, terminate_status; + unsigned int i; + if (!process_arguments(argc, argv)) return 1;
@@ -423,7 +440,12 @@ int __cdecl wmain(int argc, WCHAR *argv[]) return 1; }
+ for (i = 0; i < task_count; ++i) + mark_task_process(task_list[i], &search_status); + if (force_termination) - return terminate_processes(); - return send_close_messages(); + terminate_status = terminate_processes(); + else + terminate_status = send_close_messages(); + return search_status ? search_status : terminate_status; }
From: Paul Gofman pgofman@codeweavers.com
--- programs/taskkill/taskkill.c | 59 +++++++++++++++++++++++++++++++---- programs/taskkill/taskkill.h | 2 ++ programs/taskkill/taskkill.rc | 2 ++ 3 files changed, 57 insertions(+), 6 deletions(-)
diff --git a/programs/taskkill/taskkill.c b/programs/taskkill/taskkill.c index c32c380f001..1eff832f0ea 100644 --- a/programs/taskkill/taskkill.c +++ b/programs/taskkill/taskkill.c @@ -29,6 +29,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(taskkill);
static BOOL force_termination = FALSE; +static BOOL kill_child_processes;
static WCHAR **task_list; static unsigned int task_count; @@ -238,6 +239,46 @@ static void taskkill_message_print_process(int msg, unsigned int index) taskkill_message_printfW(msg, pid_str); }
+static BOOL find_parent(unsigned int process_index, unsigned int *parent_index) +{ + DWORD parent_id = process_list[process_index].p.th32ParentProcessID; + unsigned int i; + + if (!parent_id) + return FALSE; + + for (i = 0; i < process_count; ++i) + { + if (process_list[i].p.th32ProcessID == parent_id) + { + *parent_index = i; + return TRUE; + } + } + return FALSE; +} + +static void mark_child_processes(void) +{ + unsigned int i, parent; + + for (i = 0; i < process_count; ++i) + { + if (process_list[i].matched) + continue; + parent = i; + while (find_parent(parent, &parent)) + { + if (process_list[parent].matched) + { + WINE_TRACE("Adding child %04lx.\n", process_list[i].p.th32ProcessID); + process_list[i].matched = TRUE; + break; + } + } + } +} + /* The implemented task enumeration and termination behavior does not * exactly match native behavior. On Windows: * @@ -259,17 +300,20 @@ static int send_close_messages(void) unsigned int i; int status_code = 0;
- for (i = 0; i < task_count; i++) + for (i = 0; i < process_count; i++) { if (!process_list[i].matched) continue; info.pid = process_list[i].p.th32ProcessID; process_name = process_list[i].p.szExeFile; info.found = FALSE; + WINE_TRACE("Terminating pid %04lx.\n", info.pid); EnumWindows(pid_enum_proc, (LPARAM)&info); if (info.found) { - if (process_list[i].is_numeric) + if (kill_child_processes) + taskkill_message_printfW(STRING_CLOSE_CHILD, info.pid, process_list[i].p.th32ParentProcessID); + else if (process_list[i].is_numeric) taskkill_message_printfW(STRING_CLOSE_PID_SEARCH, info.pid); else taskkill_message_printfW(STRING_CLOSE_PROC_SRCH, process_name, info.pid); @@ -311,7 +355,9 @@ static int terminate_processes(void) CloseHandle(process); continue; } - if (process_list[i].is_numeric) + if (kill_child_processes) + taskkill_message_printfW(STRING_TERM_CHILD, pid, process_list[i].p.th32ParentProcessID); + else if (process_list[i].is_numeric) taskkill_message_printfW(STRING_TERM_PID_SEARCH, pid); else taskkill_message_printfW(STRING_TERM_PROC_SEARCH, process_name, pid); @@ -378,8 +424,8 @@ static BOOL process_arguments(int argc, WCHAR *argv[]) argdata++;
if (!wcsicmp(L"t", argdata)) - WINE_FIXME("argument T not supported\n"); - if (!wcsicmp(L"f", argdata)) + kill_child_processes = TRUE; + else if (!wcsicmp(L"f", argdata)) force_termination = TRUE; /* Options /IM and /PID appear to behave identically, except for * the fact that they cannot be specified at the same time. */ @@ -442,7 +488,8 @@ int __cdecl wmain(int argc, WCHAR *argv[])
for (i = 0; i < task_count; ++i) mark_task_process(task_list[i], &search_status); - + if (kill_child_processes) + mark_child_processes(); if (force_termination) terminate_status = terminate_processes(); else diff --git a/programs/taskkill/taskkill.h b/programs/taskkill/taskkill.h index 7972a156f3c..068f817f546 100644 --- a/programs/taskkill/taskkill.h +++ b/programs/taskkill/taskkill.h @@ -35,3 +35,5 @@ #define STRING_ENUM_FAILED 112 #define STRING_TERMINATE_FAILED 113 #define STRING_SELF_TERMINATION 114 +#define STRING_TERM_CHILD 115 +#define STRING_CLOSE_CHILD 116 diff --git a/programs/taskkill/taskkill.rc b/programs/taskkill/taskkill.rc index e6ad8afac75..fd195f3f8c0 100644 --- a/programs/taskkill/taskkill.rc +++ b/programs/taskkill/taskkill.rc @@ -40,4 +40,6 @@ STRINGTABLE STRING_ENUM_FAILED, "Error: Unable to enumerate the process list.\n" STRING_TERMINATE_FAILED, "Error: Unable to terminate process "%1".\n" STRING_SELF_TERMINATION, "Error: Process self-termination is not permitted.\n" + STRING_TERM_CHILD, "The process with PID %1!u! (child process of PID %2!u!) has been terminated.\n" + STRING_CLOSE_CHILD, "Sent termination signal to process with PID %1!u!, child of PID %2!u!.\n" }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=131166
Your paranoid android.
=== debian11 (32 bit report) ===
Report validation errors: d3d11:d3d11 has no test summary line (early exit of the main process?) d3d11:d3d11 has unaccounted for failure messages d3d11:d3d11 has unaccounted for todo messages d3d11:d3d11 has unaccounted for skip messages