From f314a01aa45c876cc37b8c3c2c5df0ef4996988b Mon Sep 17 00:00:00 2001 From: Doug MacEachern Date: Tue, 21 Aug 2007 05:22:01 +0000 Subject: [PATCH] [SIGAR-67] Change windows proc_exe impl to use PEB --- src/os/win32/peb.c | 21 ++++++ src/os/win32/sigar_os.h | 3 + src/os/win32/win32_sigar.c | 146 ++++++++----------------------------- 3 files changed, 56 insertions(+), 114 deletions(-) diff --git a/src/os/win32/peb.c b/src/os/win32/peb.c index 9b08948a..942cf4c2 100644 --- a/src/os/win32/peb.c +++ b/src/os/win32/peb.c @@ -181,3 +181,24 @@ int sigar_proc_args_peb_get(sigar_t *sigar, HANDLE proc, return SIGAR_OK; } } + +int sigar_proc_env_peb_get(sigar_t *sigar, HANDLE proc, + WCHAR *buf, DWORD size) +{ + int status; + RTL_USER_PROCESS_PARAMETERS rtl; + + if ((status = sigar_rtl_get(sigar, proc, &rtl)) != SIGAR_OK) { + return status; + } + + memset(buf, '\0', size); + + /* -2 to ensure \0\0 terminator */ + if (ReadProcessMemory(proc, rtl.Environment, buf, size-2, NULL)) { + return SIGAR_OK; + } + else { + return GetLastError(); + } +} diff --git a/src/os/win32/sigar_os.h b/src/os/win32/sigar_os.h index ba37ec45..3bf27cac 100644 --- a/src/os/win32/sigar_os.h +++ b/src/os/win32/sigar_os.h @@ -564,6 +564,9 @@ int sigar_proc_exe_peb_get(sigar_t *sigar, HANDLE proc, int sigar_proc_args_peb_get(sigar_t *sigar, HANDLE proc, sigar_proc_args_t *procargs); +int sigar_proc_env_peb_get(sigar_t *sigar, HANDLE proc, + WCHAR *env, DWORD envlen); + int sigar_parse_proc_args(sigar_t *sigar, WCHAR *buf, sigar_proc_args_t *procargs); diff --git a/src/os/win32/win32_sigar.c b/src/os/win32/win32_sigar.c index 7aeff736..de073e1e 100644 --- a/src/os/win32/win32_sigar.c +++ b/src/os/win32/win32_sigar.c @@ -1332,13 +1332,8 @@ int sigar_os_proc_args_get(sigar_t *sigar, sigar_pid_t pid, } } -static int sigar_local_proc_env_get(sigar_t *sigar, sigar_pid_t pid, - sigar_proc_env_t *procenv) +static int sigar_proc_env_parse(UCHAR *ptr, sigar_proc_env_t *procenv) { - UCHAR *ptr, *env; - - env = ptr = (UCHAR*)GetEnvironmentStrings(); - while (*ptr) { char *val; int klen, vlen, status; @@ -1367,12 +1362,22 @@ static int sigar_local_proc_env_get(sigar_t *sigar, sigar_pid_t pid, if (status != SIGAR_OK) { /* not an error; just stop iterating */ - break; + return status; } ptr += klen + 1 + vlen + 1; } + return SIGAR_OK; +} + +static int sigar_local_proc_env_get(sigar_t *sigar, sigar_pid_t pid, + sigar_proc_env_t *procenv) +{ + UCHAR *env = (UCHAR*)GetEnvironmentStrings(); + + sigar_proc_env_parse(env, procenv); + FreeEnvironmentStrings(env); return SIGAR_OK; @@ -1381,115 +1386,33 @@ static int sigar_local_proc_env_get(sigar_t *sigar, sigar_pid_t pid, static int sigar_remote_proc_env_get(sigar_t *sigar, sigar_pid_t pid, sigar_proc_env_t *procenv) { - FARPROC rgetenv, fstrlen; - HANDLE proc, thread, kdll; - PVOID data=NULL; - const char *key; - char *value; - DWORD rv, thrid, bytes, datalen=0, size; - LPVOID addr; int status; + HANDLE proc = open_process(pid); + WCHAR env[4096]; - /* - * Do not FreeLibrary(kdll), see: - * http://msdn2.microsoft.com/en-us/library/ms683199.aspx - */ - if (!(kdll = GetModuleHandle("msvcrt.dll"))) { + if (!proc) { return GetLastError(); } - if (!(rgetenv = GetProcAddress(kdll, "getenv"))) { - return GetLastError(); - } + status = sigar_proc_env_peb_get(sigar, proc, env, sizeof(env)); - if (!(kdll = GetModuleHandle("kernel32.dll"))) { - return GetLastError(); - } - - if (!(fstrlen = GetProcAddress(kdll, "lstrlenA"))) { - return GetLastError(); - } - - if (!(proc = OpenProcess(MAXIMUM_ALLOWED, 0, (DWORD)pid))) { - return GetLastError(); - } - - key = procenv->key; - size = procenv->klen+1; - addr = VirtualAllocEx(proc, NULL, size, - MEM_COMMIT, PAGE_EXECUTE_READWRITE); - if (!addr) { - CloseHandle(proc); - return GetLastError(); - } - - if (!WriteProcessMemory(proc, addr, (char*)&key[0], size, 0)) { - VirtualFreeEx(proc, addr, size, 0); - CloseHandle(proc); - return GetLastError(); - } - - thread = CreateRemoteThread(proc, NULL, 0, - (LPTHREAD_START_ROUTINE)rgetenv, - addr, 0, &thrid); - if (!thread) { - VirtualFreeEx(proc, addr, size, 0); - CloseHandle(proc); - return GetLastError(); - } - - WaitForSingleObject(thread, INFINITE); - GetExitCodeThread(thread, (LPDWORD)(&data)); - CloseHandle(thread); - VirtualFreeEx(proc, addr, size, 0); - - if (!data) { - CloseHandle(proc); - return SIGAR_OK; - } - - thread = CreateRemoteThread(proc, NULL, 0, - (LPTHREAD_START_ROUTINE)fstrlen, - data, 0, &thrid); - if (!thread) { - CloseHandle(proc); - return GetLastError(); - } - - WaitForSingleObject(thread, INFINITE); - GetExitCodeThread(thread, &datalen); - CloseHandle(thread); - - if (!datalen) { - CloseHandle(proc); - return GetLastError(); - } - - value = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - datalen); - - if (!value) { - CloseHandle(proc); - return GetLastError(); - } - - if (ReadProcessMemory(proc, data, value, - datalen+1, &bytes)) - { - procenv->env_getter(procenv->data, - key, strlen(key), - value, bytes-1); - - status = SIGAR_OK; - } - else { - status = GetLastError(); - } - - HeapFree(GetProcessHeap(), 0, value); CloseHandle(proc); + if (status == SIGAR_OK) { + LPBYTE ptr = (LPBYTE)env; + DWORD size = sizeof(env); + UCHAR ent[1024]; + while ((size > 0) && (*ptr != L'\0')) { + DWORD len = (wcslen((LPWSTR)ptr) + 1) * sizeof(WCHAR); + SIGAR_W2A((WCHAR *)ptr, ent, sizeof(ent)); + if (sigar_proc_env_parse(ent, procenv) != SIGAR_OK) { + break; + } + size -= len; + ptr += len; + } + } + return status; } @@ -1523,12 +1446,7 @@ SIGAR_DECLARE(int) sigar_proc_env_get(sigar_t *sigar, sigar_pid_t pid, } } else { - if (procenv->type == SIGAR_PROC_ENV_KEY) { - return sigar_remote_proc_env_get(sigar, pid, procenv); - } - else { - return SIGAR_ENOTIMPL; - } + return sigar_remote_proc_env_get(sigar, pid, procenv); } }