Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1675)

Unified Diff: third_party/psutil/psutil/arch/mswindows/process_info.c

Issue 6246123: Moving psutil to third_party. This is first step for Media Performance test project. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: modification based on code review's comments Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/psutil/psutil/arch/mswindows/process_info.c
diff --git a/third_party/psutil/psutil/arch/mswindows/process_info.c b/third_party/psutil/psutil/arch/mswindows/process_info.c
new file mode 100644
index 0000000000000000000000000000000000000000..3713eae00910b4bde0c2ec6492de6e8a1e45143d
--- /dev/null
+++ b/third_party/psutil/psutil/arch/mswindows/process_info.c
@@ -0,0 +1,479 @@
+/*
+ * $Id: process_info.c 778 2010-11-08 19:59:08Z g.rodola $
+ *
+ * Helper functions related to fetching process information. Used by
+ * _psutil_mswindows module methods.
+ */
+
+#include <Python.h>
+#include <windows.h>
+#include <Psapi.h>
+#include <tlhelp32.h>
+
+#include "security.h"
+#include "process_info.h"
+
+
+/*
+ * NtQueryInformationProcess code taken from
+ * http://wj32.wordpress.com/2009/01/24/howto-get-the-command-line-of-processes/
+ * typedefs needed to compile against ntdll functions not exposted in the API
+ */
+typedef LONG NTSTATUS;
+
+typedef NTSTATUS (NTAPI *_NtQueryInformationProcess)(
+ HANDLE ProcessHandle,
+ DWORD ProcessInformationClass,
+ PVOID ProcessInformation,
+ DWORD ProcessInformationLength,
+ PDWORD ReturnLength
+ );
+
+typedef struct _UNICODE_STRING
+{
+ USHORT Length;
+ USHORT MaximumLength;
+ PWSTR Buffer;
+} UNICODE_STRING, *PUNICODE_STRING;
+
+typedef struct _PROCESS_BASIC_INFORMATION
+{
+ PVOID Reserved1;
+ PVOID PebBaseAddress;
+ PVOID Reserved2[2];
+ ULONG_PTR UniqueProcessId;
+ PVOID Reserved3;
+} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;
+
+
+/*
+ * Set OSError(errno=ESRCH, strerror="No such process") Python exception.
+ */
+PyObject *
+NoSuchProcess(void) {
+ PyObject *exc;
+ char *msg = strerror(ESRCH);
+ exc = PyObject_CallFunction(PyExc_OSError, "(is)", ESRCH, msg);
+ PyErr_SetObject(PyExc_OSError, exc);
+ Py_XDECREF(exc);
+ return NULL;
+}
+
+/*
+ * Set OSError(errno=EACCES, strerror="No such process") Python exception.
+ */
+PyObject *
+AccessDenied(void) {
+ PyObject *exc;
+ char *msg = strerror(EACCES);
+ exc = PyObject_CallFunction(PyExc_OSError, "(is)", EACCES, msg);
+ PyErr_SetObject(PyExc_OSError, exc);
+ Py_XDECREF(exc);
+ return NULL;
+}
+
+
+/*
+ * A wrapper around OpenProcess setting NSP exception if process
+ * no longer exists.
+ * "pid" is the process pid, "dwDesiredAccess" is the first argument
+ * exptected by OpenProcess.
+ * Return a process handle or NULL.
+ */
+HANDLE
+handle_from_pid_waccess(DWORD pid, DWORD dwDesiredAccess)
+{
+ HANDLE hProcess;
+ DWORD processExitCode = 0;
+
+ hProcess = OpenProcess(dwDesiredAccess, FALSE, pid);
+ if (hProcess == NULL) {
+ if (GetLastError() == ERROR_INVALID_PARAMETER) {
+ NoSuchProcess();
+ }
+ else {
+ PyErr_SetFromWindowsErr(0);
+ }
+ return NULL;
+ }
+
+ /* make sure the process is running */
+ GetExitCodeProcess(hProcess, &processExitCode);
+ if (processExitCode == 0) {
+ NoSuchProcess();
+ CloseHandle(hProcess);
+ return NULL;
+ }
+ return hProcess;
+}
+
+
+/*
+ * Same as handle_from_pid_waccess but implicitly uses
+ * PROCESS_QUERY_INFORMATION | PROCESS_VM_READ as dwDesiredAccess
+ * parameter for OpenProcess.
+ */
+HANDLE
+handle_from_pid(DWORD pid) {
+ DWORD dwDesiredAccess = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ;
+ return handle_from_pid_waccess(pid, dwDesiredAccess);
+}
+
+
+// fetch the PEB base address from NtQueryInformationProcess()
+PVOID
+GetPebAddress(HANDLE ProcessHandle)
+{
+ _NtQueryInformationProcess NtQueryInformationProcess =
+ (_NtQueryInformationProcess)GetProcAddress(
+ GetModuleHandleA("ntdll.dll"), "NtQueryInformationProcess");
+ PROCESS_BASIC_INFORMATION pbi;
+
+ NtQueryInformationProcess(ProcessHandle, 0, &pbi, sizeof(pbi), NULL);
+ return pbi.PebBaseAddress;
+}
+
+
+DWORD*
+get_pids(DWORD *numberOfReturnedPIDs) {
+ int procArraySz = 1024;
+
+ /* Win32 SDK says the only way to know if our process array
+ * wasn't large enough is to check the returned size and make
+ * sure that it doesn't match the size of the array.
+ * If it does we allocate a larger array and try again*/
+
+ /* Stores the actual array */
+ DWORD *procArray = NULL;
+ DWORD procArrayByteSz;
+
+ /* Stores the byte size of the returned array from enumprocesses */
+ DWORD enumReturnSz = 0;
+
+ do {
+ free(procArray);
+ procArrayByteSz = procArraySz * sizeof(DWORD);
+ procArray = malloc(procArrayByteSz);
+
+ if (! EnumProcesses(procArray, procArrayByteSz, &enumReturnSz)) {
+ free(procArray);
+ PyErr_SetFromWindowsErr(0);
+ return NULL;
+ }
+ else if (enumReturnSz == procArrayByteSz) {
+ /* Process list was too large. Allocate more space*/
+ procArraySz += 1024;
+ }
+
+ /* else we have a good list */
+
+ } while(enumReturnSz == procArraySz * sizeof(DWORD));
+
+ /* The number of elements is the returned size / size of each element */
+ *numberOfReturnedPIDs = enumReturnSz / sizeof(DWORD);
+
+ return procArray;
+}
+
+
+int
+is_system_proc(DWORD pid) {
+ HANDLE hProcess;
+
+ // Special case for PID 0 System Idle Process
+ // and PID 4 (SYSTEM)
+ if ((pid == 0) || (pid == 4)) {
+ return 1;
+ }
+ if (pid < 0) {
+ return 0;
+ }
+
+ hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
+ if (NULL == hProcess) {
+ // invalid parameter is no such process
+ if (GetLastError() == ERROR_INVALID_PARAMETER) {
+ return 0;
+ }
+
+ // access denied obviously means there's a process to deny access to...
+ if (GetLastError() == ERROR_ACCESS_DENIED) {
+ return 1;
+ }
+
+ PyErr_SetFromWindowsErr(0);
+ return -1;
+ }
+
+ return HasSystemPrivilege(hProcess);
+}
+
+
+int
+pid_is_running(DWORD pid)
+{
+ HANDLE hProcess;
+ DWORD exitCode;
+
+ // Special case for PID 0 System Idle Process
+ if (pid == 0) {
+ return 1;
+ }
+
+ if (pid < 0) {
+ return 0;
+ }
+
+ hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
+ FALSE, pid);
+ if (NULL == hProcess) {
+ // invalid parameter is no such process
+ if (GetLastError() == ERROR_INVALID_PARAMETER) {
+ CloseHandle(hProcess);
+ return 0;
+ }
+
+ // access denied obviously means there's a process to deny access to...
+ if (GetLastError() == ERROR_ACCESS_DENIED) {
+ CloseHandle(hProcess);
+ return 1;
+ }
+
+ CloseHandle(hProcess);
+ PyErr_SetFromWindowsErr(0);
+ return -1;
+ }
+
+ if (GetExitCodeProcess(hProcess, &exitCode)) {
+ CloseHandle(hProcess);
+ return (exitCode == STILL_ACTIVE);
+ }
+
+ // access denied means there's a process there so we'll assume it's running
+ if (GetLastError() == ERROR_ACCESS_DENIED) {
+ CloseHandle(hProcess);
+ return 1;
+ }
+
+ PyErr_SetFromWindowsErr(0);
+ CloseHandle(hProcess);
+ return -1;
+}
+
+
+int
+pid_in_proclist(DWORD pid)
+{
+ DWORD *proclist = NULL;
+ DWORD numberOfReturnedPIDs;
+ DWORD i;
+
+ proclist = get_pids(&numberOfReturnedPIDs);
+ if (NULL == proclist) {
+ return NULL;
+ }
+
+ for (i = 0; i < numberOfReturnedPIDs; i++) {
+ if (pid == proclist[i]) {
+ free(proclist);
+ return 1;
+ }
+ }
+
+ free(proclist);
+ return 0;
+}
+
+
+// Check exit code from a process handle. Return FALSE on an error also
+BOOL is_running(HANDLE hProcess)
+{
+ DWORD dwCode;
+
+ if (NULL == hProcess) {
+ return FALSE;
+ }
+
+ if (GetExitCodeProcess(hProcess, &dwCode)) {
+ return (dwCode == STILL_ACTIVE);
+ }
+ return FALSE;
+}
+
+
+// Return None to represent NoSuchProcess, else return NULL for
+// other exception or the name as a Python string
+PyObject*
+get_name(long pid)
+{
+ HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ PROCESSENTRY32 pe = { 0 };
+ pe.dwSize = sizeof(PROCESSENTRY32);
+
+ if( Process32First(h, &pe)) {
+ do {
+ if (pe.th32ProcessID == pid) {
+ CloseHandle(h);
+ return Py_BuildValue("s", pe.szExeFile);
+ }
+ } while(Process32Next(h, &pe));
+
+ // the process was never found, set NoSuchProcess exception
+ NoSuchProcess();
+ CloseHandle(h);
+ return NULL;
+ }
+
+ CloseHandle(h);
+ return PyErr_SetFromWindowsErr(0);
+}
+
+
+/* returns parent pid (as a Python int) for given pid or None on failure */
+PyObject*
+get_ppid(long pid)
+{
+ HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ PROCESSENTRY32 pe = { 0 };
+ pe.dwSize = sizeof(PROCESSENTRY32);
+
+ if( Process32First(h, &pe)) {
+ do {
+ if (pe.th32ProcessID == pid) {
+ //printf("PID: %i; PPID: %i\n", pid, pe.th32ParentProcessID);
+ CloseHandle(h);
+ return Py_BuildValue("I", pe.th32ParentProcessID);
+ }
+ } while(Process32Next(h, &pe));
+
+ // the process was never found, set NoSuchProcess exception
+ NoSuchProcess();
+ CloseHandle(h);
+ return NULL;
+ }
+
+ CloseHandle(h);
+ return PyErr_SetFromWindowsErr(0);
+}
+
+
+
+/*
+ * returns a Python list representing the arguments for the process
+ * with given pid or NULL on error.
+ */
+PyObject*
+get_arg_list(long pid)
+{
+ int nArgs, i;
+ LPWSTR *szArglist;
+ HANDLE hProcess;
+ PVOID pebAddress;
+ PVOID rtlUserProcParamsAddress;
+ UNICODE_STRING commandLine;
+ WCHAR *commandLineContents;
+ PyObject *arg = NULL;
+ PyObject *arg_from_wchar = NULL;
+ PyObject *argList = NULL;
+
+
+ hProcess = handle_from_pid(pid);
+ if(hProcess == NULL) {
+ return NULL;
+ }
+
+ pebAddress = GetPebAddress(hProcess);
+
+ /* get the address of ProcessParameters */
+#ifdef _WIN64
+ if (!ReadProcessMemory(hProcess, (PCHAR)pebAddress + 32,
+ &rtlUserProcParamsAddress, sizeof(PVOID), NULL))
+#else
+ if (!ReadProcessMemory(hProcess, (PCHAR)pebAddress + 0x10,
+ &rtlUserProcParamsAddress, sizeof(PVOID), NULL))
+#endif
+ {
+ //printf("Could not read the address of ProcessParameters!\n");
+ PyErr_SetFromWindowsErr(0);
+ CloseHandle(hProcess);
+ return NULL;
+ }
+
+ /* read the CommandLine UNICODE_STRING structure */
+#ifdef _WIN64
+ if (!ReadProcessMemory(hProcess, (PCHAR)rtlUserProcParamsAddress + 112,
+ &commandLine, sizeof(commandLine), NULL))
+#else
+ if (!ReadProcessMemory(hProcess, (PCHAR)rtlUserProcParamsAddress + 0x40,
+ &commandLine, sizeof(commandLine), NULL))
+#endif
+ {
+ //printf("Could not read CommandLine!\n");
+ PyErr_SetFromWindowsErr(0);
+ CloseHandle(hProcess);
+ return NULL;
+ }
+
+
+ /* allocate memory to hold the command line */
+ commandLineContents = (WCHAR *)malloc(commandLine.Length+1);
+
+ /* read the command line */
+ if (!ReadProcessMemory(hProcess, commandLine.Buffer,
+ commandLineContents, commandLine.Length, NULL))
+ {
+ //printf("Could not read the command line string!\n");
+ PyErr_SetFromWindowsErr(0);
+ CloseHandle(hProcess);
+ free(commandLineContents);
+ return NULL;
+ }
+
+ /* print the commandline */
+ //printf("%.*S\n", commandLine.Length / 2, commandLineContents);
+
+ // null-terminate the string to prevent wcslen from returning incorrect length
+ // the length specifier is in characters, but commandLine.Length is in bytes
+ commandLineContents[(commandLine.Length/sizeof(WCHAR))] = '\0';
+
+ // attemempt tp parse the command line using Win32 API, fall back on string
+ // cmdline version otherwise
+ szArglist = CommandLineToArgvW(commandLineContents, &nArgs);
+ if (NULL == szArglist) {
+ // failed to parse arglist
+ // encode as a UTF8 Python string object from WCHAR string
+ arg_from_wchar = PyUnicode_FromWideChar(commandLineContents,
+ commandLine.Length / 2);
+ #if PY_MAJOR_VERSION >= 3
+ argList = Py_BuildValue("N", PyUnicode_AsUTF8String(arg_from_wchar));
+ #else
+ argList = Py_BuildValue("N", PyUnicode_FromObject(arg_from_wchar));
+ #endif
+ }
+ else {
+ // arglist parsed as array of UNICODE_STRING, so convert each to Python
+ // string object and add to arg list
+ argList = Py_BuildValue("[]");
+ for(i=0; i<nArgs; i++) {
+ //printf("%d: %.*S (%d characters)\n", i, wcslen(szArglist[i]),
+ // szArglist[i], wcslen(szArglist[i]));
+ arg_from_wchar = PyUnicode_FromWideChar(szArglist[i],
+ wcslen(szArglist[i])
+ );
+ #if PY_MAJOR_VERSION >= 3
+ arg = PyUnicode_FromObject(arg_from_wchar);
+ #else
+ arg = PyUnicode_AsUTF8String(arg_from_wchar);
+ #endif
+ Py_XDECREF(arg_from_wchar);
+ PyList_Append(argList, arg);
+ Py_XDECREF(arg);
+ }
+ }
+
+ LocalFree(szArglist);
+ free(commandLineContents);
+ CloseHandle(hProcess);
+ return argList;
+}
+
« no previous file with comments | « third_party/psutil/psutil/arch/mswindows/process_info.h ('k') | third_party/psutil/psutil/arch/mswindows/security.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698