Andrew Nguyen : taskkill: Implement graceful termination by process identifier.

Alexandre Julliard julliard at winehq.org
Tue Sep 21 13:59:29 CDT 2010


Module: wine
Branch: master
Commit: df4359b117acd7466ed7d9bed61e3bed713b5c45
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=df4359b117acd7466ed7d9bed61e3bed713b5c45

Author: Andrew Nguyen <anguyen at codeweavers.com>
Date:   Tue Sep 21 02:18:41 2010 -0500

taskkill: Implement graceful termination by process identifier.

---

 programs/taskkill/En.rc      |    2 +
 programs/taskkill/taskkill.c |   87 +++++++++++++++++++++++++++++++++++++++++-
 programs/taskkill/taskkill.h |    2 +
 3 files changed, 89 insertions(+), 2 deletions(-)

diff --git a/programs/taskkill/En.rc b/programs/taskkill/En.rc
index 67b2dac..ccad885 100644
--- a/programs/taskkill/En.rc
+++ b/programs/taskkill/En.rc
@@ -31,4 +31,6 @@ STRINGTABLE
     STRING_MISSING_OPTION, "Error: One of options /im or /pid must be specified.\n"
     STRING_MISSING_PARAM, "Error: Option %s expects a command line parameter.\n"
     STRING_MUTUAL_EXCLUSIVE, "Error: Options /im and /pid are mutually exclusive.\n"
+    STRING_CLOSE_PID_SEARCH, "Close message sent to top-level windows of process with PID %u.\n"
+    STRING_SEARCH_FAILED, "Error: Could not find process \"%s\".\n"
 }
diff --git a/programs/taskkill/taskkill.c b/programs/taskkill/taskkill.c
index 0ff6385..4b9fb94 100644
--- a/programs/taskkill/taskkill.c
+++ b/programs/taskkill/taskkill.c
@@ -32,6 +32,12 @@ int force_termination;
 WCHAR **task_list;
 unsigned int task_count;
 
+struct pid_close_info
+{
+    DWORD pid;
+    BOOL found;
+};
+
 static int taskkill_vprintfW(const WCHAR *msg, va_list va_args)
 {
     int wlen;
@@ -100,6 +106,78 @@ static int taskkill_message(int msg)
     return taskkill_printfW(formatW, msg_buffer);
 }
 
+/* Post WM_CLOSE to all top-level windows belonging to the process with specified PID. */
+static BOOL CALLBACK pid_enum_proc(HWND hwnd, LPARAM lParam)
+{
+    struct pid_close_info *info = (struct pid_close_info *)lParam;
+    DWORD hwnd_pid;
+
+    GetWindowThreadProcessId(hwnd, &hwnd_pid);
+
+    if (hwnd_pid == info->pid)
+    {
+        PostMessageW(hwnd, WM_CLOSE, 0, 0);
+        info->found = TRUE;
+    }
+
+    return TRUE;
+}
+
+/* The implemented task enumeration and termination behavior does not
+ * exactly match native behavior. On Windows:
+ *
+ * In the case of terminating by process name, specifying a particular
+ * process name more times than the number of running instances causes
+ * all instances to be terminated, but termination failure messages to
+ * be printed as many times as the difference between the specification
+ * quantity and the number of running instances.
+ *
+ * Successful terminations are all listed first in order, with failing
+ * terminations being listed at the end.
+ *
+ * A PID of zero causes taskkill to warn about the inability to terminate
+ * system processes. */
+static int send_close_messages(void)
+{
+    unsigned int i;
+    int status_code = 0;
+
+    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]);
+            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
+            WINE_FIXME("Termination by name is not implemented\n");
+    }
+
+    return status_code;
+}
+
 static BOOL add_to_task_list(WCHAR *name)
 {
     static unsigned int list_size = 16;
@@ -202,14 +280,19 @@ static BOOL process_arguments(int argc, WCHAR *argv[])
 
 int wmain(int argc, WCHAR *argv[])
 {
+    int status_code = 0;
+
     if (!process_arguments(argc, argv))
     {
         HeapFree(GetProcessHeap(), 0, task_list);
         return 1;
     }
 
-    WINE_FIXME("taskkill.exe functionality is not implemented\n");
+    if (force_termination)
+        WINE_FIXME("Forced termination is not implemented\n");
+    else
+        status_code = send_close_messages();
 
     HeapFree(GetProcessHeap(), 0, task_list);
-    return 0;
+    return status_code;
 }
diff --git a/programs/taskkill/taskkill.h b/programs/taskkill/taskkill.h
index 281690b..1cc09af 100644
--- a/programs/taskkill/taskkill.h
+++ b/programs/taskkill/taskkill.h
@@ -27,3 +27,5 @@
 #define STRING_MISSING_OPTION   104
 #define STRING_MISSING_PARAM    105
 #define STRING_MUTUAL_EXCLUSIVE 106
+#define STRING_CLOSE_PID_SEARCH 107
+#define STRING_SEARCH_FAILED    108




More information about the wine-cvs mailing list