[TASKKILL] Implement /t (tree) parameter (#2403)

CORE-15998
This commit is contained in:
Nguyen Trung Khanh 2020-03-01 15:34:38 +07:00 committed by Hermès Bélusca-Maïto
parent 49c40a2941
commit 97e7efc020
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
12 changed files with 290 additions and 163 deletions

View file

@ -2,7 +2,7 @@ LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL
STRINGTABLE
{
STRING_USAGE, "Usage: taskkill [/?] [/f] [/im Prozess Name | /pid Prozess ID]\n"
STRING_USAGE, "Usage: taskkill [/?] [/f] [/im Prozess Name | /pid Prozess ID] [/t]\n"
STRING_INVALID_OPTION, "Fehler: Unbekannte oder ungülige Kommandozeilenoption angegeben.\n"
STRING_INVALID_PARAM, "Fehler: Ungültiger Kommandozeilenparameter angegeben.\n"
STRING_MISSING_OPTION, "Fehler: Eine der Optionen /im oder /pid muss angegeben werden.\n"
@ -16,6 +16,9 @@ STRINGTABLE
STRING_ENUM_FAILED, "Fehler: Prozessliste kann nicht aufgebaut werden.\n"
STRING_TERMINATE_FAILED, "Fehler: Prozess ""%1"" kann nicht beendet werden.\n"
STRING_SELF_TERMINATION, "Fehler: Der Prozess kann sich nicht selbst beenden.\n"
STRING_CLOSE_CHILD, "Close message sent to top-level windows of process with PID %1!u!, child of PID %2!u!.\n"
STRING_TERM_CHILD, "Process with PID %1!u! was forcibly terminated, child of PID %2!u!.\n"
STRING_TERM_CHILD_FAILED, "Error: Unable to terminate process with PID %1!u!, child of PID %2!u!.\n"
STRING_PARAM_TOO_MUCH, "Error: Invalid syntax. '%1' option is not allowed more than '%2!d!' time(s).\n"
STRING_INVALID_SYNTAX, "Error: Invalid syntax.\n"
}

View file

@ -2,7 +2,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
STRINGTABLE
{
STRING_USAGE, "Usage: taskkill [/?] [/f] [/im ProcessName | /pid ProcessID]\n"
STRING_USAGE, "Usage: taskkill [/?] [/f] [/im ProcessName | /pid ProcessID] [/t]\n"
STRING_INVALID_OPTION, "Error: Unknown or invalid command line option specified.\n"
STRING_INVALID_PARAM, "Error: Invalid command line parameter specified.\n"
STRING_MISSING_OPTION, "Error: One of options /im or /pid must be specified.\n"
@ -16,6 +16,9 @@ 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_CLOSE_CHILD, "Close message sent to top-level windows of process with PID %1!u!, child of PID %2!u!.\n"
STRING_TERM_CHILD, "Process with PID %1!u! was forcibly terminated, child of PID %2!u!.\n"
STRING_TERM_CHILD_FAILED, "Error: Unable to terminate process with PID %1!u!, child of PID %2!u!.\n"
STRING_PARAM_TOO_MUCH, "Error: Invalid syntax. '%1' option is not allowed more than '%2!d!' time(s).\n"
STRING_INVALID_SYNTAX, "Error: Invalid syntax.\n"
}

View file

@ -9,7 +9,7 @@ LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL
STRINGTABLE
{
STRING_USAGE, "Uso: taskkill [/?] [/f] [/im NomeProcesso | /pid IDProcesso]\n"
STRING_USAGE, "Uso: taskkill [/?] [/f] [/im NomeProcesso | /pid IDProcesso] [/t]\n"
STRING_INVALID_OPTION, "Errore: L'opzione specificata è invalida o sconosciuta.\n"
STRING_INVALID_PARAM, "Errore: Il parametro di comando a riga è invalido.\n"
STRING_MISSING_OPTION, "Errore: Specifica una delle opzioni /im oppure /pid.\n"
@ -23,6 +23,9 @@ STRINGTABLE
STRING_ENUM_FAILED, "Errore: Impossibile enumerare la lista dei processi.\n"
STRING_TERMINATE_FAILED, "Errore: Impossibile terminare il processo ""%1"".\n"
STRING_SELF_TERMINATION, "Errore: L'auto-terminazione non è consentita.\n"
STRING_CLOSE_CHILD, "Close message sent to top-level windows of process with PID %1!u!, child of PID %2!u!.\n"
STRING_TERM_CHILD, "Process with PID %1!u! was forcibly terminated, child of PID %2!u!.\n"
STRING_TERM_CHILD_FAILED, "Error: Unable to terminate process with PID %1!u!, child of PID %2!u!.\n"
STRING_PARAM_TOO_MUCH, "Error: Invalid syntax. '%1' option is not allowed more than '%2!d!' time(s).\n"
STRING_INVALID_SYNTAX, "Error: Invalid syntax.\n"
}

View file

@ -9,7 +9,7 @@ LANGUAGE LANG_POLISH, SUBLANG_DEFAULT
STRINGTABLE
{
STRING_USAGE, "Sposób użycia: taskkill [/?] [/f] [/im nazwa_procesu | /pid id_procesu]\n"
STRING_USAGE, "Sposób użycia: taskkill [/?] [/f] [/im nazwa_procesu | /pid id_procesu] [/t]\n"
STRING_INVALID_OPTION, "Błąd: Określono nieznaną lub nieprawidłową opcję.\n"
STRING_INVALID_PARAM, "Błąd: Nieprawidłowy parametr.\n"
STRING_MISSING_OPTION, "Błąd: Nie określono opcji /im ani /pid.\n"
@ -23,6 +23,9 @@ STRINGTABLE
STRING_ENUM_FAILED, "Błąd: Nie można wyliczyć listy procesów.\n"
STRING_TERMINATE_FAILED, "Błąd: Nie można zakończyć procesu ""%1"".\n"
STRING_SELF_TERMINATION, "Błąd: Proces nie może zakończyć sam siebie.\n"
STRING_CLOSE_CHILD, "Close message sent to top-level windows of process with PID %1!u!, child of PID %2!u!.\n"
STRING_TERM_CHILD, "Process with PID %1!u! was forcibly terminated, child of PID %2!u!.\n"
STRING_TERM_CHILD_FAILED, "Error: Unable to terminate process with PID %1!u!, child of PID %2!u!.\n"
STRING_PARAM_TOO_MUCH, "Błąd: Nieprawidłowa składnia. Opcja '%1' nie jest dozwolona więcej niż '%2!d!' razy.\n"
STRING_INVALID_SYNTAX, "Błąd: Nieprawidłowa składnia.\n"
}

View file

@ -10,7 +10,7 @@ LANGUAGE LANG_ROMANIAN, SUBLANG_NEUTRAL
STRINGTABLE
{
STRING_USAGE, "Utilizare: taskkill [/?] [/f] [/im NumeProces | /pid IdProces]\n"
STRING_USAGE, "Utilizare: taskkill [/?] [/f] [/im NumeProces | /pid IdProces] [/t]\n"
STRING_INVALID_OPTION, "Eroare: Opțiune specificată nevalidă sau necunoscută.\n"
STRING_INVALID_PARAM, "Eroare: Parametrul de comandă specificat este nevalid.\n"
STRING_MISSING_OPTION, "Eroare: Trebuie specificată una dintre opțiunile /im sau /pid.\n"
@ -24,6 +24,9 @@ STRINGTABLE
STRING_ENUM_FAILED, "Eroare: Nu se poate enumera lista de procese.\n"
STRING_TERMINATE_FAILED, "Eroare: Procesul «%1» nu poate fi oprit.\n"
STRING_SELF_TERMINATION, "Eroare: Auto-terminarea nu este permisă.\n"
STRING_CLOSE_CHILD, "Close message sent to top-level windows of process with PID %1!u!, child of PID %2!u!.\n"
STRING_TERM_CHILD, "Process with PID %1!u! was forcibly terminated, child of PID %2!u!.\n"
STRING_TERM_CHILD_FAILED, "Error: Unable to terminate process with PID %1!u!, child of PID %2!u!.\n"
STRING_PARAM_TOO_MUCH, "Eroare: Sintaxă nevalidă. Opțiunea '%1' nu este permisă mai mult de '%2!d!' dată(dăți).\n"
STRING_INVALID_SYNTAX, "Eroare: Sintaxă nevalidă.\n"
}

View file

@ -4,7 +4,7 @@ LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
STRINGTABLE
{
STRING_USAGE, "Использование: TASKKILL [/F] [/IM <образ> | /PID <процесс>]\n"
STRING_USAGE, "Использование: TASKKILL [/F] [/IM <образ> | /PID <процесс>] [/t]\n"
STRING_INVALID_OPTION, "Ошибка: Указаны неверные параметры командной строки.\n"
STRING_INVALID_PARAM, "Ошибка: Указаны неверные параметры командной строки.\n"
STRING_MISSING_OPTION, "Ошибка: Должен быть указан параметр /im или /pid.\n"
@ -18,6 +18,9 @@ STRINGTABLE
STRING_ENUM_FAILED, "Ошибка: Не удается получить список процессов.\n"
STRING_TERMINATE_FAILED, "Ошибка: Не удается завершить процесс ""%1"".\n"
STRING_SELF_TERMINATION, "Ошибка: Процесс не может завершить сам себя.\n"
STRING_CLOSE_CHILD, "Close message sent to top-level windows of process with PID %1!u!, child of PID %2!u!.\n"
STRING_TERM_CHILD, "Process with PID %1!u! was forcibly terminated, child of PID %2!u!.\n"
STRING_TERM_CHILD_FAILED, "Error: Unable to terminate process with PID %1!u!, child of PID %2!u!.\n"
STRING_PARAM_TOO_MUCH, "Ошибка: Неверный синтаксис. Нельзя использовать опцию '%1' больше '%2!d!' раз(а).\n"
STRING_INVALID_SYNTAX, "Ошибка: Неверный синтаксис.\n"
}

View file

@ -6,7 +6,7 @@ LANGUAGE LANG_ALBANIAN, SUBLANG_NEUTRAL
STRINGTABLE
{
STRING_USAGE, "Usage: taskkill [/?] [/f] [/im ProcessName | /pid ProcessID]\n"
STRING_USAGE, "Usage: taskkill [/?] [/f] [/im ProcessName | /pid ProcessID] [/t]\n"
STRING_INVALID_OPTION, "Gabim: Panjohur ose i pavlefshëm opsioni linjes komandes i specifikuar.\n"
STRING_INVALID_PARAM, "Gabim: Pavlefshëm parametri i specifikuar ne linjen e komandes.\n"
STRING_MISSING_OPTION, "Gabim: Njera nga opsionet /im ose /pid duhet te specifikohet.\n"
@ -20,6 +20,9 @@ STRINGTABLE
STRING_ENUM_FAILED, "Gabim: Në pamundësi për të numëruar listën proceseve.\n"
STRING_TERMINATE_FAILED, "Gabim: Pamundur mbyllja e proceseve ""%1"".\n"
STRING_SELF_TERMINATION, "Gabim: Procesi vetë-përfundimi nuk është i lejuar.\n"
STRING_CLOSE_CHILD, "Close message sent to top-level windows of process with PID %1!u!, child of PID %2!u!.\n"
STRING_TERM_CHILD, "Process with PID %1!u! was forcibly terminated, child of PID %2!u!.\n"
STRING_TERM_CHILD_FAILED, "Error: Unable to terminate process with PID %1!u!, child of PID %2!u!.\n"
STRING_PARAM_TOO_MUCH, "Error: Invalid syntax. '%1' option is not allowed more than '%2!d!' time(s).\n"
STRING_INVALID_SYNTAX, "Error: Invalid syntax.\n"
}

View file

@ -4,7 +4,7 @@ LANGUAGE LANG_TURKISH, SUBLANG_NEUTRAL
STRINGTABLE
{
STRING_USAGE, "Kullanım: taskkill [/?] [/f] [/im işlem adı | /pid işlem kimliği]\n"
STRING_USAGE, "Kullanım: taskkill [/?] [/f] [/im işlem adı | /pid işlem kimliği] [/t]\n"
STRING_INVALID_OPTION, "Hata: Bilinmeyen veya geçersiz komut satırı seçeneği belirtildi.\n"
STRING_INVALID_PARAM, "Hata: Geçersiz komut satırı değişkeni belirtildi.\n"
STRING_MISSING_OPTION, "Hata: /im ve /pid seçeneklerinden biri belirtilmeli.\n"
@ -18,6 +18,9 @@ STRINGTABLE
STRING_ENUM_FAILED, "Hata: İşlem numaralandırılamıyor.\n"
STRING_TERMINATE_FAILED, "Hata: ""%1"" işlemi sonlandırılamıyor.\n"
STRING_SELF_TERMINATION, "Hata: İşlemi kendi kendine sonlandırmaya izin verilmedi.\n"
STRING_CLOSE_CHILD, "Close message sent to top-level windows of process with PID %1!u!, child of PID %2!u!.\n"
STRING_TERM_CHILD, "Process with PID %1!u! was forcibly terminated, child of PID %2!u!.\n"
STRING_TERM_CHILD_FAILED, "Error: Unable to terminate process with PID %1!u!, child of PID %2!u!.\n"
STRING_PARAM_TOO_MUCH, "Hata: Geçersiz sözdizimi. '%1' seçeneğine '%2!d!'den fazla kez izin verilmiyor..\n"
STRING_INVALID_SYNTAX, "Hata: Geçersiz sözdizimi.\n"
}

View file

@ -7,7 +7,7 @@ LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
STRINGTABLE
{
STRING_USAGE, "用法taskkill [/?] [/f] [/im 进程名称 | /pid 进程 ID]\n"
STRING_USAGE, "用法taskkill [/?] [/f] [/im 进程名称 | /pid 进程 ID] [/t]\n"
STRING_INVALID_OPTION, "错误:指定了未知或无效的命令行选项。\n"
STRING_INVALID_PARAM, "错误:指定了无效的命令行参数。\n"
STRING_MISSING_OPTION, "错误:必须指定选项 /im 或 /pid。\n"
@ -21,6 +21,9 @@ STRINGTABLE
STRING_ENUM_FAILED, "错误:无法枚举进程列表。\n"
STRING_TERMINATE_FAILED, "错误:无法终止进程“%1”。\n"
STRING_SELF_TERMINATION, "错误:不允许终止自身。\n"
STRING_CLOSE_CHILD, "Close message sent to top-level windows of process with PID %1!u!, child of PID %2!u!.\n"
STRING_TERM_CHILD, "Process with PID %1!u! was forcibly terminated, child of PID %2!u!.\n"
STRING_TERM_CHILD_FAILED, "Error: Unable to terminate process with PID %1!u!, child of PID %2!u!.\n"
STRING_PARAM_TOO_MUCH, "错误:无效语法。选项“%1”不允许超过“%2!d!”次。\n"
STRING_INVALID_SYNTAX, "错误:无效语法。\n"
}

View file

@ -11,7 +11,7 @@ LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL
STRINGTABLE
{
STRING_USAGE, "用法: taskkill [/?] [/f] [/im 處理程序名稱 | /pid PID]\n"
STRING_USAGE, "用法: taskkill [/?] [/f] [/im 處理程序名稱 | /pid PID] [/t]\n"
STRING_INVALID_OPTION, "錯誤: 指定了不明或不正確的命令列選項。\n"
STRING_INVALID_PARAM, "錯誤: 指定了不正確的命令列參數。\n"
STRING_MISSING_OPTION, "錯誤: 必須指定選項 /im 或 /pid 的其中之一。\n"
@ -25,6 +25,9 @@ STRINGTABLE
STRING_ENUM_FAILED, "錯誤: 無法列舉處理程序清單。\n"
STRING_TERMINATE_FAILED, "錯誤: 無法終止處理程序 '%1'。\n"
STRING_SELF_TERMINATION, "錯誤: 處理程序不允許自我終止。\n"
STRING_CLOSE_CHILD, "Close message sent to top-level windows of process with PID %1!u!, child of PID %2!u!.\n"
STRING_TERM_CHILD, "Process with PID %1!u! was forcibly terminated, child of PID %2!u!.\n"
STRING_TERM_CHILD_FAILED, "Error: Unable to terminate process with PID %1!u!, child of PID %2!u!.\n"
STRING_PARAM_TOO_MUCH, "錯誤: 無效的語法。'%1' 選項不允許超過 '%2!d!' 次。\n"
STRING_INVALID_SYNTAX, "錯誤: 無效的語法。\n"
}

View file

@ -23,6 +23,7 @@
#include <stdlib.h>
#include <windows.h>
#include <psapi.h>
#include <tlhelp32.h>
#include <wine/debug.h>
#include <wine/unicode.h>
@ -31,6 +32,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(taskkill);
static BOOL force_termination = FALSE;
static BOOL kill_child_processes = FALSE;
static WCHAR **task_list;
static unsigned int task_count;
@ -230,11 +232,74 @@ static BOOL get_process_name_from_pid(DWORD pid, WCHAR *buf, DWORD chars)
* A PID of zero causes taskkill to warn about the inability to terminate
* system processes. */
#ifndef __REACTOS__
static BOOL get_pid_creation_time(DWORD pid, FILETIME *time)
{
HANDLE process = INVALID_HANDLE_VALUE;
FILETIME t1 = { 0 }, t2 = { 0 }, t3 = { 0 };
process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
if (!process)
{
return FALSE;
}
if (!GetProcessTimes(process, time, &t1, &t2, &t3))
{
CloseHandle(process);
return FALSE;
}
CloseHandle(process);
return TRUE;
}
static void send_close_messages_tree(DWORD ppid)
{
FILETIME parent_creation_time = { 0 };
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32W pe = { 0 };
pe.dwSize = sizeof(PROCESSENTRY32W);
if (!get_pid_creation_time(ppid, &parent_creation_time) || !h)
{
CloseHandle(h);
return;
}
if (Process32FirstW(h, &pe))
{
do
{
FILETIME child_creation_time = { 0 };
struct pid_close_info info = { pe.th32ProcessID };
if (!get_pid_creation_time(pe.th32ProcessID, &child_creation_time))
{
continue;
}
// Compare creation time to avoid reuse PID, thanks to @ThFabba
if (pe.th32ParentProcessID == ppid &&
CompareFileTime(&parent_creation_time, &child_creation_time) < 0)
{
// Use recursion to browse all child processes
send_close_messages_tree(pe.th32ProcessID);
EnumWindows(pid_enum_proc, (LPARAM)&info);
if (info.found)
{
taskkill_message_printfW(STRING_CLOSE_CHILD, pe.th32ProcessID, ppid);
}
}
} while (Process32NextW(h, &pe));
}
CloseHandle(h);
}
static int send_close_messages(void)
{
DWORD *pid_list, pid_list_size;
DWORD *pid_list, pid_list_size, *pkill_list;
DWORD self_pid = GetCurrentProcessId();
unsigned int i;
int status_code = 0;
@ -246,10 +311,17 @@ static int send_close_messages(void)
return 1;
}
pkill_list = HeapAlloc(GetProcessHeap(), 0, pid_list_size * sizeof(DWORD));
if (!pkill_list)
return 1;
for (i = 0; i < task_count; i++)
{
WCHAR *p = task_list[i];
BOOL is_numeric = TRUE;
DWORD pkill_size = 0, index = 0;
memset(pkill_list, 0, pid_list_size * sizeof(DWORD));
/* Determine whether the string is not numeric. */
while (*p)
@ -261,9 +333,43 @@ static int send_close_messages(void)
}
}
// Find processes to kill
if (is_numeric)
{
DWORD pid = atoiW(task_list[i]);
WCHAR ps_name[MAX_PATH] = { 0 };
if (get_process_name_from_pid(atoiW(task_list[i]), ps_name, MAX_PATH))
{
pkill_list[pkill_size] = atoiW(task_list[i]);
pkill_size++;
}
}
else
{
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) &&
!strcmpiW(process_name, task_list[i]))
{
pkill_list[pkill_size] = pid_list[index];
pkill_size++;
}
}
}
// Can't find any process same as name or PID
if (pkill_size == 0)
{
taskkill_message_printfW(STRING_SEARCH_FAILED, task_list[i]);
status_code = 128;
continue;
}
// Try to send close messages to process in `pkill_list`
for (index = 0; index < pkill_size; index++)
{
DWORD pid = pkill_list[index];
WCHAR process_name[MAX_PATH] = { 0 };
struct pid_close_info info = { pid };
if (pid == self_pid)
@ -273,63 +379,90 @@ static int send_close_messages(void)
continue;
}
// Send close messages to child first
if (kill_child_processes)
{
send_close_messages_tree(pid);
}
get_process_name_from_pid(pid, process_name, MAX_PATH);
EnumWindows(pid_enum_proc, (LPARAM)&info);
if (info.found)
taskkill_message_printfW(STRING_CLOSE_PID_SEARCH, 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) &&
!strcmpiW(process_name, task_list[i]))
if (is_numeric)
{
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]);
taskkill_message_printfW(STRING_CLOSE_PID_SEARCH, pid);
}
else
{
taskkill_message_printfW(STRING_CLOSE_PROC_SRCH, process_name, pid);
}
}
if (!found_process)
{
taskkill_message_printfW(STRING_SEARCH_FAILED, task_list[i]);
status_code = 128;
}
}
}
HeapFree(GetProcessHeap(), 0, pkill_list);
HeapFree(GetProcessHeap(), 0, pid_list);
return status_code;
}
#endif // __REACTOS__
#ifdef __REACTOS__
static int terminate_processes(BOOL force_termination)
#else
static int terminate_processes(void)
#endif
static void terminate_process_tree(DWORD ppid)
{
DWORD *pid_list, pid_list_size;
FILETIME parent_creation_time = { 0 };
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32W pe = { 0 };
pe.dwSize = sizeof(PROCESSENTRY32W);
if (!get_pid_creation_time(ppid, &parent_creation_time) || !h)
{
CloseHandle(h);
return;
}
if (Process32FirstW(h, &pe))
{
do
{
FILETIME child_creation_time = { 0 };
if (!get_pid_creation_time(pe.th32ProcessID, &child_creation_time))
{
continue;
}
// Compare creation time to avoid reuse PID, thanks to @ThFabba
if (pe.th32ParentProcessID == ppid &&
CompareFileTime(&parent_creation_time, &child_creation_time) < 0)
{
HANDLE process = INVALID_HANDLE_VALUE;
// Use recursion to browse all child processes
terminate_process_tree(pe.th32ProcessID);
process = OpenProcess(PROCESS_TERMINATE, FALSE, pe.th32ProcessID);
if (!process)
{
continue;
}
if (!TerminateProcess(process, 0))
{
taskkill_message_printfW(STRING_TERM_CHILD_FAILED, pe.th32ProcessID, ppid);
CloseHandle(process);
continue;
}
taskkill_message_printfW(STRING_TERM_CHILD, pe.th32ProcessID, ppid);
CloseHandle(process);
}
} while (Process32NextW(h, &pe));
}
CloseHandle(h);
}
static int terminate_processes(void)
{
DWORD *pid_list, pid_list_size, *pkill_list;
DWORD self_pid = GetCurrentProcessId();
unsigned int i;
int status_code = 0;
@ -341,10 +474,17 @@ static int terminate_processes(void)
return 1;
}
pkill_list = HeapAlloc(GetProcessHeap(), 0, pid_list_size * sizeof(DWORD));
if (!pkill_list)
return 1;
for (i = 0; i < task_count; i++)
{
WCHAR *p = task_list[i];
BOOL is_numeric = TRUE;
DWORD pkill_size = 0, index = 0;
memset(pkill_list, 0, pid_list_size * sizeof(DWORD));
/* Determine whether the string is not numeric. */
while (*p)
@ -356,12 +496,44 @@ static int terminate_processes(void)
}
}
// Find processes to kill
if (is_numeric)
{
DWORD pid = atoiW(task_list[i]);
#ifndef __REACTOS__
HANDLE process;
#endif
WCHAR ps_name[MAX_PATH] = { 0 };
if (get_process_name_from_pid(atoiW(task_list[i]), ps_name, MAX_PATH))
{
pkill_list[pkill_size] = atoiW(task_list[i]);
pkill_size++;
}
}
else
{
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) &&
!strcmpiW(process_name, task_list[i]))
{
pkill_list[pkill_size] = pid_list[index];
pkill_size++;
}
}
}
// Can't find any process same as name or PID
if (!pkill_size)
{
taskkill_message_printfW(STRING_SEARCH_FAILED, task_list[i]);
status_code = 128;
continue;
}
// Try to terminate to process in `pkill_list`
for (index = 0; index < pkill_size; index++)
{
DWORD pid = pkill_list[index];
WCHAR process_name[MAX_PATH] = { 0 };
HANDLE process = INVALID_HANDLE_VALUE;
if (pid == self_pid)
{
@ -370,13 +542,14 @@ static int terminate_processes(void)
continue;
}
#ifdef __REACTOS__
if (force_termination)
// Terminate child first
if (kill_child_processes)
{
HANDLE process;
#endif
terminate_process_tree(pid);
}
process = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
if (!process)
if (get_process_name_from_pid(pid, process_name, MAX_PATH) && !process)
{
taskkill_message_printfW(STRING_SEARCH_FAILED, task_list[i]);
status_code = 128;
@ -385,102 +558,25 @@ static int terminate_processes(void)
if (!TerminateProcess(process, 0))
{
taskkill_message_printfW(STRING_TERMINATE_FAILED, task_list[i]);
taskkill_message_printfW(STRING_TERMINATE_FAILED, process_name);
status_code = 1;
CloseHandle(process);
continue;
}
taskkill_message_printfW(STRING_TERM_PID_SEARCH, pid);
CloseHandle(process);
#ifdef __REACTOS__
if (is_numeric)
{
taskkill_message_printfW(STRING_TERM_PID_SEARCH, pid);
}
else
{
struct pid_close_info info = { pid };
EnumWindows(pid_enum_proc, (LPARAM)&info);
if (info.found)
taskkill_message_printfW(STRING_CLOSE_PID_SEARCH, pid);
else
{
taskkill_message_printfW(STRING_SEARCH_FAILED, task_list[i]);
status_code = 128;
}
}
#endif
}
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) &&
!strcmpiW(process_name, task_list[i]))
{
#ifdef __REACTOS__
found_process = TRUE;
#else
HANDLE process;
#endif
if (pid_list[index] == self_pid)
{
taskkill_message(STRING_SELF_TERMINATION);
status_code = 1;
continue;
}
#ifdef __REACTOS__
if (force_termination)
{
HANDLE process;
#endif
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, 0))
{
taskkill_message_printfW(STRING_TERMINATE_FAILED, task_list[i]);
status_code = 1;
CloseHandle(process);
continue;
}
#ifndef __REACTOS__
found_process = TRUE;
#endif
taskkill_message_printfW(STRING_TERM_PROC_SEARCH, task_list[i], pid_list[index]);
CloseHandle(process);
#ifdef __REACTOS__
}
else
{
struct pid_close_info info = { pid_list[index] };
EnumWindows(pid_enum_proc, (LPARAM)&info);
taskkill_message_printfW(STRING_CLOSE_PROC_SRCH, process_name, pid_list[index]);
}
#endif
}
}
if (!found_process)
{
taskkill_message_printfW(STRING_SEARCH_FAILED, task_list[i]);
status_code = 128;
taskkill_message_printfW(STRING_TERM_PROC_SEARCH, process_name, pid);
}
CloseHandle(process);
}
}
HeapFree(GetProcessHeap(), 0, pkill_list);
HeapFree(GetProcessHeap(), 0, pid_list);
return status_code;
}
@ -535,10 +631,6 @@ static int get_argument_type(WCHAR* argument)
return OP_PARAM_INVALID;
}
/* FIXME
argument T not supported
*/
static BOOL process_arguments(int argc, WCHAR* argv[])
{
BOOL has_im = FALSE, has_pid = FALSE, has_help = FALSE;
@ -612,7 +704,14 @@ static BOOL process_arguments(int argc, WCHAR* argv[])
}
case OP_PARAM_TERMINATE_CHILD:
{
WINE_FIXME("argument T not supported\n");
if (kill_child_processes == TRUE)
{
// -t already specified
taskkill_message_printfW(STRING_PARAM_TOO_MUCH, argv[i], 1);
taskkill_message(STRING_USAGE);
return FALSE;
}
kill_child_processes = TRUE;
break;
}
case OP_PARAM_INVALID:
@ -691,8 +790,8 @@ static BOOL process_arguments(int argc, WCHAR *argv[])
argdata++;
if (!strcmpiW(opTerminateChildren, argdata))
WINE_FIXME("argument T not supported\n");
if (!strcmpiW(opForceTerminate, argdata))
kill_child_processes = TRUE;
else if (!strcmpiW(opForceTerminate, 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. */
@ -751,14 +850,10 @@ int wmain(int argc, WCHAR *argv[])
return 1;
}
#ifdef __REACTOS__
status_code = terminate_processes(force_termination);
#else
if (force_termination)
status_code = terminate_processes();
else
status_code = send_close_messages();
#endif
HeapFree(GetProcessHeap(), 0, task_list);
return status_code;

View file

@ -35,6 +35,8 @@
#define STRING_ENUM_FAILED 112
#define STRING_TERMINATE_FAILED 113
#define STRING_SELF_TERMINATION 114
#define STRING_PARAM_TOO_MUCH 115
#define STRING_INVALID_SYNTAX 116
#define STRING_CLOSE_CHILD 115
#define STRING_TERM_CHILD 116
#define STRING_TERM_CHILD_FAILED 117
#define STRING_PARAM_TOO_MUCH 118
#define STRING_INVALID_SYNTAX 119