From 2fa069d0686738aad4d8a138c4292ec685a1e5e6 Mon Sep 17 00:00:00 2001 From: Doug MacEachern Date: Wed, 28 Jul 2004 21:47:14 +0000 Subject: [PATCH] change proc_args to use the PEB --- src/os/win32/peb.c | 45 +++++++++++++++++++++++++++++++++----- src/os/win32/sigar_os.h | 2 ++ src/os/win32/win32_sigar.c | 38 ++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 6 deletions(-) diff --git a/src/os/win32/peb.c b/src/os/win32/peb.c index 5b57cf4f..5dd35e97 100644 --- a/src/os/win32/peb.c +++ b/src/os/win32/peb.c @@ -34,12 +34,12 @@ static int sigar_peb_get(sigar_t *sigar, HANDLE proc, DWORD *base) return SIGAR_OK; } -//point scratch to PATH env var -#define PEB_PATH(scratch, base) \ +//point scratch to env block +#define PEB_FIRST(scratch, base) \ scratch = sigar->peb + ((DWORD)START_ADDRESS - base) -//point scratch to EXE (assumes PEB_PATH) -#define PEB_EXE(scratch) \ +//point scratch to next string (assumes PEB_FIRST) +#define PEB_NEXT(scratch) \ scratch = scratch + (wcslen((LPWSTR)scratch) + 1) * sizeof(WCHAR) int sigar_proc_exe_name_get(sigar_t *sigar, HANDLE proc, char *name) @@ -54,9 +54,9 @@ int sigar_proc_exe_name_get(sigar_t *sigar, HANDLE proc, char *name) } //skip env PATH - PEB_PATH(scratch, base); + PEB_FIRST(scratch, base); - PEB_EXE(scratch); + PEB_NEXT(scratch); //seems common, reason unknown. if (*scratch == '\0') { @@ -70,3 +70,36 @@ int sigar_proc_exe_name_get(sigar_t *sigar, HANDLE proc, char *name) return SIGAR_OK; } + +int sigar_proc_cmdline_get(sigar_t *sigar, HANDLE proc, char *cmdline) +{ + int status; + LPBYTE scratch; + DWORD base; + WCHAR buf[MAX_PATH]; + + if ((status = sigar_peb_get(sigar, proc, &base)) != SIGAR_OK) { + return status; + } + + //skip env block + PEB_FIRST(scratch, base); + + PEB_NEXT(scratch); + //seems common, reason unknown. + if (*scratch == '\0') { + scratch += sizeof(WCHAR); + } + + PEB_NEXT(scratch); + if (*scratch == '\0') { + scratch += sizeof(WCHAR); + } + + wcsncpy(buf, (LPWSTR)scratch, MAX_PATH); + buf[MAX_PATH-1] = L'\0'; + + SIGAR_W2A(buf, cmdline, MAX_PATH); + + return SIGAR_OK; +} diff --git a/src/os/win32/sigar_os.h b/src/os/win32/sigar_os.h index e60d1094..d0e07eee 100644 --- a/src/os/win32/sigar_os.h +++ b/src/os/win32/sigar_os.h @@ -121,6 +121,8 @@ int sigar_wsa_init(sigar_t *sigar); int sigar_proc_exe_name_get(sigar_t *sigar, HANDLE proc, char *name); +int sigar_proc_cmdline_get(sigar_t *sigar, HANDLE proc, char *cmdline); + unsigned int sigar_cpu_count(sigar_t *sigar); int sigar_cpu_info_get(sigar_t *sigar, sigar_cpu_info_t *info); diff --git a/src/os/win32/win32_sigar.c b/src/os/win32/win32_sigar.c index 5179c95d..41944cd3 100644 --- a/src/os/win32/win32_sigar.c +++ b/src/os/win32/win32_sigar.c @@ -804,6 +804,10 @@ static char *getarg(char **line) return res; } +#if 0 +/* this was the first shot, works but injects a remote thread + * in the process. probably best to avoid that. + */ /* * this is ugly, but there is no alternative. * we spawn a remote thread within the process @@ -901,6 +905,40 @@ static int sigar_remote_proc_args_get(sigar_t *sigar, sigar_pid_t pid, CloseHandle(proc); return SIGAR_OK; } +#else +/* second shot, using the PEB. + * read-only, minimum access privs and in general seems to work + * better than the method above. lets roll... + */ +static int sigar_remote_proc_args_get(sigar_t *sigar, sigar_pid_t pid, + sigar_proc_args_t *procargs) +{ + int status; + char cmdline[MAX_PATH], *ptr = cmdline, *arg; + HANDLE proc = open_process(pid); + + if (!proc) { + return GetLastError(); + } + + status = sigar_proc_cmdline_get(sigar, proc, cmdline); + + CloseHandle(proc); + + if (status != SIGAR_OK) { + return status; + } + + sigar_proc_args_create(procargs); + + while (*ptr && (arg = getarg(&ptr))) { + SIGAR_PROC_ARGS_GROW(procargs); + procargs->data[procargs->number++] = strdup(arg); + } + + return SIGAR_OK; +} +#endif static int sigar_local_proc_args_get(sigar_t *sigar, sigar_pid_t pid, sigar_proc_args_t *procargs)