https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5874c66e41391e25f9d61…
commit 5874c66e41391e25f9d612694d4fa73e584fed91
Author: He Yang <1160386205(a)qq.com>
AuthorDate: Fri Apr 3 10:37:53 2020 -0500
Commit: GitHub <noreply(a)github.com>
CommitDate: Fri Apr 3 17:37:53 2020 +0200
[TASKKILL] Improve taskkill utility (#2459)
Make the argument process of command utility "taskkill" behave same as what
Windows does.
Now options are no longer detected as parameters when placed after options that accept
one.
For example, `taskkill /im /f` will no longer regard `/f` as a process name.
If `/?` and `/f` options appear more than once, an error will be reported, telling
they are not allowed more than once.
(e.g. `taskkill /f /pid 1000 /f`)
If only one option `/f` is given without `/pid` or `/im`, an eerror will be reported,
telling that one must specify `/pid` or `/im`.
(e.g. `taskkill /f`)
Additional changes:
- Combine SendCloseMessages() and TerminateProcesses() functions.
- Protect new written code with `#ifdef __REACTOS__`
---
base/applications/cmdutils/taskkill/lang/de-DE.rc | 2 +
base/applications/cmdutils/taskkill/lang/en-US.rc | 2 +
base/applications/cmdutils/taskkill/lang/it-IT.rc | 2 +
base/applications/cmdutils/taskkill/lang/pl-PL.rc | 2 +
base/applications/cmdutils/taskkill/lang/ro-RO.rc | 2 +
base/applications/cmdutils/taskkill/lang/ru-RU.rc | 2 +
base/applications/cmdutils/taskkill/lang/sq-AL.rc | 2 +
base/applications/cmdutils/taskkill/lang/tr-TR.rc | 2 +
base/applications/cmdutils/taskkill/lang/zh-CN.rc | 7 +-
base/applications/cmdutils/taskkill/lang/zh-TW.rc | 2 +
base/applications/cmdutils/taskkill/taskkill.c | 320 ++++++++++++++++++++++
base/applications/cmdutils/taskkill/taskkill.h | 3 +
12 files changed, 347 insertions(+), 1 deletion(-)
diff --git a/base/applications/cmdutils/taskkill/lang/de-DE.rc
b/base/applications/cmdutils/taskkill/lang/de-DE.rc
index ea43a9bae17..54a408fcc8a 100644
--- a/base/applications/cmdutils/taskkill/lang/de-DE.rc
+++ b/base/applications/cmdutils/taskkill/lang/de-DE.rc
@@ -16,4 +16,6 @@ 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_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"
}
diff --git a/base/applications/cmdutils/taskkill/lang/en-US.rc
b/base/applications/cmdutils/taskkill/lang/en-US.rc
index 1e87249cb11..e34b34bad25 100644
--- a/base/applications/cmdutils/taskkill/lang/en-US.rc
+++ b/base/applications/cmdutils/taskkill/lang/en-US.rc
@@ -16,4 +16,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_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"
}
diff --git a/base/applications/cmdutils/taskkill/lang/it-IT.rc
b/base/applications/cmdutils/taskkill/lang/it-IT.rc
index 0a2cb322ae7..886c4a9a3c1 100644
--- a/base/applications/cmdutils/taskkill/lang/it-IT.rc
+++ b/base/applications/cmdutils/taskkill/lang/it-IT.rc
@@ -23,4 +23,6 @@ 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_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"
}
diff --git a/base/applications/cmdutils/taskkill/lang/pl-PL.rc
b/base/applications/cmdutils/taskkill/lang/pl-PL.rc
index c907dc72b62..d66da03ec6e 100644
--- a/base/applications/cmdutils/taskkill/lang/pl-PL.rc
+++ b/base/applications/cmdutils/taskkill/lang/pl-PL.rc
@@ -16,4 +16,6 @@ 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_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"
}
diff --git a/base/applications/cmdutils/taskkill/lang/ro-RO.rc
b/base/applications/cmdutils/taskkill/lang/ro-RO.rc
index d050c6b4b80..649dfc47ed2 100644
--- a/base/applications/cmdutils/taskkill/lang/ro-RO.rc
+++ b/base/applications/cmdutils/taskkill/lang/ro-RO.rc
@@ -18,4 +18,6 @@ STRINGTABLE
STRING_ENUM_FAILED, "Eroare: Procesele nu au putut fi enumerate.\n"
STRING_TERMINATE_FAILED, "Eroare: Procesul «%1» nu poate fi oprit.\n"
STRING_SELF_TERMINATION, "Eroare: Auto-terminarea nu este permisă.\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"
}
diff --git a/base/applications/cmdutils/taskkill/lang/ru-RU.rc
b/base/applications/cmdutils/taskkill/lang/ru-RU.rc
index 5002db0732f..9a671e98b45 100644
--- a/base/applications/cmdutils/taskkill/lang/ru-RU.rc
+++ b/base/applications/cmdutils/taskkill/lang/ru-RU.rc
@@ -18,4 +18,6 @@ STRINGTABLE
STRING_ENUM_FAILED, "Ошибка: Не удается получить список процессов.\n"
STRING_TERMINATE_FAILED, "Ошибка: Не удается завершить процесс
""%1"".\n"
STRING_SELF_TERMINATION, "Ошибка: Процесс не может завершить сам себя.\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"
}
diff --git a/base/applications/cmdutils/taskkill/lang/sq-AL.rc
b/base/applications/cmdutils/taskkill/lang/sq-AL.rc
index c4ee3dd1bc3..85878177488 100644
--- a/base/applications/cmdutils/taskkill/lang/sq-AL.rc
+++ b/base/applications/cmdutils/taskkill/lang/sq-AL.rc
@@ -20,4 +20,6 @@ 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_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"
}
diff --git a/base/applications/cmdutils/taskkill/lang/tr-TR.rc
b/base/applications/cmdutils/taskkill/lang/tr-TR.rc
index 97ebbc186a8..fec4c4a07de 100644
--- a/base/applications/cmdutils/taskkill/lang/tr-TR.rc
+++ b/base/applications/cmdutils/taskkill/lang/tr-TR.rc
@@ -18,4 +18,6 @@ STRINGTABLE
STRING_ENUM_FAILED, "Yanlışlık: İşlem dizelgesi numaralandırılamaz.\n"
STRING_TERMINATE_FAILED, "Yanlışlık: ""%1"" işlemi
sonlandırılamaz.\n"
STRING_SELF_TERMINATION, "Yanlışlık: İşlemi kendi kendine sonlandırmaya izin
verilmedi.\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"
}
diff --git a/base/applications/cmdutils/taskkill/lang/zh-CN.rc
b/base/applications/cmdutils/taskkill/lang/zh-CN.rc
index f6980a6932d..e6b2c272d1d 100644
--- a/base/applications/cmdutils/taskkill/lang/zh-CN.rc
+++ b/base/applications/cmdutils/taskkill/lang/zh-CN.rc
@@ -1,4 +1,7 @@
-/* Simplified Chinese translation by Henry Tang Ih 2016 (henrytang2(a)hotmail.com) */
+/* Simplified Chinese translation by
+Henry Tang Ih 2016 (henrytang2(a)hotmail.com)
+He Yang 2020 (1160386205(a)qq.com)
+ */
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
@@ -18,4 +21,6 @@ STRINGTABLE
STRING_ENUM_FAILED, "错误: 无法枚举进程列表。\n"
STRING_TERMINATE_FAILED, "错误: 无法终止进程 ""%1""。\n"
STRING_SELF_TERMINATION, "错误: 不允许终止自身。\n"
+ STRING_PARAM_TOO_MUCH, "错误:无效语法。选项 '%1' 不允许超过 '%2!d!'
次。\n"
+ STRING_INVALID_SYNTAX, "错误:无效语法。\n"
}
diff --git a/base/applications/cmdutils/taskkill/lang/zh-TW.rc
b/base/applications/cmdutils/taskkill/lang/zh-TW.rc
index afc52383bab..16b37cae210 100644
--- a/base/applications/cmdutils/taskkill/lang/zh-TW.rc
+++ b/base/applications/cmdutils/taskkill/lang/zh-TW.rc
@@ -18,4 +18,6 @@ STRINGTABLE
STRING_ENUM_FAILED, "錯誤: 無法枚舉處理序清單。\n"
STRING_TERMINATE_FAILED, "錯誤: 無法終止處理序 ""%1""。\n"
STRING_SELF_TERMINATION, "錯誤: 不允許自我終止的處理序。\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"
}
diff --git a/base/applications/cmdutils/taskkill/taskkill.c
b/base/applications/cmdutils/taskkill/taskkill.c
index 59ce98dc6dc..b78d461a6fa 100644
--- a/base/applications/cmdutils/taskkill/taskkill.c
+++ b/base/applications/cmdutils/taskkill/taskkill.c
@@ -34,6 +34,26 @@ static BOOL force_termination = FALSE;
static WCHAR **task_list;
static unsigned int task_count;
+#ifdef __REACTOS__
+
+static WCHAR opForceTerminate[] = L"f";
+static WCHAR opImage[] = L"im";
+static WCHAR opPID[] = L"pid";
+static WCHAR opHelp[] = L"?";
+static WCHAR opTerminateChildren[] = L"t";
+
+static PWCHAR opList[] = {opForceTerminate, opImage, opPID, opHelp,
opTerminateChildren};
+
+#define OP_PARAM_INVALID -1
+
+#define OP_PARAM_FORCE_TERMINATE 0
+#define OP_PARAM_IMAGE 1
+#define OP_PARAM_PID 2
+#define OP_PARAM_HELP 3
+#define OP_PARAM_TERMINATE_CHILD 4
+
+#endif
+
struct pid_close_info
{
DWORD pid;
@@ -208,6 +228,153 @@ 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. */
+
+
+#ifdef __REACTOS__
+
+static int terminate_processes(BOOL force_termination)
+{
+ 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];
+ BOOL is_numeric = TRUE;
+
+ /* Determine whether the string is not numeric. */
+ while (*p)
+ {
+ if (!isdigitW(*p++))
+ {
+ is_numeric = FALSE;
+ break;
+ }
+ }
+
+ if (is_numeric)
+ {
+ DWORD pid = atoiW(task_list[i]);
+
+ if (pid == self_pid)
+ {
+ taskkill_message(STRING_SELF_TERMINATION);
+ status_code = 1;
+ continue;
+ }
+
+ if (force_termination)
+ {
+ HANDLE process;
+ process = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
+ 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;
+ }
+
+ taskkill_message_printfW(STRING_TERM_PID_SEARCH, pid);
+ CloseHandle(process);
+ }
+ 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;
+ }
+ }
+ }
+ 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]))
+ {
+ found_process = TRUE;
+
+ if (pid_list[index] == self_pid)
+ {
+ taskkill_message(STRING_SELF_TERMINATION);
+ status_code = 1;
+ continue;
+ }
+
+ if (force_termination)
+ {
+ HANDLE process;
+
+ 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;
+ }
+
+ taskkill_message_printfW(STRING_TERM_PROC_SEARCH, task_list[i],
pid_list[index]);
+ CloseHandle(process);
+ }
+ 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]);
+ }
+ }
+ }
+
+ if (!found_process)
+ {
+ taskkill_message_printfW(STRING_SEARCH_FAILED, task_list[i]);
+ status_code = 128;
+ }
+ }
+ }
+
+ HeapFree(GetProcessHeap(), 0, pid_list);
+ return status_code;
+}
+
+#else
+
static int send_close_messages(void)
{
DWORD *pid_list, pid_list_size;
@@ -412,6 +579,9 @@ static int terminate_processes(void)
return status_code;
}
+#endif // __REACTOS__
+
+
static BOOL add_to_task_list(WCHAR *name)
{
static unsigned int list_size = 16;
@@ -440,6 +610,146 @@ static BOOL add_to_task_list(WCHAR *name)
return TRUE;
}
+#ifdef __REACTOS__
+
+static int get_argument_type(WCHAR* argument)
+{
+ int i;
+
+ if (argument[0] != L'/' && argument[0] != L'-')
+ {
+ return OP_PARAM_INVALID;
+ }
+ argument++;
+
+ for (i = 0; i < _countof(opList); i++)
+ {
+ if (!strcmpiW(opList[i], argument))
+ {
+ return i;
+ }
+ }
+ 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;
+
+ if (argc > 1)
+ {
+ int i;
+ for (i = 1; i < argc; i++)
+ {
+ int argument = get_argument_type(argv[i]);
+
+ switch (argument)
+ {
+ case OP_PARAM_FORCE_TERMINATE:
+ {
+ if (force_termination == TRUE)
+ {
+ // -f already specified
+ taskkill_message_printfW(STRING_PARAM_TOO_MUCH, argv[i], 1);
+ taskkill_message(STRING_USAGE);
+ return FALSE;
+ }
+ force_termination = TRUE;
+ break;
+ }
+ case OP_PARAM_IMAGE:
+ case OP_PARAM_PID:
+ {
+ if (!argv[i + 1])
+ {
+ taskkill_message_printfW(STRING_MISSING_PARAM, argv[i]);
+ taskkill_message(STRING_USAGE);
+ return FALSE;
+ }
+
+ if (argument == OP_PARAM_IMAGE)
+ has_im = TRUE;
+ if (argument == OP_PARAM_PID)
+ has_pid = TRUE;
+
+ if (has_im && has_pid)
+ {
+ taskkill_message(STRING_MUTUAL_EXCLUSIVE);
+ taskkill_message(STRING_USAGE);
+ return FALSE;
+ }
+
+ if (get_argument_type(argv[i + 1]) != OP_PARAM_INVALID)
+ {
+ taskkill_message_printfW(STRING_MISSING_PARAM, argv[i]);
+ taskkill_message(STRING_USAGE);
+ return FALSE;
+ }
+
+ if (!add_to_task_list(argv[++i])) // add next parameters to task_list
+ return FALSE;
+
+ break;
+ }
+ case OP_PARAM_HELP:
+ {
+ if (has_help == TRUE)
+ {
+ // -? already specified
+ taskkill_message_printfW(STRING_PARAM_TOO_MUCH, argv[i], 1);
+ taskkill_message(STRING_USAGE);
+ return FALSE;
+ }
+ has_help = TRUE;
+ break;
+ }
+ case OP_PARAM_TERMINATE_CHILD:
+ {
+ WINE_FIXME("argument T not supported\n");
+ break;
+ }
+ case OP_PARAM_INVALID:
+ default:
+ {
+ taskkill_message(STRING_INVALID_OPTION);
+ taskkill_message(STRING_USAGE);
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ if (has_help)
+ {
+ if (argc > 2) // any parameters other than -? is specified
+ {
+ taskkill_message(STRING_INVALID_SYNTAX);
+ taskkill_message(STRING_USAGE);
+ return FALSE;
+ }
+ else
+ {
+ taskkill_message(STRING_USAGE);
+ exit(0);
+ }
+ }
+ else if ((!has_im) && (!has_pid)) // has_help == FALSE
+ {
+ // both has_im and has_pid are missing (maybe -fi option is missing too, if
implemented later)
+ taskkill_message(STRING_MISSING_OPTION);
+ taskkill_message(STRING_USAGE);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#else
+
/* FIXME Argument processing does not match behavior observed on Windows.
* Stringent argument counting and processing is performed, and unrecognized
* options are detected as parameters when placed after options that accept one. */
@@ -526,6 +836,8 @@ static BOOL process_arguments(int argc, WCHAR *argv[])
return TRUE;
}
+#endif // __REACTOS__
+
int wmain(int argc, WCHAR *argv[])
{
int status_code = 0;
@@ -536,11 +848,19 @@ 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;
}
diff --git a/base/applications/cmdutils/taskkill/taskkill.h
b/base/applications/cmdutils/taskkill/taskkill.h
index 7972a156f3c..03312fa8c9c 100644
--- a/base/applications/cmdutils/taskkill/taskkill.h
+++ b/base/applications/cmdutils/taskkill/taskkill.h
@@ -35,3 +35,6 @@
#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
+