From 695acc2e9bfd270253e8329e831d6cfba2ca454d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Sat, 21 Jan 2017 17:23:48 +0100
Subject: programs/winedbg: Print process arguments in info threads.

---
 programs/winedbg/info.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 105 insertions(+), 2 deletions(-)

diff --git a/programs/winedbg/info.c b/programs/winedbg/info.c
index e521252ec32..d9261ecc090 100644
--- a/programs/winedbg/info.c
+++ b/programs/winedbg/info.c
@@ -562,6 +562,103 @@ static BOOL get_process_name(DWORD pid, PROCESSENTRY32* entry)
     return ret;
 }
 
+static BOOL read_process_memory(HANDLE process, const void *ptr, void *buffer, SIZE_T length)
+{
+    SIZE_T read;
+    return ReadProcessMemory(process, ptr, buffer, length, &read) && (read == length);
+}
+
+static BOOL get_process_cmdline(HANDLE process, PEB *peb, UNICODE_STRING *cmdline)
+{
+    RTL_USER_PROCESS_PARAMETERS *params;
+
+    if (!read_process_memory(process, &peb->ProcessParameters, &params, sizeof(params)))
+        return FALSE;
+
+    if (!read_process_memory(process, &params->CommandLine, cmdline, sizeof(*cmdline)))
+        return FALSE;
+
+    return TRUE;
+}
+
+static BOOL get_process_cmdline_wow64(HANDLE process, PEB *peb, UNICODE_STRING *cmdline)
+{
+    DWORD params;
+    struct
+    {
+        USHORT Length;
+        USHORT MaximumLength;
+        DWORD  Buffer;
+    } cmdline32;
+
+    /* &peb->ProcessParameters */
+    if (!read_process_memory(process, (char *)peb + 0x10, &params, sizeof(params)))
+        return FALSE;
+
+    /* &params->CommandLine */
+    if (!read_process_memory(process, (char *)(DWORD_PTR)params + 0x40, &cmdline32, sizeof(cmdline32)))
+        return FALSE;
+
+    cmdline->Length = cmdline32.Length;
+    cmdline->MaximumLength = cmdline32.MaximumLength;
+    cmdline->Buffer = (WCHAR *)(DWORD_PTR)cmdline32.Buffer;
+    return TRUE;
+}
+
+static char *get_process_args(DWORD pid)
+{
+    PROCESS_BASIC_INFORMATION info;
+    BOOL self_wow64, process_wow64;
+    UNICODE_STRING cmdline;
+    WCHAR *tempW = NULL;
+    char *args = NULL;
+    HANDLE process;
+    DWORD len;
+    BOOL ret;
+
+    if (!(process = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, pid)))
+        return FALSE;
+    if (NtQueryInformationProcess(process, ProcessBasicInformation, &info, sizeof(info), NULL))
+        goto done;
+
+    IsWow64Process(GetCurrentProcess(), &self_wow64);
+    if (!IsWow64Process(process, &process_wow64))
+        goto done;
+
+    if (process_wow64 == self_wow64)
+        ret = get_process_cmdline(process, info.PebBaseAddress, &cmdline);
+    else if (!self_wow64 && process_wow64)
+        ret = get_process_cmdline_wow64(process, info.PebBaseAddress, &cmdline);
+    else
+        ret = FALSE; /* can't read process args of 64-bit process with 32-bit winedbg */
+
+    if (!ret) goto done;
+
+    /* protect against malicious content */
+    if (cmdline.Length > 4096 || (cmdline.Length & 1))
+        goto done;
+
+    if (!(tempW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cmdline.Length + 2)))
+        goto done;
+    if (!read_process_memory(process, cmdline.Buffer, tempW, cmdline.Length))
+        goto done;
+
+    if (!(len = WideCharToMultiByte(CP_ACP, 0, tempW, -1, NULL, 0, NULL, NULL)))
+        goto done;
+    if (!(args = HeapAlloc(GetProcessHeap(), 0, len)))
+        goto done;
+    if (!WideCharToMultiByte(CP_ACP, 0, tempW, -1, args, len, NULL, NULL))
+    {
+        HeapFree(GetProcessHeap(), 0, args);
+        args = NULL;
+    }
+
+done:
+    HeapFree(GetProcessHeap(), 0, tempW);
+    CloseHandle(process);
+    return args;
+}
+
 void info_win32_threads(void)
 {
     HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
@@ -589,6 +686,7 @@ void info_win32_threads(void)
 		    struct dbg_process*	p = dbg_get_process(entry.th32OwnerProcessID);
                     PROCESSENTRY32 pcs_entry;
                     const char* exename;
+                    char *args;
 
                     if (p)
                         exename = dbg_W2A(p->imageName, -1);
@@ -597,8 +695,13 @@ void info_win32_threads(void)
                     else
                         exename = "";
 
-		    dbg_printf("%08x%s %s\n",
-                               entry.th32OwnerProcessID, p ? " (D)" : "", exename);
+                    dbg_printf("%08x%s %s\n", entry.th32OwnerProcessID, p ? " (D)" : "", exename);
+                    args = get_process_args(entry.th32OwnerProcessID);
+                    if (args)
+                    {
+                        dbg_printf("\t[%s]\n", args);
+                        HeapFree(GetProcessHeap(), 0, args);
+                    }
                     lastProcessId = entry.th32OwnerProcessID;
 		}
                 dbg_printf("\t%08x %4d%s\n",
-- 
2.11.0

