mirror of
https://github.com/reactos/reactos.git
synced 2025-04-26 16:40:27 +00:00
parent
49c40a2941
commit
97e7efc020
12 changed files with 290 additions and 163 deletions
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue