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

Unified Diff: third_party/psutil/psutil/_psutil_mswindows.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
« no previous file with comments | « third_party/psutil/psutil/_psutil_mswindows.h ('k') | third_party/psutil/psutil/_psutil_osx.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/psutil/psutil/_psutil_mswindows.c
diff --git a/third_party/psutil/psutil/_psutil_mswindows.c b/third_party/psutil/psutil/_psutil_mswindows.c
new file mode 100644
index 0000000000000000000000000000000000000000..94f9057e6641493a8d4720ff505dcee8422189d8
--- /dev/null
+++ b/third_party/psutil/psutil/_psutil_mswindows.c
@@ -0,0 +1,1655 @@
+/*
+ * $Id: _psutil_mswindows.c 796 2010-11-12 20:31:28Z g.rodola $
+ *
+ * Windows platform-specific module methods for _psutil_mswindows
+ */
+
+#include <Python.h>
+#include <windows.h>
+#include <Psapi.h>
+#include <time.h>
+#include <lm.h>
+#include <tchar.h>
+#include <tlhelp32.h>
+#include <iphlpapi.h>
+
+#include "_psutil_mswindows.h"
+#include "arch/mswindows/security.h"
+#include "arch/mswindows/process_info.h"
+#include "arch/mswindows/process_handles.h"
+
+
+// ------------------------ Python init ---------------------------
+
+static PyMethodDef
+PsutilMethods[] =
+{
+ // --- per-process functions
+
+ {"get_process_name", get_process_name, METH_VARARGS,
+ "Return process name"},
+ {"get_process_cmdline", get_process_cmdline, METH_VARARGS,
+ "Return process cmdline as a list of cmdline arguments"},
+ {"get_process_ppid", get_process_ppid, METH_VARARGS,
+ "Return process ppid as an integer"},
+ {"kill_process", kill_process, METH_VARARGS,
+ "Kill the process identified by the given PID"},
+ {"get_process_cpu_times", get_process_cpu_times, METH_VARARGS,
+ "Return tuple of user/kern time for the given PID"},
+ {"get_process_create_time", get_process_create_time, METH_VARARGS,
+ "Return a float indicating the process create time expressed in "
+ "seconds since the epoch"},
+ {"get_memory_info", get_memory_info, METH_VARARGS,
+ "Return a tuple of RSS/VMS memory information"},
+ {"get_process_cwd", get_process_cwd, METH_VARARGS,
+ "Return process current working directory"},
+ {"suspend_process", suspend_process, METH_VARARGS,
+ "Suspend a process"},
+ {"resume_process", resume_process, METH_VARARGS,
+ "Resume a process"},
+ {"get_process_open_files", get_process_open_files, METH_VARARGS,
+ "Return files opened by process"},
+ {"_QueryDosDevice", _QueryDosDevice, METH_VARARGS,
+ "QueryDosDevice binding"},
+ {"get_process_username", get_process_username, METH_VARARGS,
+ "Return the username of a process"},
+ {"get_process_connections", get_process_connections, METH_VARARGS,
+ "Return the network connections of a process"},
+ {"get_process_num_threads", get_process_num_threads, METH_VARARGS,
+ "Return the network connections of a process"},
+
+ // --- system-related functions
+
+ {"get_pid_list", get_pid_list, METH_VARARGS,
+ "Returns a list of PIDs currently running on the system"},
+ {"pid_exists", pid_exists, METH_VARARGS,
+ "Determine if the process exists in the current process list."},
+ {"get_num_cpus", get_num_cpus, METH_VARARGS,
+ "Returns the number of CPUs on the system"},
+ {"get_system_uptime", get_system_uptime, METH_VARARGS,
+ "Return system uptime"},
+ {"get_total_phymem", get_total_phymem, METH_VARARGS,
+ "Return the total amount of physical memory, in bytes"},
+ {"get_total_virtmem", get_total_virtmem, METH_VARARGS,
+ "Return the total amount of virtual memory, in bytes"},
+ {"get_avail_phymem", get_avail_phymem, METH_VARARGS,
+ "Return the amount of available physical memory, in bytes"},
+ {"get_avail_virtmem", get_avail_virtmem, METH_VARARGS,
+ "Return the amount of available virtual memory, in bytes"},
+ {"get_system_cpu_times", get_system_cpu_times, METH_VARARGS,
+ "Return system cpu times as a tuple (user, system, idle)"},
+
+ {NULL, NULL, 0, NULL}
+};
+
+
+struct module_state {
+ PyObject *error;
+};
+
+#if PY_MAJOR_VERSION >= 3
+ #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
+#else
+ #define GETSTATE(m) (&_state)
+ static struct module_state _state;
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+
+ static int psutil_mswindows_traverse(PyObject *m, visitproc visit, void *arg) {
+ Py_VISIT(GETSTATE(m)->error);
+ return 0;
+ }
+
+ static int psutil_mswindows_clear(PyObject *m) {
+ Py_CLEAR(GETSTATE(m)->error);
+ return 0;
+ }
+
+ static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "psutil_mswindows",
+ NULL,
+ sizeof(struct module_state),
+ PsutilMethods,
+ NULL,
+ psutil_mswindows_traverse,
+ psutil_mswindows_clear,
+ NULL
+ };
+
+#define INITERROR return NULL
+
+ PyObject* PyInit__psutil_mswindows(void)
+
+#else
+ #define INITERROR return
+ void init_psutil_mswindows(void)
+#endif
+{
+ struct module_state *st = NULL;
+#if PY_MAJOR_VERSION >= 3
+ PyObject *module = PyModule_Create(&moduledef);
+#else
+ PyObject *module = Py_InitModule("_psutil_mswindows", PsutilMethods);
+#endif
+
+ if (module == NULL) {
+ INITERROR;
+ }
+
+ st = GETSTATE(module);
+ st->error = PyErr_NewException("_psutil_mswindow.Error", NULL, NULL);
+ if (st->error == NULL) {
+ Py_DECREF(module);
+ INITERROR;
+ }
+
+ SetSeDebug();
+
+#if PY_MAJOR_VERSION >= 3
+ return module;
+#endif
+}
+
+
+// ------------------------ Public functions ---------------------------
+
+/*
+ * Return a Python float representing the system uptime expressed in seconds
+ * since the epoch.
+ */
+static PyObject*
+get_system_uptime(PyObject* self, PyObject* args)
+{
+ double uptime;
+ time_t pt;
+ FILETIME fileTime;
+ long long ll;
+
+ GetSystemTimeAsFileTime(&fileTime);
+
+ /*
+ HUGE thanks to:
+ http://johnstewien.spaces.live.com/blog/cns!E6885DB5CEBABBC8!831.entry
+
+ This function converts the FILETIME structure to the 32 bit
+ Unix time structure.
+ The time_t is a 32-bit value for the number of seconds since
+ January 1, 1970. A FILETIME is a 64-bit for the number of
+ 100-nanosecond periods since January 1, 1601. Convert by
+ subtracting the number of 100-nanosecond period betwee 01-01-1970
+ and 01-01-1601, from time_t the divide by 1e+7 to get to the same
+ base granularity.
+ */
+ ll = (((LONGLONG)(fileTime.dwHighDateTime)) << 32) + fileTime.dwLowDateTime;
+ pt = (time_t)((ll - 116444736000000000ull) / 10000000ull);
+
+ // XXX - By using GetTickCount() time will wrap around to zero if the
+ // system is run continuously for 49.7 days.
+ uptime = GetTickCount() / 1000.00f;
+ return Py_BuildValue("d", (double)pt - uptime);
+}
+
+
+/*
+ * Return 1 if PID exists in the current process list, else 0.
+ */
+static PyObject*
+pid_exists(PyObject* self, PyObject* args)
+{
+ long pid;
+ int status;
+
+ if (! PyArg_ParseTuple(args, "l", &pid)) {
+ return NULL;
+ }
+
+ status = pid_is_running(pid);
+ if (-1 == status) {
+ return NULL; // exception raised in pid_is_running()
+ }
+ return PyBool_FromLong(status);
+}
+
+
+/*
+ * Return a Python list of all the PIDs running on the system.
+ */
+static PyObject*
+get_pid_list(PyObject* self, PyObject* args)
+{
+ DWORD *proclist = NULL;
+ DWORD numberOfReturnedPIDs;
+ DWORD i;
+ PyObject* pid = NULL;
+ PyObject* retlist = PyList_New(0);
+
+ proclist = get_pids(&numberOfReturnedPIDs);
+ if (NULL == proclist) {
+ Py_DECREF(retlist);
+ return NULL;
+ }
+
+ for (i = 0; i < numberOfReturnedPIDs; i++) {
+ pid = Py_BuildValue("I", proclist[i]);
+ PyList_Append(retlist, pid);
+ Py_XDECREF(pid);
+ }
+
+ // free C array allocated for PIDs
+ free(proclist);
+
+ return retlist;
+}
+
+
+/*
+ * Kill a process given its PID.
+ */
+static PyObject*
+kill_process(PyObject* self, PyObject* args)
+{
+ HANDLE hProcess;
+ long pid;
+
+ if (! PyArg_ParseTuple(args, "l", &pid))
+ return NULL;
+ if (pid == 0)
+ return AccessDenied();
+
+ hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
+ if (hProcess == NULL) {
+ if (GetLastError() == ERROR_INVALID_PARAMETER) {
+ // see http://code.google.com/p/psutil/issues/detail?id=24
+ NoSuchProcess();
+ }
+ else {
+ PyErr_SetFromWindowsErr(0);
+ }
+ return NULL;
+ }
+
+ // kill the process
+ if (! TerminateProcess(hProcess, 0)) {
+ PyErr_SetFromWindowsErr(0);
+ CloseHandle(hProcess);
+ return NULL;
+ }
+
+ CloseHandle(hProcess);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+
+/*
+ * Return a Python tuple (user_time, kernel_time)
+ */
+static PyObject*
+get_process_cpu_times(PyObject* self, PyObject* args)
+{
+ long pid;
+ HANDLE hProcess;
+ FILETIME ftCreate, ftExit, ftKernel, ftUser;
+
+ if (! PyArg_ParseTuple(args, "l", &pid)) {
+ return NULL;
+ }
+
+ // special case for PID 0
+ if (0 == pid){
+ return Py_BuildValue("(dd)", 0.0, 0.0);
+ }
+
+ hProcess = handle_from_pid(pid);
+ if (hProcess == NULL) {
+ return NULL;
+ }
+
+ if (! GetProcessTimes(hProcess, &ftCreate, &ftExit, &ftKernel, &ftUser)) {
+ if (GetLastError() == ERROR_ACCESS_DENIED) {
+ // usually means the process has died so we throw a NoSuchProcess
+ // here
+ CloseHandle(hProcess);
+ return NoSuchProcess();
+ }
+ PyErr_SetFromWindowsErr(0);
+ CloseHandle(hProcess);
+ return NULL;
+ }
+
+ CloseHandle(hProcess);
+
+ /*
+ user and kernel times are represented as a FILETIME structure wich contains
+ a 64-bit value representing the number of 100-nanosecond intervals since
+ January 1, 1601 (UTC).
+ http://msdn.microsoft.com/en-us/library/ms724284(VS.85).aspx
+
+ To convert it into a float representing the seconds that the process has
+ executed in user/kernel mode I borrowed the code below from Python's
+ Modules/posixmodule.c
+ */
+
+ return Py_BuildValue(
+ "(dd)",
+ (double)(ftUser.dwHighDateTime*429.4967296 + \
+ ftUser.dwLowDateTime*1e-7),
+ (double)(ftKernel.dwHighDateTime*429.4967296 + \
+ ftKernel.dwLowDateTime*1e-7)
+ );
+}
+
+
+/*
+ * Return a Python float indicating the process create time expressed in
+ * seconds since the epoch.
+ */
+static PyObject*
+get_process_create_time(PyObject* self, PyObject* args)
+{
+ long pid;
+ long long unix_time;
+ HANDLE hProcess;
+ FILETIME ftCreate, ftExit, ftKernel, ftUser;
+
+ if (! PyArg_ParseTuple(args, "l", &pid)) {
+ return NULL;
+ }
+
+ // special case for PIDs 0 and 4
+ if ( (0 == pid) || (4 == pid) ){
+ return Py_BuildValue("d", 0.0);
+ }
+
+ hProcess = handle_from_pid(pid);
+ if (hProcess == NULL) {
+ return NULL;
+ }
+
+ if (! GetProcessTimes(hProcess, &ftCreate, &ftExit, &ftKernel, &ftUser)) {
+ if (GetLastError() == ERROR_ACCESS_DENIED) {
+ // usually means the process has died so we throw a NoSuchProcess here
+ return NoSuchProcess();
+ }
+ else {
+ PyErr_SetFromWindowsErr(0);
+ }
+ CloseHandle(hProcess);
+ return NULL;
+ }
+
+ CloseHandle(hProcess);
+
+ /*
+ Convert the FILETIME structure to a Unix time.
+ It's the best I could find by googling and borrowing code here and there.
+ The time returned has a precision of 1 second.
+ */
+ unix_time = ((LONGLONG)ftCreate.dwHighDateTime) << 32;
+ unix_time += ftCreate.dwLowDateTime - 116444736000000000LL;
+ unix_time /= 10000000;
+ return Py_BuildValue("d", (double)unix_time);
+}
+
+
+/*
+ * Return a Python integer indicating the number of CPUs on the system.
+ */
+static PyObject*
+get_num_cpus(PyObject* self, PyObject* args)
+{
+ SYSTEM_INFO system_info;
+ system_info.dwNumberOfProcessors = 0;
+
+ GetSystemInfo(&system_info);
+ if (system_info.dwNumberOfProcessors == 0){
+ // GetSystemInfo failed for some reason; return 1 as default
+ return Py_BuildValue("I", 1);
+ }
+ return Py_BuildValue("I", system_info.dwNumberOfProcessors);
+}
+
+/*
+ * Return process name as a Python string.
+ */
+static PyObject*
+get_process_name(PyObject* self, PyObject* args) {
+ long pid;
+ int pid_return;
+ PyObject* name;
+
+ if (! PyArg_ParseTuple(args, "l", &pid))
+ return NULL;
+
+ if (pid == 0) {
+ return Py_BuildValue("s", "System Idle Process");
+ }
+ else if (pid == 4) {
+ return Py_BuildValue("s", "System");
+ }
+
+ pid_return = pid_is_running(pid);
+ if (pid_return == 0) {
+ return NoSuchProcess();
+ }
+ if (pid_return == -1) {
+ return NULL;
+ }
+
+ name = get_name(pid);
+ if (name == NULL)
+ return NULL; // exception set in get_name()
+ return name;
+}
+
+
+/*
+ * Return process parent pid as a Python integer.
+ */
+static PyObject*
+get_process_ppid(PyObject* self, PyObject* args) {
+ long pid;
+ int pid_return;
+ PyObject* ppid;
+
+ if (! PyArg_ParseTuple(args, "l", &pid))
+ return NULL;
+ if ((pid == 0) || (pid == 4))
+ return Py_BuildValue("l", 0);
+
+ pid_return = pid_is_running(pid);
+ if (pid_return == 0) {
+ return NoSuchProcess();
+ }
+ if (pid_return == -1) {
+ return NULL;
+ }
+
+ ppid = get_ppid(pid);
+ if (ppid == NULL)
+ return NULL; // exception set in get_ppid()
+ return ppid;
+}
+
+/*
+ * Return process cmdline as a Python list of cmdline arguments.
+ */
+static PyObject*
+get_process_cmdline(PyObject* self, PyObject* args) {
+ long pid;
+ int pid_return;
+ PyObject* arglist;
+
+ if (! PyArg_ParseTuple(args, "l", &pid))
+ return NULL;
+ if ((pid == 0) || (pid == 4))
+ return Py_BuildValue("[]");
+
+ pid_return = pid_is_running(pid);
+ if (pid_return == 0) {
+ return NoSuchProcess();
+ }
+ if (pid_return == -1) {
+ return NULL;
+ }
+
+ // May fail any of several ReadProcessMemory calls etc. and not indicate
+ // a real problem so we ignore any errors and just live without commandline
+ arglist = get_arg_list(pid);
+ if ( NULL == arglist ) {
+ // carry on anyway, clear any exceptions too
+ PyErr_Clear();
+ return Py_BuildValue("[]");
+ }
+
+ return arglist;
+}
+
+
+/*
+ * Return the RSS and VMS as a Python tuple.
+ */
+static PyObject*
+get_memory_info(PyObject* self, PyObject* args)
+{
+ HANDLE hProcess;
+ PROCESS_MEMORY_COUNTERS counters;
+ DWORD pid;
+
+ if (! PyArg_ParseTuple(args, "l", &pid)) {
+ return NULL;
+ }
+
+ hProcess = handle_from_pid(pid);
+ if (NULL == hProcess) {
+ return NULL;
+ }
+
+ if (! GetProcessMemoryInfo(hProcess, &counters, sizeof(counters)) ) {
+ return PyErr_SetFromWindowsErr(0);
+ }
+
+ return Py_BuildValue("(nn)", counters.WorkingSetSize, counters.PagefileUsage);
+}
+
+
+/*
+ * Return a Python integer indicating the total amount of physical memory
+ * in bytes.
+ */
+static PyObject*
+get_total_phymem(PyObject* self, PyObject* args)
+{
+ MEMORYSTATUSEX memInfo;
+ memInfo.dwLength = sizeof(MEMORYSTATUSEX);
+
+ if (! GlobalMemoryStatusEx(&memInfo) ) {
+ return PyErr_SetFromWindowsErr(0);
+ }
+
+ return Py_BuildValue("L", memInfo.ullTotalPhys);
+}
+
+
+/*
+ * Return a Python integer indicating the total amount of virtual memory
+ * in bytes.
+ */
+static PyObject*
+get_total_virtmem(PyObject* self, PyObject* args)
+{
+ MEMORYSTATUSEX memInfo;
+ memInfo.dwLength = sizeof(MEMORYSTATUSEX);
+
+ if (! GlobalMemoryStatusEx(&memInfo) ) {
+ return PyErr_SetFromWindowsErr(0);
+ }
+
+ return Py_BuildValue("L", memInfo.ullTotalPageFile);
+}
+
+
+/*
+ * Return a Python integer indicating the amount of available physical memory
+ * in bytes.
+ */
+static PyObject*
+get_avail_phymem(PyObject* self, PyObject* args)
+{
+ MEMORYSTATUSEX memInfo;
+ memInfo.dwLength = sizeof(MEMORYSTATUSEX);
+ if (! GlobalMemoryStatusEx(&memInfo) ) {
+ return PyErr_SetFromWindowsErr(0);
+ }
+ return Py_BuildValue("L", memInfo.ullAvailPhys);
+}
+
+
+/*
+ * Return a Python integer indicating the amount of available virtual memory
+ * in bytes.
+ */
+static PyObject*
+get_avail_virtmem(PyObject* self, PyObject* args)
+{
+ MEMORYSTATUSEX memInfo;
+ memInfo.dwLength = sizeof(MEMORYSTATUSEX);
+
+ if (! GlobalMemoryStatusEx(&memInfo) ) {
+ return PyErr_SetFromWindowsErr(0);
+ }
+ return Py_BuildValue("L", memInfo.ullAvailPageFile);
+}
+
+
+#define LO_T ((float)1e-7)
+#define HI_T (LO_T*4294967296.0)
+
+// structures and enums from winternl.h (not available under mingw)
+typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION {
+ LARGE_INTEGER IdleTime;
+ LARGE_INTEGER KernelTime;
+ LARGE_INTEGER UserTime;
+ LARGE_INTEGER Reserved1[2];
+ ULONG Reserved2;
+} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
+
+
+typedef enum _SYSTEM_INFORMATION_CLASS {
+ SystemBasicInformation = 0,
+ SystemPerformanceInformation = 2,
+ SystemTimeOfDayInformation = 3,
+ SystemProcessInformation = 5,
+ SystemProcessorPerformanceInformation = 8,
+ SystemInterruptInformation = 23,
+ SystemExceptionInformation = 33,
+ SystemRegistryQuotaInformation = 37,
+ SystemLookasideInformation = 45
+} SYSTEM_INFORMATION_CLASS;
+
+
+/*
+ * Return a Python tuple representing user, kernel and idle CPU times
+ */
+static PyObject*
+get_system_cpu_times(PyObject* self, PyObject* args)
+{
+ typedef BOOL (_stdcall *GST_PROC) (LPFILETIME, LPFILETIME, LPFILETIME);
+ static GST_PROC GetSystemTimes;
+ static BOOL bFirstCall = TRUE;
+ float idle, kernel, user;
+
+ // Improves performance calling GetProcAddress only the first time
+ if (bFirstCall) {
+ // retrieves GetSystemTimes address in Kernel32
+ GetSystemTimes=(GST_PROC)GetProcAddress(GetModuleHandle
+ (TEXT("Kernel32.dll")),
+ "GetSystemTimes");
+ bFirstCall = FALSE;
+ }
+
+
+ // Uses GetSystemTimes if supported (winXP sp1+)
+ if (NULL!=GetSystemTimes) {
+ // GetSystemTimes supported
+
+ FILETIME idle_time;
+ FILETIME kernel_time;
+ FILETIME user_time;
+
+ if (!GetSystemTimes(&idle_time, &kernel_time, &user_time)) {
+ return PyErr_SetFromWindowsErr(0);
+ }
+
+ idle = (float)((HI_T * idle_time.dwHighDateTime) + \
+ (LO_T * idle_time.dwLowDateTime));
+ user = (float)((HI_T * user_time.dwHighDateTime) + \
+ (LO_T * user_time.dwLowDateTime));
+ kernel = (float)((HI_T * kernel_time.dwHighDateTime) + \
+ (LO_T * kernel_time.dwLowDateTime));
+
+ // kernel time includes idle time on windows
+ // we return only busy kernel time subtracting idle time from kernel time
+ return Py_BuildValue("(fff)", user,
+ kernel - idle,
+ idle);
+
+ }
+
+ else {
+ // GetSystemTimes NOT supported, use NtQuerySystemInformation instead
+
+ typedef DWORD (_stdcall *NTQSI_PROC) (int, PVOID, ULONG, PULONG);
+ NTQSI_PROC NtQuerySystemInformation;
+ HINSTANCE hNtDll;
+ SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi = NULL;
+ SYSTEM_INFO si;
+ UINT i;
+
+ // dynamic linking is mandatory to use NtQuerySystemInformation
+ hNtDll = LoadLibrary(TEXT("ntdll.dll"));
+ if (hNtDll != NULL) {
+ // gets NtQuerySystemInformation address
+ NtQuerySystemInformation = (NTQSI_PROC)GetProcAddress(
+ hNtDll, "NtQuerySystemInformation");
+
+ if (NtQuerySystemInformation != NULL)
+ {
+ // retrives number of processors
+ GetSystemInfo(&si);
+
+ // allocates an array of SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
+ // structures, one per processor
+ sppi=(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *) \
+ malloc(si.dwNumberOfProcessors * \
+ sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
+ if (sppi != NULL)
+ {
+ // gets cpu time informations
+ if (0 == NtQuerySystemInformation(
+ SystemProcessorPerformanceInformation,
+ sppi,
+ si.dwNumberOfProcessors * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION),
+ NULL))
+ {
+ // computes system global times summing each processor value
+ idle = user = kernel = 0;
+ for (i=0; i<si.dwNumberOfProcessors; i++) {
+ idle += (float)((HI_T * sppi[i].IdleTime.HighPart) + \
+ (LO_T * sppi[i].IdleTime.LowPart));
+ user += (float)((HI_T * sppi[i].UserTime.HighPart) + \
+ (LO_T * sppi[i].UserTime.LowPart));
+ kernel += (float)((HI_T * sppi[i].KernelTime.HighPart) + \
+ (LO_T * sppi[i].KernelTime.LowPart));
+ }
+
+ // kernel time includes idle time on windows
+ // we return only busy kernel time subtracting idle
+ // time from kernel time
+ return Py_BuildValue("(ddd)", user,
+ kernel - idle,
+ idle
+ );
+
+ } // END NtQuerySystemInformation
+
+ } // END malloc SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
+
+ } // END GetProcAddress
+
+ } // END LoadLibrary
+
+ PyErr_SetFromWindowsErr(0);
+ if (sppi) {
+ free(sppi);
+ }
+ if (hNtDll) {
+ FreeLibrary(hNtDll);
+ }
+ return 0;
+
+ } // END GetSystemTimes NOT supported
+}
+
+
+/*
+ * Sid to User convertion
+ */
+BOOL SidToUser(PSID pSid, LPTSTR szUser, DWORD dwUserLen, LPTSTR szDomain, DWORD
+dwDomainLen, DWORD pid)
+{
+ SID_NAME_USE snuSIDNameUse;
+ DWORD dwULen;
+ DWORD dwDLen;
+
+ dwULen = dwUserLen;
+ dwDLen = dwDomainLen;
+
+ if ( IsValidSid( pSid ) ) {
+ // Get user and domain name based on SID
+ if ( LookupAccountSid( NULL, pSid, szUser, &dwULen, szDomain, &dwDLen, &snuSIDNameUse) ) {
+ // LocalSystem processes are incorrectly reported as owned
+ // by BUILTIN\Administrators We modify that behavior to
+ // conform to standard taskmanager only if the process is
+ // actually a System process
+ if (is_system_proc(pid) == 1) {
+ // default to *not* changing the data if we fail to
+ // check for local system privileges, so only look for
+ // definite confirmed system processes and ignore errors
+ if ( lstrcmpi(szDomain, TEXT("builtin")) == 0 && lstrcmpi(szUser, TEXT("administrators")) == 0) {
+ strncpy (szUser, "SYSTEM", dwUserLen);
+ strncpy (szDomain, "NT AUTHORITY", dwDomainLen);
+ }
+ }
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+typedef struct _UNICODE_STRING {
+ USHORT Length;
+ USHORT MaximumLength;
+ PWSTR Buffer;
+} UNICODE_STRING, *PUNICODE_STRING;
+
+/*
+ * Return process current working directory as a Python string.
+ */
+
+static PyObject*
+get_process_cwd(PyObject* self, PyObject* args)
+{
+ long pid;
+ HANDLE processHandle;
+ PVOID pebAddress;
+ PVOID rtlUserProcParamsAddress;
+ UNICODE_STRING currentDirectory;
+ WCHAR *currentDirectoryContent;
+ PyObject *returnPyObj = NULL;
+ PyObject *cwd_from_wchar = NULL;
+ PyObject *cwd = NULL;
+
+ if (! PyArg_ParseTuple(args, "l", &pid)) {
+ return NULL;
+ }
+
+ processHandle = handle_from_pid(pid);
+ if (processHandle == NULL) {
+ return NULL;
+ }
+
+ pebAddress = GetPebAddress(processHandle);
+
+ /* get the address of ProcessParameters */
+#ifdef _WIN64
+ if (!ReadProcessMemory(processHandle, (PCHAR)pebAddress + 32,
+ &rtlUserProcParamsAddress, sizeof(PVOID), NULL))
+#else
+ if (!ReadProcessMemory(processHandle, (PCHAR)pebAddress + 0x10,
+ &rtlUserProcParamsAddress, sizeof(PVOID), NULL))
+#endif
+ {
+ CloseHandle(processHandle);
+
+ if (GetLastError() == ERROR_PARTIAL_COPY) {
+ /* Usually means the process has gone in the meantime */
+ return NoSuchProcess();
+ }
+ else {
+ return PyErr_SetFromWindowsErr(0);
+ }
+
+ }
+
+ /* read the currentDirectory UNICODE_STRING structure.
+ 0x24 refers to "CurrentDirectoryPath" of RTL_USER_PROCESS_PARAMETERS
+ structure (http://wj32.wordpress.com/2009/01/24/howto-get-the-command-line-of-processes/)
+ */
+#ifdef _WIN64
+ if (!ReadProcessMemory(processHandle, (PCHAR)rtlUserProcParamsAddress + 56,
+ &currentDirectory, sizeof(currentDirectory), NULL))
+#else
+ if (!ReadProcessMemory(processHandle, (PCHAR)rtlUserProcParamsAddress + 0x24,
+ &currentDirectory, sizeof(currentDirectory), NULL))
+#endif
+ {
+ CloseHandle(processHandle);
+ if (GetLastError() == ERROR_PARTIAL_COPY) {
+ /* Usually means the process has gone in the meantime */
+ return NoSuchProcess();
+ }
+ else {
+ return PyErr_SetFromWindowsErr(0);
+ }
+ }
+
+ /* allocate memory to hold the command line */
+ currentDirectoryContent = (WCHAR *)malloc(currentDirectory.Length+1);
+
+ /* read the command line */
+ if (!ReadProcessMemory(processHandle, currentDirectory.Buffer,
+ currentDirectoryContent, currentDirectory.Length, NULL))
+ {
+ CloseHandle(processHandle);
+ free(currentDirectoryContent);
+
+ if (GetLastError() == ERROR_PARTIAL_COPY) {
+ /* Usually means the process has gone in the meantime */
+ return NoSuchProcess();
+ }
+ else {
+ return PyErr_SetFromWindowsErr(0);
+ }
+ }
+
+ // null-terminate the string to prevent wcslen from returning incorrect length
+ // the length specifier is in characters, but commandLine.Length is in bytes
+ currentDirectoryContent[(currentDirectory.Length/sizeof(WCHAR))] = '\0';
+
+ // convert wchar array to a Python unicode string, and then to UTF8
+ cwd_from_wchar = PyUnicode_FromWideChar(currentDirectoryContent,
+ wcslen(currentDirectoryContent));
+
+ #if PY_MAJOR_VERSION >= 3
+ cwd = PyUnicode_FromObject(cwd_from_wchar);
+ #else
+ cwd = PyUnicode_AsUTF8String(cwd_from_wchar);
+ #endif
+
+ // decrement the reference count on our temp unicode str to avoid mem leak
+ Py_XDECREF(cwd_from_wchar);
+ returnPyObj = Py_BuildValue("N", cwd);
+
+ CloseHandle(processHandle);
+ free(currentDirectoryContent);
+ return returnPyObj;
+}
+
+
+/*
+ * Resume or suspends a process
+ */
+int
+suspend_resume_process(DWORD pid, int suspend)
+{
+ // a huge thanks to http://www.codeproject.com/KB/threads/pausep.aspx
+ HANDLE hThreadSnap = NULL;
+ THREADENTRY32 te32 = {0};
+
+ hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
+ if (hThreadSnap == INVALID_HANDLE_VALUE) {
+ PyErr_SetFromWindowsErr(0);
+ return FALSE;
+ }
+
+ // Fill in the size of the structure before using it
+ te32.dwSize = sizeof(THREADENTRY32);
+
+ if (! Thread32First(hThreadSnap, &te32)) {
+ PyErr_SetFromWindowsErr(0);
+ CloseHandle(hThreadSnap);
+ return FALSE;
+ }
+
+ // Walk the thread snapshot to find all threads of the process.
+ // If the thread belongs to the process, add its information
+ // to the display list.
+ do
+ {
+ if (te32.th32OwnerProcessID == pid)
+ {
+ HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE,
+ te32.th32ThreadID);
+ if (hThread == NULL) {
+ PyErr_SetFromWindowsErr(0);
+ CloseHandle(hThread);
+ CloseHandle(hThreadSnap);
+ return FALSE;
+ }
+ if (suspend == 1)
+ {
+ if (SuspendThread(hThread) == (DWORD)-1) {
+ PyErr_SetFromWindowsErr(0);
+ CloseHandle(hThread);
+ CloseHandle(hThreadSnap);
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (ResumeThread(hThread) == (DWORD)-1) {
+ PyErr_SetFromWindowsErr(0);
+ CloseHandle(hThread);
+ CloseHandle(hThreadSnap);
+ return FALSE;
+ }
+ }
+ CloseHandle(hThread);
+ }
+ } while (Thread32Next(hThreadSnap, &te32));
+
+ return TRUE;
+}
+
+
+static PyObject*
+suspend_process(PyObject* self, PyObject* args)
+{
+ long pid;
+ int suspend = 1;
+ if (! PyArg_ParseTuple(args, "l", &pid)) {
+ return NULL;
+ }
+
+ if (! suspend_resume_process(pid, suspend)) {
+ return NULL;
+ }
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+static PyObject*
+resume_process(PyObject* self, PyObject* args)
+{
+ long pid;
+ int suspend = 0;
+ if (! PyArg_ParseTuple(args, "l", &pid)) {
+ return NULL;
+ }
+
+ if (! suspend_resume_process(pid, suspend)) {
+ return NULL;
+ }
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+
+static PyObject*
+get_process_num_threads(PyObject* self, PyObject* args)
+{
+ long pid;
+ int pid_return;
+ long nthreads = 0;
+ HANDLE hThreadSnap = NULL;
+ THREADENTRY32 te32 = {0};
+
+ if (! PyArg_ParseTuple(args, "l", &pid))
+ return NULL;
+ if (pid == 0) {
+ // raise AD instead of returning 0 as procexp is able to
+ // retrieve useful information somehow
+ return AccessDenied();
+ }
+
+ pid_return = pid_is_running(pid);
+ if (pid_return == 0) {
+ return NoSuchProcess();
+ }
+ if (pid_return == -1) {
+ return NULL;
+ }
+
+ hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
+ if (hThreadSnap == INVALID_HANDLE_VALUE) {
+ PyErr_SetFromWindowsErr(0);
+ return NULL;
+ }
+
+ // Fill in the size of the structure before using it
+ te32.dwSize = sizeof(THREADENTRY32);
+
+ if (! Thread32First(hThreadSnap, &te32)) {
+ PyErr_SetFromWindowsErr(0);
+ CloseHandle(hThreadSnap);
+ return NULL;
+ }
+
+ // Walk the thread snapshot to find all threads of the process.
+ // If the thread belongs to the process, increase the counter.
+ do
+ {
+ if (te32.th32OwnerProcessID == pid)
+ {
+ HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION,
+ FALSE, te32.th32ThreadID);
+ if (hThread == NULL) {
+ if (GetLastError() == ERROR_INVALID_PARAMETER) {
+ NoSuchProcess();
+ }
+ else {
+ PyErr_SetFromWindowsErr(0);
+ }
+ CloseHandle(hThread);
+ CloseHandle(hThreadSnap);
+ return NULL;
+ }
+ nthreads += 1;
+ CloseHandle(hThread);
+ }
+ } while (Thread32Next(hThreadSnap, &te32));
+
+ // every process should be supposed to have at least one thread
+ if (nthreads == 0) {
+ return NoSuchProcess();
+ }
+
+ return Py_BuildValue("l", nthreads);
+}
+
+
+static PyObject*
+get_process_open_files(PyObject* self, PyObject* args)
+{
+ long pid;
+ HANDLE processHandle;
+ DWORD access = PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION;
+ PyObject* filesList;
+
+ if (! PyArg_ParseTuple(args, "l", &pid)) {
+ return NULL;
+ }
+
+ processHandle = handle_from_pid_waccess(pid, access);
+ if (processHandle == NULL) {
+ return NULL;
+ }
+
+ filesList = get_open_files(pid, processHandle);
+ if (filesList == NULL) {
+ return PyErr_SetFromWindowsErr(0);
+ }
+ return filesList;
+}
+
+
+/*
+ Accept a filename's drive in native format like "\Device\HarddiskVolume1\"
+ and return the corresponding drive letter (e.g. "C:\\").
+ If no match is found return an empty string.
+*/
+static PyObject*
+_QueryDosDevice(PyObject* self, PyObject* args)
+{
+ LPCTSTR lpDevicePath;
+ TCHAR d = TEXT('A');
+ TCHAR szBuff[5];
+
+ if (!PyArg_ParseTuple(args, "s", &lpDevicePath)) {
+ return NULL;
+ }
+
+ while(d <= TEXT('Z'))
+ {
+ TCHAR szDeviceName[3] = {d,TEXT(':'),TEXT('\0')};
+ TCHAR szTarget[512] = {0};
+ if (QueryDosDevice(szDeviceName, szTarget, 511) != 0){
+ //_tprintf (TEXT("%c:\\ => %s\n"), d, szTarget);
+ if(_tcscmp(lpDevicePath, szTarget) == 0) {
+ _stprintf(szBuff, TEXT("%c:"), d);
+ return Py_BuildValue("s", szBuff);
+ }
+ }
+ d++;
+ }
+ return Py_BuildValue("s", "");
+}
+
+/*
+ * Return process username as a "DOMAIN//USERNAME" string.
+ */
+static PyObject*
+get_process_username(PyObject* self, PyObject* args)
+{
+ long pid;
+ HANDLE processHandle;
+ HANDLE tokenHandle;
+ PTOKEN_USER user;
+ ULONG bufferSize;
+ PTSTR name;
+ ULONG nameSize;
+ PTSTR domainName;
+ ULONG domainNameSize;
+ SID_NAME_USE nameUse;
+ PTSTR fullName;
+ PyObject* returnObject;
+
+ if (! PyArg_ParseTuple(args, "l", &pid)) {
+ return NULL;
+ }
+
+ processHandle = handle_from_pid_waccess(pid, PROCESS_QUERY_INFORMATION);
+ if (processHandle == NULL) {
+ return NULL;
+ }
+
+ if (!OpenProcessToken(processHandle, TOKEN_QUERY, &tokenHandle)) {
+ CloseHandle(processHandle);
+ return PyErr_SetFromWindowsErr(0);
+ }
+
+ CloseHandle(processHandle);
+
+ /* Get the user SID. */
+
+ bufferSize = 0x100;
+ user = malloc(bufferSize);
+
+ if (!GetTokenInformation(tokenHandle,
+ TokenUser,
+ user,
+ bufferSize,
+ &bufferSize))
+ {
+ free(user);
+ user = malloc(bufferSize);
+
+ if (!GetTokenInformation(tokenHandle,
+ TokenUser,
+ user,
+ bufferSize,
+ &bufferSize))
+ {
+ free(user);
+ CloseHandle(tokenHandle);
+ return PyErr_SetFromWindowsErr(0);
+ }
+ }
+
+ CloseHandle(tokenHandle);
+
+ /* Resolve the SID to a name. */
+
+ nameSize = 0x100;
+ domainNameSize = 0x100;
+
+ name = malloc(nameSize * sizeof(TCHAR));
+ domainName = malloc(domainNameSize * sizeof(TCHAR));
+
+ if (!LookupAccountSid(NULL, user->User.Sid, name, &nameSize, domainName,
+ &domainNameSize, &nameUse))
+ {
+ free(name);
+ free(domainName);
+ name = malloc(nameSize * sizeof(TCHAR));
+ domainName = malloc(domainNameSize * sizeof(TCHAR));
+
+ if (!LookupAccountSid(NULL, user->User.Sid, name, &nameSize, domainName,
+ &domainNameSize, &nameUse))
+ {
+ free(name);
+ free(domainName);
+ free(user);
+
+ return PyErr_SetFromWindowsErr(0);
+ }
+ }
+
+ nameSize = _tcslen(name);
+ domainNameSize = _tcslen(domainName);
+
+ /* Build the full username string. */
+ fullName = malloc((domainNameSize + 1 + nameSize + 1) * sizeof(TCHAR));
+ memcpy(fullName, domainName, domainNameSize);
+ fullName[domainNameSize] = '\\';
+ memcpy(&fullName[domainNameSize + 1], name, nameSize);
+ fullName[domainNameSize + 1 + nameSize] = '\0';
+
+ returnObject = Py_BuildValue("s", fullName);
+
+ free(fullName);
+ free(name);
+ free(domainName);
+ free(user);
+
+ return returnObject;
+}
+
+#define BYTESWAP_USHORT(x) ((((USHORT)(x) << 8) | ((USHORT)(x) >> 8)) & 0xffff)
+
+#ifndef AF_INET6
+#define AF_INET6 23
+#endif
+
+static char *state_to_string(ULONG state)
+{
+ switch (state)
+ {
+ case MIB_TCP_STATE_CLOSED:
+ return "CLOSE";
+ case MIB_TCP_STATE_LISTEN:
+ return "LISTEN";
+ case MIB_TCP_STATE_SYN_SENT:
+ return "SYN_SENT";
+ case MIB_TCP_STATE_SYN_RCVD:
+ return "SYN_RECV";
+ case MIB_TCP_STATE_ESTAB:
+ return "ESTABLISHED";
+ case MIB_TCP_STATE_FIN_WAIT1:
+ return "FIN_WAIT1";
+ case MIB_TCP_STATE_FIN_WAIT2:
+ return "FIN_WAIT2";
+ case MIB_TCP_STATE_CLOSE_WAIT:
+ return "CLOSE_WAIT";
+ case MIB_TCP_STATE_CLOSING:
+ return "CLOSING";
+ case MIB_TCP_STATE_LAST_ACK:
+ return "LAST_ACK";
+ case MIB_TCP_STATE_TIME_WAIT:
+ return "TIME_WAIT";
+ case MIB_TCP_STATE_DELETE_TCB:
+ return "DELETE_TCB";
+ default:
+ return "";
+ }
+}
+
+/* mingw support */
+#ifndef _IPRTRMIB_H
+typedef struct _MIB_TCP6ROW_OWNER_PID
+{
+ UCHAR ucLocalAddr[16];
+ DWORD dwLocalScopeId;
+ DWORD dwLocalPort;
+ UCHAR ucRemoteAddr[16];
+ DWORD dwRemoteScopeId;
+ DWORD dwRemotePort;
+ DWORD dwState;
+ DWORD dwOwningPid;
+} MIB_TCP6ROW_OWNER_PID, *PMIB_TCP6ROW_OWNER_PID;
+
+typedef struct _MIB_TCP6TABLE_OWNER_PID
+{
+ DWORD dwNumEntries;
+ MIB_TCP6ROW_OWNER_PID table[ANY_SIZE];
+} MIB_TCP6TABLE_OWNER_PID, *PMIB_TCP6TABLE_OWNER_PID;
+#endif
+
+#ifndef __IPHLPAPI_H__
+typedef struct in6_addr {
+ union {
+ UCHAR Byte[16];
+ USHORT Word[8];
+ } u;
+} IN6_ADDR, *PIN6_ADDR, FAR *LPIN6_ADDR;
+
+
+typedef enum _UDP_TABLE_CLASS {
+ UDP_TABLE_BASIC,
+ UDP_TABLE_OWNER_PID,
+ UDP_TABLE_OWNER_MODULE
+} UDP_TABLE_CLASS, *PUDP_TABLE_CLASS;
+
+
+typedef struct _MIB_UDPROW_OWNER_PID {
+ DWORD dwLocalAddr;
+ DWORD dwLocalPort;
+ DWORD dwOwningPid;
+} MIB_UDPROW_OWNER_PID, *PMIB_UDPROW_OWNER_PID;
+
+typedef struct _MIB_UDPTABLE_OWNER_PID
+{
+ DWORD dwNumEntries;
+ MIB_UDPROW_OWNER_PID table[ANY_SIZE];
+} MIB_UDPTABLE_OWNER_PID, *PMIB_UDPTABLE_OWNER_PID;
+#endif
+/* end of mingw support */
+
+typedef struct _MIB_UDP6ROW_OWNER_PID {
+ UCHAR ucLocalAddr[16];
+ DWORD dwLocalScopeId;
+ DWORD dwLocalPort;
+ DWORD dwOwningPid;
+} MIB_UDP6ROW_OWNER_PID, *PMIB_UDP6ROW_OWNER_PID;
+
+typedef struct _MIB_UDP6TABLE_OWNER_PID
+{
+ DWORD dwNumEntries;
+ MIB_UDP6ROW_OWNER_PID table[ANY_SIZE];
+} MIB_UDP6TABLE_OWNER_PID, *PMIB_UDP6TABLE_OWNER_PID;
+
+
+/*
+ * Return a list of network connections opened by a process
+ */
+static PyObject*
+get_process_connections(PyObject* self, PyObject* args)
+{
+ static long null_address[4] = { 0, 0, 0, 0 };
+
+ unsigned long pid;
+ PyObject* connectionsList;
+ PyObject* connectionTuple;
+ typedef PSTR (NTAPI *_RtlIpv4AddressToStringA)(struct in_addr *,
+ PSTR /* __out_ecount(16) */);
+ _RtlIpv4AddressToStringA rtlIpv4AddressToStringA;
+ typedef PSTR (NTAPI *_RtlIpv6AddressToStringA)(struct in6_addr *,
+ PSTR /* __out_ecount(65) */);
+ _RtlIpv6AddressToStringA rtlIpv6AddressToStringA;
+ typedef DWORD (WINAPI *_GetExtendedTcpTable)(PVOID, PDWORD, BOOL, ULONG,
+ TCP_TABLE_CLASS, ULONG);
+ _GetExtendedTcpTable getExtendedTcpTable;
+ typedef DWORD (WINAPI *_GetExtendedUdpTable)(PVOID, PDWORD, BOOL, ULONG,
+ UDP_TABLE_CLASS, ULONG);
+ _GetExtendedUdpTable getExtendedUdpTable;
+ PVOID table;
+ DWORD tableSize;
+ PMIB_TCPTABLE_OWNER_PID tcp4Table;
+ PMIB_UDPTABLE_OWNER_PID udp4Table;
+ PMIB_TCP6TABLE_OWNER_PID tcp6Table;
+ PMIB_UDP6TABLE_OWNER_PID udp6Table;
+ ULONG i;
+ CHAR addressBufferLocal[65];
+ PyObject* addressTupleLocal;
+ CHAR addressBufferRemote[65];
+ PyObject* addressTupleRemote;
+
+ if (!PyArg_ParseTuple(args, "l", &pid)) {
+ return NULL;
+ }
+
+ if (pid_is_running(pid) == 0) {
+ return NoSuchProcess();
+ }
+
+ /* Import some functions. */
+ {
+ HMODULE ntdll;
+ HMODULE iphlpapi;
+
+ ntdll = LoadLibrary(TEXT("ntdll.dll"));
+ rtlIpv4AddressToStringA = (_RtlIpv4AddressToStringA)GetProcAddress(ntdll,
+ "RtlIpv4AddressToStringA");
+ rtlIpv6AddressToStringA = (_RtlIpv6AddressToStringA)GetProcAddress(ntdll,
+ "RtlIpv6AddressToStringA");
+ /* TODO: Check these two function pointers */
+
+ iphlpapi = LoadLibrary(TEXT("iphlpapi.dll"));
+ getExtendedTcpTable = (_GetExtendedTcpTable)GetProcAddress(iphlpapi,
+ "GetExtendedTcpTable");
+ getExtendedUdpTable = (_GetExtendedUdpTable)GetProcAddress(iphlpapi,
+ "GetExtendedUdpTable");
+ }
+
+ if ((getExtendedTcpTable == NULL) || (getExtendedUdpTable == NULL)) {
+ PyErr_SetString(PyExc_NotImplementedError,
+ "feature not supported on this Windows version");
+ return NULL;
+ }
+
+ connectionsList = PyList_New(0);
+
+ /* TCP IPv4 */
+
+ tableSize = 0;
+ getExtendedTcpTable(NULL, &tableSize, FALSE, AF_INET,
+ TCP_TABLE_OWNER_PID_ALL, 0);
+
+ table = malloc(tableSize);
+
+ if (getExtendedTcpTable(table, &tableSize, FALSE, AF_INET,
+ TCP_TABLE_OWNER_PID_ALL, 0) == 0)
+ {
+ tcp4Table = table;
+
+ for (i = 0; i < tcp4Table->dwNumEntries; i++)
+ {
+ if (tcp4Table->table[i].dwOwningPid != pid)
+ continue;
+
+ if (tcp4Table->table[i].dwLocalAddr != 0 ||
+ tcp4Table->table[i].dwLocalPort != 0)
+ {
+ struct in_addr addr;
+
+ addr.S_un.S_addr = tcp4Table->table[i].dwLocalAddr;
+ rtlIpv4AddressToStringA(&addr, addressBufferLocal);
+ addressTupleLocal = Py_BuildValue("(si)", addressBufferLocal,
+ BYTESWAP_USHORT(tcp4Table->table[i].dwLocalPort));
+ }
+ else
+ {
+ addressTupleLocal = PyTuple_New(0);
+ }
+
+ // On Windows <= XP, remote addr is filled even if socket
+ // is in LISTEN mode in which case we just ignore it.
+ if ((tcp4Table->table[i].dwRemoteAddr != 0 ||
+ tcp4Table->table[i].dwRemotePort != 0) &&
+ (tcp4Table->table[i].dwState != MIB_TCP_STATE_LISTEN))
+ {
+ struct in_addr addr;
+
+ addr.S_un.S_addr = tcp4Table->table[i].dwRemoteAddr;
+ rtlIpv4AddressToStringA(&addr, addressBufferRemote);
+ addressTupleRemote = Py_BuildValue("(si)", addressBufferRemote,
+ BYTESWAP_USHORT(tcp4Table->table[i].dwRemotePort));
+ }
+ else
+ {
+ addressTupleRemote = PyTuple_New(0);
+ }
+
+ connectionTuple = Py_BuildValue("(iiiNNs)",
+ -1,
+ AF_INET,
+ SOCK_STREAM,
+ addressTupleLocal,
+ addressTupleRemote,
+ state_to_string(tcp4Table->table[i].dwState)
+ );
+ PyList_Append(connectionsList, connectionTuple);
+ }
+ }
+
+ free(table);
+
+ /* TCP IPv6 */
+
+ tableSize = 0;
+ getExtendedTcpTable(NULL, &tableSize, FALSE, AF_INET6,
+ TCP_TABLE_OWNER_PID_ALL, 0);
+
+ table = malloc(tableSize);
+
+ if (getExtendedTcpTable(table, &tableSize, FALSE, AF_INET6,
+ TCP_TABLE_OWNER_PID_ALL, 0) == 0)
+ {
+ tcp6Table = table;
+
+ for (i = 0; i < tcp6Table->dwNumEntries; i++)
+ {
+ if (tcp6Table->table[i].dwOwningPid != pid) {
+ continue;
+ }
+
+ if (memcmp(tcp6Table->table[i].ucLocalAddr, null_address, 16) != 0 ||
+ tcp6Table->table[i].dwLocalPort != 0)
+ {
+ struct in6_addr addr;
+
+ memcpy(&addr, tcp6Table->table[i].ucLocalAddr, 16);
+ rtlIpv6AddressToStringA(&addr, addressBufferLocal);
+ addressTupleLocal = Py_BuildValue("(si)", addressBufferLocal,
+ BYTESWAP_USHORT(tcp6Table->table[i].dwLocalPort));
+ }
+ else
+ {
+ addressTupleLocal = PyTuple_New(0);
+ }
+
+ // On Windows <= XP, remote addr is filled even if socket
+ // is in LISTEN mode in which case we just ignore it.
+ if ((memcmp(tcp6Table->table[i].ucRemoteAddr, null_address, 16) != 0 ||
+ tcp6Table->table[i].dwRemotePort != 0) &&
+ (tcp6Table->table[i].dwState != MIB_TCP_STATE_LISTEN))
+ {
+ struct in6_addr addr;
+
+ memcpy(&addr, tcp6Table->table[i].ucRemoteAddr, 16);
+ rtlIpv6AddressToStringA(&addr, addressBufferRemote);
+ addressTupleRemote = Py_BuildValue("(si)", addressBufferRemote,
+ BYTESWAP_USHORT(tcp6Table->table[i].dwRemotePort));
+ }
+ else
+ {
+ addressTupleRemote = PyTuple_New(0);
+ }
+
+ connectionTuple = Py_BuildValue("(iiiNNs)",
+ -1,
+ AF_INET6,
+ SOCK_STREAM,
+ addressTupleLocal,
+ addressTupleRemote,
+ state_to_string(tcp6Table->table[i].dwState)
+ );
+ PyList_Append(connectionsList, connectionTuple);
+ }
+ }
+
+ free(table);
+
+ /* UDP IPv4 */
+
+ tableSize = 0;
+ getExtendedUdpTable(NULL, &tableSize, FALSE, AF_INET,
+ UDP_TABLE_OWNER_PID, 0);
+
+ table = malloc(tableSize);
+
+ if (getExtendedUdpTable(table, &tableSize, FALSE, AF_INET,
+ UDP_TABLE_OWNER_PID, 0) == 0)
+ {
+ udp4Table = table;
+
+ for (i = 0; i < udp4Table->dwNumEntries; i++)
+ {
+ if (udp4Table->table[i].dwOwningPid != pid)
+ continue;
+
+ if (udp4Table->table[i].dwLocalAddr != 0 ||
+ udp4Table->table[i].dwLocalPort != 0)
+ {
+ struct in_addr addr;
+
+ addr.S_un.S_addr = udp4Table->table[i].dwLocalAddr;
+ rtlIpv4AddressToStringA(&addr, addressBufferLocal);
+ addressTupleLocal = Py_BuildValue("(si)", addressBufferLocal,
+ BYTESWAP_USHORT(udp4Table->table[i].dwLocalPort));
+ }
+ else
+ {
+ addressTupleLocal = PyTuple_New(0);
+ }
+
+ connectionTuple = Py_BuildValue("(iiiNNs)",
+ -1,
+ AF_INET,
+ SOCK_DGRAM,
+ addressTupleLocal,
+ PyTuple_New(0),
+ ""
+ );
+ PyList_Append(connectionsList, connectionTuple);
+ }
+ }
+
+ free(table);
+
+ /* UDP IPv6 */
+
+ tableSize = 0;
+ getExtendedUdpTable(NULL, &tableSize, FALSE, AF_INET6, UDP_TABLE_OWNER_PID, 0);
+
+ table = malloc(tableSize);
+
+ if (getExtendedUdpTable(table, &tableSize, FALSE, AF_INET6, UDP_TABLE_OWNER_PID, 0) == 0)
+ {
+ udp6Table = table;
+
+ for (i = 0; i < udp6Table->dwNumEntries; i++)
+ {
+ if (udp6Table->table[i].dwOwningPid != pid) {
+ continue;
+ }
+
+ if (memcmp(udp6Table->table[i].ucLocalAddr, null_address, 16) != 0 ||
+ udp6Table->table[i].dwLocalPort != 0)
+ {
+ struct in6_addr addr;
+
+ memcpy(&addr, udp6Table->table[i].ucLocalAddr, 16);
+ rtlIpv6AddressToStringA(&addr, addressBufferLocal);
+ addressTupleLocal = Py_BuildValue("(si)", addressBufferLocal,
+ BYTESWAP_USHORT(udp6Table->table[i].dwLocalPort));
+ }
+ else
+ {
+ addressTupleLocal = PyTuple_New(0);
+ }
+
+ connectionTuple = Py_BuildValue("(iiiNNs)",
+ -1,
+ AF_INET6,
+ SOCK_DGRAM,
+ addressTupleLocal,
+ PyTuple_New(0),
+ ""
+ );
+ PyList_Append(connectionsList, connectionTuple);
+ }
+ }
+
+ free(table);
+
+ return connectionsList;
+}
+
« no previous file with comments | « third_party/psutil/psutil/_psutil_mswindows.h ('k') | third_party/psutil/psutil/_psutil_osx.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698