From: Zhiyi Zhang zzhang@codeweavers.com
--- programs/tasklist/tasklist.c | 79 +++++++++++++++++++++++++++--- programs/tasklist/tasklist.h | 9 ++++ programs/tasklist/tasklist.rc | 1 + programs/tasklist/tests/tasklist.c | 43 ++++++++++++++++ 4 files changed, 124 insertions(+), 8 deletions(-)
diff --git a/programs/tasklist/tasklist.c b/programs/tasklist/tasklist.c index 48d9b438e84..c8cb8804c3a 100644 --- a/programs/tasklist/tasklist.c +++ b/programs/tasklist/tasklist.c @@ -33,6 +33,14 @@ static int tasklist_message(int msg) return wprintf(msg_buffer); }
+static int tasklist_error(int msg) +{ + WCHAR msg_buffer[MAXSTRING]; + + LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer, ARRAY_SIZE(msg_buffer)); + return fwprintf(stderr, msg_buffer); +} + static PROCESSENTRY32W *enumerate_processes(DWORD *process_count) { unsigned int alloc_count = 128; @@ -112,7 +120,8 @@ static NUMBERFMTW *tasklist_get_memory_format(void) return &format; }
-static void tasklist_get_header(struct tasklist_process_info *header) +static void tasklist_get_header(const struct tasklist_options *options, + struct tasklist_process_info *header) { HMODULE module;
@@ -122,6 +131,14 @@ static void tasklist_get_header(struct tasklist_process_info *header) LoadStringW(module, STRING_SESSION_NAME, header->session_name, ARRAY_SIZE(header->session_name)); LoadStringW(module, STRING_SESSION_NUMBER, header->session_number, ARRAY_SIZE(header->session_number)); LoadStringW(module, STRING_MEM_USAGE, header->memory_usage, ARRAY_SIZE(header->memory_usage)); + if (options->format == LIST) + { + wcscat(header->image_name, L":"); + wcscat(header->pid, L":"); + wcscat(header->session_name, L":"); + wcscat(header->session_number, L":"); + wcscat(header->memory_usage, L":"); + } }
static BOOL tasklist_get_process_info(const PROCESSENTRY32W *process_entry, struct tasklist_process_info *info) @@ -169,14 +186,19 @@ static void tasklist_print(const struct tasklist_options *options) PROCESSENTRY32W *process_list; DWORD process_count, i;
- wprintf(L"\n"); + if (options->format == TABLE) + wprintf(L"\n");
+ tasklist_get_header(options, &header); if (!options->no_header) { - tasklist_get_header(&header); - wprintf(L"%-25.25s %8.8s %-16.16s %11.11s %12.12s\n" - L"========================= ======== ================ =========== ============\n", - header.image_name, header.pid, header.session_name, header.session_number, header.memory_usage); + if (options->format == TABLE) + wprintf(L"%-25.25s %8.8s %-16.16s %11.11s %12.12s\n" + L"========================= ======== ================ =========== ============\n", + header.image_name, header.pid, header.session_name, header.session_number, header.memory_usage); + else if (options->format == CSV) + wprintf(L""%s","%s","%s","%s","%s"\n", + header.image_name, header.pid, header.session_name, header.session_number, header.memory_usage); }
process_list = enumerate_processes(&process_count); @@ -185,8 +207,24 @@ static void tasklist_print(const struct tasklist_options *options) if (!tasklist_get_process_info(&process_list[i], &info)) continue;
- wprintf(L"%-25.25s %8.8s %-16.16s %11.11s %12s\n", - info.image_name, info.pid, info.session_name, info.session_number, info.memory_usage); + if (options->format == TABLE) + wprintf(L"%-25.25s %8.8s %-16.16s %11.11s %12s\n", + info.image_name, info.pid, info.session_name, info.session_number, info.memory_usage); + else if (options->format == CSV) + wprintf(L""%s","%s","%s","%s","%s"\n", + info.image_name, info.pid, info.session_name, info.session_number, info.memory_usage); + else if (options->format == LIST) + wprintf(L"\n" + L"%-13.13s %s\n" + L"%-13.13s %s\n" + L"%-13.13s %s\n" + L"%-13.13s %s\n" + L"%-13.13s %s\n", + header.image_name, info.image_name, + header.pid, info.pid, + header.session_name, info.session_name, + header.session_number, info.session_number, + header.memory_usage, info.memory_usage); } free(process_list); } @@ -211,6 +249,31 @@ int __cdecl wmain(int argc, WCHAR *argv[]) { options.no_header = TRUE; } + else if (!wcsicmp(argv[i], L"/fo")) + { + if (i + 1 >= argc) + { + tasklist_error(STRING_INVALID_SYNTAX); + return 1; + } + else if (!wcsicmp(argv[i + 1], L"TABLE")) + { + options.format = TABLE; + } + else if (!wcsicmp(argv[i + 1], L"CSV")) + { + options.format = CSV; + } + else if (!wcsicmp(argv[i + 1], L"LIST")) + { + options.format = LIST; + } + else + { + tasklist_error(STRING_INVALID_SYNTAX); + return 1; + } + } else { WINE_WARN("Ignoring option %s\n", wine_dbgstr_w(argv[i])); diff --git a/programs/tasklist/tasklist.h b/programs/tasklist/tasklist.h index 6add1f30277..5e4e90960ea 100644 --- a/programs/tasklist/tasklist.h +++ b/programs/tasklist/tasklist.h @@ -27,6 +27,14 @@ #define STRING_SESSION_NUMBER 105 #define STRING_MEM_USAGE 106 #define STRING_K 107 +#define STRING_INVALID_SYNTAX 108 + +enum tasklist_format +{ + TABLE = 0, + CSV = 1, + LIST = 2, +};
struct tasklist_process_info { @@ -40,4 +48,5 @@ struct tasklist_process_info struct tasklist_options { BOOL no_header; + enum tasklist_format format; }; diff --git a/programs/tasklist/tasklist.rc b/programs/tasklist/tasklist.rc index 5b5e72c4a67..f92b0348f72 100644 --- a/programs/tasklist/tasklist.rc +++ b/programs/tasklist/tasklist.rc @@ -32,6 +32,7 @@ STRINGTABLE STRING_SESSION_NUMBER, "Session#" STRING_MEM_USAGE, "Mem Usage" STRING_K, "K" + STRING_INVALID_SYNTAX, "ERROR: Invalid syntax\n" }
#define WINE_FILEDESCRIPTION_STR "Wine tasklist" diff --git a/programs/tasklist/tests/tasklist.c b/programs/tasklist/tests/tasklist.c index 2c4d77855b0..011bfdeb382 100644 --- a/programs/tasklist/tests/tasklist.c +++ b/programs/tasklist/tests/tasklist.c @@ -122,6 +122,48 @@ static void test_no_header(void) ok(!pos, "Got header.\n"); }
+static void test_format(void) +{ + char *pos; + + /* /fo */ + run_tasklist("/fo", 1); + ok(stdout_size == 0, "Unexpected stdout buffer size %ld.\n", stdout_size); + ok(stderr_size > 0, "Unexpected stderr buffer size %ld.\n", stderr_size); + + /* /fo invalid */ + run_tasklist("/fo invalid", 1); + ok(stdout_size == 0, "Unexpected stdout buffer size %ld.\n", stdout_size); + ok(stderr_size > 0, "Unexpected stderr buffer size %ld.\n", stderr_size); + + /* /fo TABLE */ + run_tasklist("/fo TABLE", 0); + ok(stdout_size > 0, "Unexpected stdout buffer size %ld.\n", stdout_size); + ok(stderr_size == 0, "Unexpected stderr buffer size %ld.\n", stderr_size); + pos = strstr(stdout_buffer, "\r\n" + "Image Name PID Session Name Session# Mem Usage\r\n" + "========================= ======== ================ =========== ============\r\n"); + ok(pos == stdout_buffer, "Got the wrong first line.\n"); + pos = strstr(stdout_buffer, "tasklist.exe"); + ok(!!pos, "Failed to list tasklist.exe.\n"); + + /* /fo CSV */ + run_tasklist("/fo CSV", 0); + ok(stdout_size > 0, "Unexpected stdout buffer size %ld.\n", stdout_size); + ok(stderr_size == 0, "Unexpected stderr buffer size %ld.\n", stderr_size); + pos = strstr(stdout_buffer, ""Image Name","PID","Session Name","Session#","Mem Usage""); + ok(pos == stdout_buffer, "Got the wrong first line.\n"); + pos = strstr(stdout_buffer, ""tasklist.exe","); + ok(!!pos, "Failed to list tasklist.exe.\n"); + + /* /fo LIST */ + run_tasklist("/fo LIST", 0); + ok(stdout_size > 0, "Unexpected stdout buffer size %ld.\n", stdout_size); + ok(stderr_size == 0, "Unexpected stderr buffer size %ld.\n", stderr_size); + pos = strstr(stdout_buffer, "Image Name: tasklist.exe"); + ok(!!pos, "Failed to list tasklist.exe.\n"); +} + START_TEST(tasklist) { if (PRIMARYLANGID(GetUserDefaultUILanguage()) != LANG_ENGLISH) @@ -132,4 +174,5 @@ START_TEST(tasklist)
test_basic(); test_no_header(); + test_format(); }