summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2020-01-02 05:28:29 +0100
committerGiampaolo Rodola <g.rodola@gmail.com>2020-01-02 05:28:29 +0100
commit616f519b1f9f2d59e68eccea2f234b1c0e6ff5ed (patch)
treec8f7d03fc70fe467918b54c352eaa5d1c0d03e31
parent8d184ed7d1c5c10cc38c577b0d7f681e69c2d8d4 (diff)
parent0cbab098df8f8d6e242917d44c2231e0a35c8c11 (diff)
downloadpsutil-616f519b1f9f2d59e68eccea2f234b1c0e6ff5ed.tar.gz
Merge branch 'master' of github.com:giampaolo/psutil
-rw-r--r--psutil/_psutil_windows.c463
-rw-r--r--psutil/arch/windows/process_handles.c3
-rw-r--r--psutil/arch/windows/process_info.c271
-rw-r--r--psutil/arch/windows/process_info.h7
-rw-r--r--psutil/arch/windows/process_utils.c286
-rw-r--r--psutil/arch/windows/process_utils.h11
-rw-r--r--psutil/arch/windows/socks.c484
-rw-r--r--psutil/arch/windows/socks.h9
-rwxr-xr-xscripts/internal/winmake.py54
-rwxr-xr-xsetup.py6
10 files changed, 853 insertions, 741 deletions
diff --git a/psutil/_psutil_windows.c b/psutil/_psutil_windows.c
index f35d0076..660e08af 100644
--- a/psutil/_psutil_windows.c
+++ b/psutil/_psutil_windows.c
@@ -27,7 +27,7 @@
#include <wtsapi32.h> // users()
#include <PowrProf.h> // cpu_freq()
#if (_WIN32_WINNT >= 0x0600) // Windows >= Vista
-#include <ws2tcpip.h> // net_connections()
+#include <ws2tcpip.h> // net_io_counters()
#endif
// Link with Iphlpapi.lib
@@ -36,10 +36,12 @@
#include "arch/windows/ntextapi.h"
#include "arch/windows/global.h"
#include "arch/windows/security.h"
+#include "arch/windows/process_utils.h"
#include "arch/windows/process_info.h"
#include "arch/windows/process_handles.h"
#include "arch/windows/inet_ntop.h"
#include "arch/windows/services.h"
+#include "arch/windows/socks.h"
#include "arch/windows/wmi.h"
#include "_psutil_common.h"
@@ -54,7 +56,6 @@
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
#define LO_T 1e-7
#define HI_T 429.4967296
-#define BYTESWAP_USHORT(x) ((((USHORT)(x) << 8) | ((USHORT)(x) >> 8)) & 0xffff)
#ifndef AF_INET6
#define AF_INET6 23
#endif
@@ -1355,464 +1356,6 @@ error:
}
-// https://msdn.microsoft.com/library/aa365928.aspx
-// TODO properly handle return code
-static DWORD __GetExtendedTcpTable(_GetExtendedTcpTable call,
- ULONG address_family,
- PVOID * data, DWORD * size)
-{
- // Due to other processes being active on the machine, it's possible
- // that the size of the table increases between the moment where we
- // query the size and the moment where we query the data. Therefore, it's
- // important to call this in a loop to retry if that happens.
- // See https://github.com/giampaolo/psutil/pull/1335 concerning 0xC0000001 error
- // and https://github.com/giampaolo/psutil/issues/1294
- DWORD error = ERROR_INSUFFICIENT_BUFFER;
- *size = 0;
- *data = NULL;
- error = call(NULL, size, FALSE, address_family,
- TCP_TABLE_OWNER_PID_ALL, 0);
- while (error == ERROR_INSUFFICIENT_BUFFER || error == 0xC0000001)
- {
- *data = malloc(*size);
- if (*data == NULL) {
- error = ERROR_NOT_ENOUGH_MEMORY;
- continue;
- }
- error = call(*data, size, FALSE, address_family,
- TCP_TABLE_OWNER_PID_ALL, 0);
- if (error != NO_ERROR) {
- free(*data);
- *data = NULL;
- }
- }
- return error;
-}
-
-
-// https://msdn.microsoft.com/library/aa365930.aspx
-// TODO properly check return value
-static DWORD __GetExtendedUdpTable(_GetExtendedUdpTable call,
- ULONG address_family,
- PVOID * data, DWORD * size)
-{
- // Due to other processes being active on the machine, it's possible
- // that the size of the table increases between the moment where we
- // query the size and the moment where we query the data. Therefore, it's
- // important to call this in a loop to retry if that happens.
- // See https://github.com/giampaolo/psutil/pull/1335 concerning 0xC0000001 error
- // and https://github.com/giampaolo/psutil/issues/1294
- DWORD error = ERROR_INSUFFICIENT_BUFFER;
- *size = 0;
- *data = NULL;
- error = call(NULL, size, FALSE, address_family,
- UDP_TABLE_OWNER_PID, 0);
- while (error == ERROR_INSUFFICIENT_BUFFER || error == 0xC0000001)
- {
- *data = malloc(*size);
- if (*data == NULL) {
- error = ERROR_NOT_ENOUGH_MEMORY;
- continue;
- }
- error = call(*data, size, FALSE, address_family,
- UDP_TABLE_OWNER_PID, 0);
- if (error != NO_ERROR) {
- free(*data);
- *data = NULL;
- }
- }
-
- if (error == ERROR_NOT_ENOUGH_MEMORY) {
- PyErr_NoMemory();
- return 1;
- }
- if (error != NO_ERROR) {
- PyErr_SetFromWindowsErr(error);
- return 1;
- }
- return 0;
-}
-
-
-#define psutil_conn_decref_objs() \
- Py_DECREF(_AF_INET); \
- Py_DECREF(_AF_INET6);\
- Py_DECREF(_SOCK_STREAM);\
- Py_DECREF(_SOCK_DGRAM);
-
-
-/*
- * Return a list of network connections opened by a process
- */
-static PyObject *
-psutil_net_connections(PyObject *self, PyObject *args) {
- static long null_address[4] = { 0, 0, 0, 0 };
- unsigned long pid;
- int pid_return;
- PVOID table = NULL;
- DWORD tableSize;
- DWORD error;
- 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];
- CHAR addressBufferRemote[65];
-
- PyObject *py_retlist;
- PyObject *py_conn_tuple = NULL;
- PyObject *py_af_filter = NULL;
- PyObject *py_type_filter = NULL;
- PyObject *py_addr_tuple_local = NULL;
- PyObject *py_addr_tuple_remote = NULL;
- PyObject *_AF_INET = PyLong_FromLong((long)AF_INET);
- PyObject *_AF_INET6 = PyLong_FromLong((long)AF_INET6);
- PyObject *_SOCK_STREAM = PyLong_FromLong((long)SOCK_STREAM);
- PyObject *_SOCK_DGRAM = PyLong_FromLong((long)SOCK_DGRAM);
-
- // Import some functions.
- if (! PyArg_ParseTuple(args, "lOO", &pid, &py_af_filter, &py_type_filter))
- goto error;
-
- if (!PySequence_Check(py_af_filter) || !PySequence_Check(py_type_filter)) {
- psutil_conn_decref_objs();
- PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence");
- return NULL;
- }
-
- if (pid != -1) {
- pid_return = psutil_pid_is_running(pid);
- if (pid_return == 0) {
- psutil_conn_decref_objs();
- return NoSuchProcess("");
- }
- else if (pid_return == -1) {
- psutil_conn_decref_objs();
- return NULL;
- }
- }
-
- py_retlist = PyList_New(0);
- if (py_retlist == NULL) {
- psutil_conn_decref_objs();
- return NULL;
- }
-
- // TCP IPv4
-
- if ((PySequence_Contains(py_af_filter, _AF_INET) == 1) &&
- (PySequence_Contains(py_type_filter, _SOCK_STREAM) == 1))
- {
- table = NULL;
- py_conn_tuple = NULL;
- py_addr_tuple_local = NULL;
- py_addr_tuple_remote = NULL;
- tableSize = 0;
-
- error = __GetExtendedTcpTable(psutil_GetExtendedTcpTable,
- AF_INET, &table, &tableSize);
- if (error != 0)
- goto error;
- tcp4Table = table;
- for (i = 0; i < tcp4Table->dwNumEntries; i++) {
- if (pid != -1) {
- 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;
- psutil_rtlIpv4AddressToStringA(&addr, addressBufferLocal);
- py_addr_tuple_local = Py_BuildValue(
- "(si)",
- addressBufferLocal,
- BYTESWAP_USHORT(tcp4Table->table[i].dwLocalPort));
- }
- else {
- py_addr_tuple_local = PyTuple_New(0);
- }
-
- if (py_addr_tuple_local == NULL)
- goto error;
-
- // 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;
- psutil_rtlIpv4AddressToStringA(&addr, addressBufferRemote);
- py_addr_tuple_remote = Py_BuildValue(
- "(si)",
- addressBufferRemote,
- BYTESWAP_USHORT(tcp4Table->table[i].dwRemotePort));
- }
- else
- {
- py_addr_tuple_remote = PyTuple_New(0);
- }
-
- if (py_addr_tuple_remote == NULL)
- goto error;
-
- py_conn_tuple = Py_BuildValue(
- "(iiiNNiI)",
- -1,
- AF_INET,
- SOCK_STREAM,
- py_addr_tuple_local,
- py_addr_tuple_remote,
- tcp4Table->table[i].dwState,
- tcp4Table->table[i].dwOwningPid);
- if (!py_conn_tuple)
- goto error;
- if (PyList_Append(py_retlist, py_conn_tuple))
- goto error;
- Py_CLEAR(py_conn_tuple);
- }
-
- free(table);
- table = NULL;
- tableSize = 0;
- }
-
- // TCP IPv6
- if ((PySequence_Contains(py_af_filter, _AF_INET6) == 1) &&
- (PySequence_Contains(py_type_filter, _SOCK_STREAM) == 1) &&
- (psutil_rtlIpv6AddressToStringA != NULL))
- {
- table = NULL;
- py_conn_tuple = NULL;
- py_addr_tuple_local = NULL;
- py_addr_tuple_remote = NULL;
- tableSize = 0;
-
- error = __GetExtendedTcpTable(psutil_GetExtendedTcpTable,
- AF_INET6, &table, &tableSize);
- if (error != 0)
- goto error;
- tcp6Table = table;
- for (i = 0; i < tcp6Table->dwNumEntries; i++)
- {
- if (pid != -1) {
- 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);
- psutil_rtlIpv6AddressToStringA(&addr, addressBufferLocal);
- py_addr_tuple_local = Py_BuildValue(
- "(si)",
- addressBufferLocal,
- BYTESWAP_USHORT(tcp6Table->table[i].dwLocalPort));
- }
- else {
- py_addr_tuple_local = PyTuple_New(0);
- }
-
- if (py_addr_tuple_local == NULL)
- goto error;
-
- // 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);
- psutil_rtlIpv6AddressToStringA(&addr, addressBufferRemote);
- py_addr_tuple_remote = Py_BuildValue(
- "(si)",
- addressBufferRemote,
- BYTESWAP_USHORT(tcp6Table->table[i].dwRemotePort));
- }
- else {
- py_addr_tuple_remote = PyTuple_New(0);
- }
-
- if (py_addr_tuple_remote == NULL)
- goto error;
-
- py_conn_tuple = Py_BuildValue(
- "(iiiNNiI)",
- -1,
- AF_INET6,
- SOCK_STREAM,
- py_addr_tuple_local,
- py_addr_tuple_remote,
- tcp6Table->table[i].dwState,
- tcp6Table->table[i].dwOwningPid);
- if (!py_conn_tuple)
- goto error;
- if (PyList_Append(py_retlist, py_conn_tuple))
- goto error;
- Py_CLEAR(py_conn_tuple);
- }
-
- free(table);
- table = NULL;
- tableSize = 0;
- }
-
- // UDP IPv4
-
- if ((PySequence_Contains(py_af_filter, _AF_INET) == 1) &&
- (PySequence_Contains(py_type_filter, _SOCK_DGRAM) == 1))
- {
- table = NULL;
- py_conn_tuple = NULL;
- py_addr_tuple_local = NULL;
- py_addr_tuple_remote = NULL;
- tableSize = 0;
- error = __GetExtendedUdpTable(psutil_GetExtendedUdpTable,
- AF_INET, &table, &tableSize);
- if (error != 0)
- goto error;
- udp4Table = table;
- for (i = 0; i < udp4Table->dwNumEntries; i++)
- {
- if (pid != -1) {
- 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;
- psutil_rtlIpv4AddressToStringA(&addr, addressBufferLocal);
- py_addr_tuple_local = Py_BuildValue(
- "(si)",
- addressBufferLocal,
- BYTESWAP_USHORT(udp4Table->table[i].dwLocalPort));
- }
- else {
- py_addr_tuple_local = PyTuple_New(0);
- }
-
- if (py_addr_tuple_local == NULL)
- goto error;
-
- py_conn_tuple = Py_BuildValue(
- "(iiiNNiI)",
- -1,
- AF_INET,
- SOCK_DGRAM,
- py_addr_tuple_local,
- PyTuple_New(0),
- PSUTIL_CONN_NONE,
- udp4Table->table[i].dwOwningPid);
- if (!py_conn_tuple)
- goto error;
- if (PyList_Append(py_retlist, py_conn_tuple))
- goto error;
- Py_CLEAR(py_conn_tuple);
- }
-
- free(table);
- table = NULL;
- tableSize = 0;
- }
-
- // UDP IPv6
-
- if ((PySequence_Contains(py_af_filter, _AF_INET6) == 1) &&
- (PySequence_Contains(py_type_filter, _SOCK_DGRAM) == 1) &&
- (psutil_rtlIpv6AddressToStringA != NULL))
- {
- table = NULL;
- py_conn_tuple = NULL;
- py_addr_tuple_local = NULL;
- py_addr_tuple_remote = NULL;
- tableSize = 0;
- error = __GetExtendedUdpTable(psutil_GetExtendedUdpTable,
- AF_INET6, &table, &tableSize);
- if (error != 0)
- goto error;
- udp6Table = table;
- for (i = 0; i < udp6Table->dwNumEntries; i++) {
- if (pid != -1) {
- 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);
- psutil_rtlIpv6AddressToStringA(&addr, addressBufferLocal);
- py_addr_tuple_local = Py_BuildValue(
- "(si)",
- addressBufferLocal,
- BYTESWAP_USHORT(udp6Table->table[i].dwLocalPort));
- }
- else {
- py_addr_tuple_local = PyTuple_New(0);
- }
-
- if (py_addr_tuple_local == NULL)
- goto error;
-
- py_conn_tuple = Py_BuildValue(
- "(iiiNNiI)",
- -1,
- AF_INET6,
- SOCK_DGRAM,
- py_addr_tuple_local,
- PyTuple_New(0),
- PSUTIL_CONN_NONE,
- udp6Table->table[i].dwOwningPid);
- if (!py_conn_tuple)
- goto error;
- if (PyList_Append(py_retlist, py_conn_tuple))
- goto error;
- Py_CLEAR(py_conn_tuple);
- }
-
- free(table);
- table = NULL;
- tableSize = 0;
- }
-
- psutil_conn_decref_objs();
- return py_retlist;
-
-error:
- psutil_conn_decref_objs();
- Py_XDECREF(py_conn_tuple);
- Py_XDECREF(py_addr_tuple_local);
- Py_XDECREF(py_addr_tuple_remote);
- Py_DECREF(py_retlist);
- if (table != NULL)
- free(table);
- return NULL;
-}
-
-
/*
* Get process priority as a Python integer.
*/
diff --git a/psutil/arch/windows/process_handles.c b/psutil/arch/windows/process_handles.c
index 5966669e..40b209ee 100644
--- a/psutil/arch/windows/process_handles.c
+++ b/psutil/arch/windows/process_handles.c
@@ -8,10 +8,11 @@
#include <windows.h>
#include <Psapi.h>
#include <Python.h>
+
#include "ntextapi.h"
#include "global.h"
#include "process_handles.h"
-#include "process_info.h"
+#include "process_utils.h"
#include "../../_psutil_common.h"
CRITICAL_SECTION g_cs;
diff --git a/psutil/arch/windows/process_info.c b/psutil/arch/windows/process_info.c
index 5ea5f765..a9c2c131 100644
--- a/psutil/arch/windows/process_info.c
+++ b/psutil/arch/windows/process_info.c
@@ -16,6 +16,7 @@
#include "global.h"
#include "security.h"
#include "process_info.h"
+#include "process_utils.h"
#include "../../_psutil_common.h"
@@ -138,276 +139,6 @@ typedef struct {
#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L)
-/*
- * Return 1 if PID exists, 0 if not, -1 on error.
- */
-int
-psutil_pid_in_pids(DWORD pid) {
- DWORD *proclist = NULL;
- DWORD numberOfReturnedPIDs;
- DWORD i;
-
- proclist = psutil_get_pids(&numberOfReturnedPIDs);
- if (proclist == NULL)
- return -1;
- for (i = 0; i < numberOfReturnedPIDs; i++) {
- if (proclist[i] == pid) {
- free(proclist);
- return 1;
- }
- }
- free(proclist);
- return 0;
-}
-
-
-/*
- * Given a process HANDLE checks whether it's actually running.
- * Returns:
- * - 1: running
- * - 0: not running
- * - -1: WindowsError
- * - -2: AssertionError
- */
-int
-psutil_is_phandle_running(HANDLE hProcess, DWORD pid) {
- DWORD processExitCode = 0;
-
- if (hProcess == NULL) {
- if (GetLastError() == ERROR_INVALID_PARAMETER) {
- // Yeah, this is the actual error code in case of
- // "no such process".
- if (! psutil_assert_pid_not_exists(
- pid, "iphr: OpenProcess() -> ERROR_INVALID_PARAMETER")) {
- return -2;
- }
- return 0;
- }
- return -1;
- }
-
- if (GetExitCodeProcess(hProcess, &processExitCode)) {
- // XXX - maybe STILL_ACTIVE is not fully reliable as per:
- // http://stackoverflow.com/questions/1591342/#comment47830782_1591379
- if (processExitCode == STILL_ACTIVE) {
- if (! psutil_assert_pid_exists(
- pid, "iphr: GetExitCodeProcess() -> STILL_ACTIVE")) {
- return -2;
- }
- return 1;
- }
- else {
- // We can't be sure so we look into pids.
- if (psutil_pid_in_pids(pid) == 1) {
- return 1;
- }
- else {
- CloseHandle(hProcess);
- return 0;
- }
- }
- }
-
- CloseHandle(hProcess);
- if (! psutil_assert_pid_not_exists( pid, "iphr: exit fun")) {
- return -2;
- }
- return -1;
-}
-
-
-/*
- * Given a process HANDLE checks whether it's actually running and if
- * it does return it, else return NULL with the proper Python exception
- * set.
- */
-HANDLE
-psutil_check_phandle(HANDLE hProcess, DWORD pid) {
- int ret = psutil_is_phandle_running(hProcess, pid);
- if (ret == 1) {
- return hProcess;
- }
- else if (ret == 0) {
- return NoSuchProcess("");
- }
- else if (ret == -1) {
- if (GetLastError() == ERROR_ACCESS_DENIED)
- return PyErr_SetFromWindowsErr(0);
- else
- return PyErr_SetFromOSErrnoWithSyscall("OpenProcess");
- }
- else {
- 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
-psutil_handle_from_pid(DWORD pid, DWORD access) {
- HANDLE hProcess;
-
- if (pid == 0) {
- // otherwise we'd get NoSuchProcess
- return AccessDenied("");
- }
- // needed for GetExitCodeProcess
- access |= PROCESS_QUERY_LIMITED_INFORMATION;
- hProcess = OpenProcess(access, FALSE, pid);
- return psutil_check_phandle(hProcess, pid);
-}
-
-
-DWORD *
-psutil_get_pids(DWORD *numberOfReturnedPIDs) {
- // 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;
- int procArraySz = 0;
-
- // Stores the byte size of the returned array from enumprocesses
- DWORD enumReturnSz = 0;
-
- do {
- procArraySz += 1024;
- if (procArray != NULL)
- free(procArray);
- procArrayByteSz = procArraySz * sizeof(DWORD);
- procArray = malloc(procArrayByteSz);
- if (procArray == NULL) {
- PyErr_NoMemory();
- return NULL;
- }
- if (! EnumProcesses(procArray, procArrayByteSz, &enumReturnSz)) {
- free(procArray);
- PyErr_SetFromWindowsErr(0);
- return NULL;
- }
- } while (enumReturnSz == procArraySz * sizeof(DWORD));
-
- // The number of elements is the returned size / size of each element
- *numberOfReturnedPIDs = enumReturnSz / sizeof(DWORD);
-
- return procArray;
-}
-
-
-int
-psutil_assert_pid_exists(DWORD pid, char *err) {
- if (PSUTIL_TESTING) {
- if (psutil_pid_in_pids(pid) == 0) {
- PyErr_SetString(PyExc_AssertionError, err);
- return 0;
- }
- }
- return 1;
-}
-
-
-int
-psutil_assert_pid_not_exists(DWORD pid, char *err) {
- if (PSUTIL_TESTING) {
- if (psutil_pid_in_pids(pid) == 1) {
- PyErr_SetString(PyExc_AssertionError, err);
- return 0;
- }
- }
- return 1;
-}
-
-
-/*
-/* Check for PID existance by using OpenProcess() + GetExitCodeProcess.
-/* Returns:
- * 1: pid exists
- * 0: it doesn't
- * -1: error
- */
-int
-psutil_pid_is_running(DWORD pid) {
- HANDLE hProcess;
- DWORD exitCode;
- DWORD err;
-
- // Special case for PID 0 System Idle Process
- if (pid == 0)
- return 1;
- if (pid < 0)
- return 0;
- hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
- if (NULL == hProcess) {
- err = GetLastError();
- // Yeah, this is the actual error code in case of "no such process".
- if (err == ERROR_INVALID_PARAMETER) {
- if (! psutil_assert_pid_not_exists(
- pid, "pir: OpenProcess() -> INVALID_PARAMETER")) {
- return -1;
- }
- return 0;
- }
- // Access denied obviously means there's a process to deny access to.
- else if (err == ERROR_ACCESS_DENIED) {
- if (! psutil_assert_pid_exists(
- pid, "pir: OpenProcess() ACCESS_DENIED")) {
- return -1;
- }
- return 1;
- }
- // Be strict and raise an exception; the caller is supposed
- // to take -1 into account.
- else {
- PyErr_SetFromOSErrnoWithSyscall("OpenProcess(PROCESS_VM_READ)");
- return -1;
- }
- }
-
- if (GetExitCodeProcess(hProcess, &exitCode)) {
- CloseHandle(hProcess);
- // XXX - maybe STILL_ACTIVE is not fully reliable as per:
- // http://stackoverflow.com/questions/1591342/#comment47830782_1591379
- if (exitCode == STILL_ACTIVE) {
- if (! psutil_assert_pid_exists(
- pid, "pir: GetExitCodeProcess() -> STILL_ACTIVE")) {
- return -1;
- }
- return 1;
- }
- // We can't be sure so we look into pids.
- else {
- return psutil_pid_in_pids(pid);
- }
- }
- else {
- err = GetLastError();
- CloseHandle(hProcess);
- // Same as for OpenProcess, assume access denied means there's
- // a process to deny access to.
- if (err == ERROR_ACCESS_DENIED) {
- if (! psutil_assert_pid_exists(
- pid, "pir: GetExitCodeProcess() -> ERROR_ACCESS_DENIED")) {
- return -1;
- }
- return 1;
- }
- else {
- PyErr_SetFromOSErrnoWithSyscall("GetExitCodeProcess");
- return -1;
- }
- }
-}
-
-
/* Given a pointer into a process's memory, figure out how much data can be
* read from it. */
static int
diff --git a/psutil/arch/windows/process_info.h b/psutil/arch/windows/process_info.h
index 4278c4df..afbbb72d 100644
--- a/psutil/arch/windows/process_info.h
+++ b/psutil/arch/windows/process_info.h
@@ -15,15 +15,8 @@
#define HANDLE_TO_PYNUM(handle) PyLong_FromUnsignedLong((unsigned long) handle)
#define PYNUM_TO_HANDLE(obj) ((HANDLE)PyLong_AsUnsignedLong(obj))
-DWORD* psutil_get_pids(DWORD *numberOfReturnedPIDs);
-HANDLE psutil_handle_from_pid(DWORD pid, DWORD dwDesiredAccess);
-int psutil_pid_is_running(DWORD pid);
int psutil_get_proc_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess,
PVOID *retBuffer);
-
-int psutil_assert_pid_exists(DWORD pid, char *err);
-int psutil_assert_pid_not_exists(DWORD pid, char *err);
-
PyObject* psutil_get_cmdline(long pid, int use_peb);
PyObject* psutil_get_cwd(long pid);
PyObject* psutil_get_environ(long pid);
diff --git a/psutil/arch/windows/process_utils.c b/psutil/arch/windows/process_utils.c
new file mode 100644
index 00000000..a81a3253
--- /dev/null
+++ b/psutil/arch/windows/process_utils.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Helper process functions.
+ */
+
+#include <Python.h>
+#include <windows.h>
+#include <Psapi.h>
+#include <tlhelp32.h>
+
+#include "ntextapi.h"
+#include "global.h"
+#include "process_utils.h"
+#include "../../_psutil_common.h"
+
+
+DWORD *
+psutil_get_pids(DWORD *numberOfReturnedPIDs) {
+ // 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;
+ int procArraySz = 0;
+
+ // Stores the byte size of the returned array from enumprocesses
+ DWORD enumReturnSz = 0;
+
+ do {
+ procArraySz += 1024;
+ if (procArray != NULL)
+ free(procArray);
+ procArrayByteSz = procArraySz * sizeof(DWORD);
+ procArray = malloc(procArrayByteSz);
+ if (procArray == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ if (! EnumProcesses(procArray, procArrayByteSz, &enumReturnSz)) {
+ free(procArray);
+ PyErr_SetFromWindowsErr(0);
+ return NULL;
+ }
+ } while (enumReturnSz == procArraySz * sizeof(DWORD));
+
+ // The number of elements is the returned size / size of each element
+ *numberOfReturnedPIDs = enumReturnSz / sizeof(DWORD);
+
+ return procArray;
+}
+
+/*
+ * Return 1 if PID exists, 0 if not, -1 on error.
+ */
+int
+psutil_pid_in_pids(DWORD pid) {
+ DWORD *proclist = NULL;
+ DWORD numberOfReturnedPIDs;
+ DWORD i;
+
+ proclist = psutil_get_pids(&numberOfReturnedPIDs);
+ if (proclist == NULL)
+ return -1;
+ for (i = 0; i < numberOfReturnedPIDs; i++) {
+ if (proclist[i] == pid) {
+ free(proclist);
+ return 1;
+ }
+ }
+ free(proclist);
+ return 0;
+}
+
+
+/*
+ * Given a process HANDLE checks whether it's actually running.
+ * Returns:
+ * - 1: running
+ * - 0: not running
+ * - -1: WindowsError
+ * - -2: AssertionError
+ */
+int
+psutil_is_phandle_running(HANDLE hProcess, DWORD pid) {
+ DWORD processExitCode = 0;
+
+ if (hProcess == NULL) {
+ if (GetLastError() == ERROR_INVALID_PARAMETER) {
+ // Yeah, this is the actual error code in case of
+ // "no such process".
+ if (! psutil_assert_pid_not_exists(
+ pid, "iphr: OpenProcess() -> ERROR_INVALID_PARAMETER")) {
+ return -2;
+ }
+ return 0;
+ }
+ return -1;
+ }
+
+ if (GetExitCodeProcess(hProcess, &processExitCode)) {
+ // XXX - maybe STILL_ACTIVE is not fully reliable as per:
+ // http://stackoverflow.com/questions/1591342/#comment47830782_1591379
+ if (processExitCode == STILL_ACTIVE) {
+ if (! psutil_assert_pid_exists(
+ pid, "iphr: GetExitCodeProcess() -> STILL_ACTIVE")) {
+ return -2;
+ }
+ return 1;
+ }
+ else {
+ // We can't be sure so we look into pids.
+ if (psutil_pid_in_pids(pid) == 1) {
+ return 1;
+ }
+ else {
+ CloseHandle(hProcess);
+ return 0;
+ }
+ }
+ }
+
+ CloseHandle(hProcess);
+ if (! psutil_assert_pid_not_exists( pid, "iphr: exit fun")) {
+ return -2;
+ }
+ return -1;
+}
+
+
+/*
+ * Given a process HANDLE checks whether it's actually running and if
+ * it does return it, else return NULL with the proper Python exception
+ * set.
+ */
+HANDLE
+psutil_check_phandle(HANDLE hProcess, DWORD pid) {
+ int ret = psutil_is_phandle_running(hProcess, pid);
+ if (ret == 1) {
+ return hProcess;
+ }
+ else if (ret == 0) {
+ return NoSuchProcess("");
+ }
+ else if (ret == -1) {
+ if (GetLastError() == ERROR_ACCESS_DENIED)
+ return PyErr_SetFromWindowsErr(0);
+ else
+ return PyErr_SetFromOSErrnoWithSyscall("OpenProcess");
+ }
+ else {
+ 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
+psutil_handle_from_pid(DWORD pid, DWORD access) {
+ HANDLE hProcess;
+
+ if (pid == 0) {
+ // otherwise we'd get NoSuchProcess
+ return AccessDenied("");
+ }
+ // needed for GetExitCodeProcess
+ access |= PROCESS_QUERY_LIMITED_INFORMATION;
+ hProcess = OpenProcess(access, FALSE, pid);
+ return psutil_check_phandle(hProcess, pid);
+}
+
+
+int
+psutil_assert_pid_exists(DWORD pid, char *err) {
+ if (PSUTIL_TESTING) {
+ if (psutil_pid_in_pids(pid) == 0) {
+ PyErr_SetString(PyExc_AssertionError, err);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
+int
+psutil_assert_pid_not_exists(DWORD pid, char *err) {
+ if (PSUTIL_TESTING) {
+ if (psutil_pid_in_pids(pid) == 1) {
+ PyErr_SetString(PyExc_AssertionError, err);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
+/*
+/* Check for PID existance by using OpenProcess() + GetExitCodeProcess.
+/* Returns:
+ * 1: pid exists
+ * 0: it doesn't
+ * -1: error
+ */
+int
+psutil_pid_is_running(DWORD pid) {
+ HANDLE hProcess;
+ DWORD exitCode;
+ DWORD err;
+
+ // Special case for PID 0 System Idle Process
+ if (pid == 0)
+ return 1;
+ if (pid < 0)
+ return 0;
+ hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
+ if (NULL == hProcess) {
+ err = GetLastError();
+ // Yeah, this is the actual error code in case of "no such process".
+ if (err == ERROR_INVALID_PARAMETER) {
+ if (! psutil_assert_pid_not_exists(
+ pid, "pir: OpenProcess() -> INVALID_PARAMETER")) {
+ return -1;
+ }
+ return 0;
+ }
+ // Access denied obviously means there's a process to deny access to.
+ else if (err == ERROR_ACCESS_DENIED) {
+ if (! psutil_assert_pid_exists(
+ pid, "pir: OpenProcess() ACCESS_DENIED")) {
+ return -1;
+ }
+ return 1;
+ }
+ // Be strict and raise an exception; the caller is supposed
+ // to take -1 into account.
+ else {
+ PyErr_SetFromOSErrnoWithSyscall("OpenProcess(PROCESS_VM_READ)");
+ return -1;
+ }
+ }
+
+ if (GetExitCodeProcess(hProcess, &exitCode)) {
+ CloseHandle(hProcess);
+ // XXX - maybe STILL_ACTIVE is not fully reliable as per:
+ // http://stackoverflow.com/questions/1591342/#comment47830782_1591379
+ if (exitCode == STILL_ACTIVE) {
+ if (! psutil_assert_pid_exists(
+ pid, "pir: GetExitCodeProcess() -> STILL_ACTIVE")) {
+ return -1;
+ }
+ return 1;
+ }
+ // We can't be sure so we look into pids.
+ else {
+ return psutil_pid_in_pids(pid);
+ }
+ }
+ else {
+ err = GetLastError();
+ CloseHandle(hProcess);
+ // Same as for OpenProcess, assume access denied means there's
+ // a process to deny access to.
+ if (err == ERROR_ACCESS_DENIED) {
+ if (! psutil_assert_pid_exists(
+ pid, "pir: GetExitCodeProcess() -> ERROR_ACCESS_DENIED")) {
+ return -1;
+ }
+ return 1;
+ }
+ else {
+ PyErr_SetFromOSErrnoWithSyscall("GetExitCodeProcess");
+ return -1;
+ }
+ }
+}
diff --git a/psutil/arch/windows/process_utils.h b/psutil/arch/windows/process_utils.h
new file mode 100644
index 00000000..a7171c5c
--- /dev/null
+++ b/psutil/arch/windows/process_utils.h
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+DWORD* psutil_get_pids(DWORD *numberOfReturnedPIDs);
+HANDLE psutil_handle_from_pid(DWORD pid, DWORD dwDesiredAccess);
+int psutil_pid_is_running(DWORD pid);
+int psutil_assert_pid_exists(DWORD pid, char *err);
+int psutil_assert_pid_not_exists(DWORD pid, char *err);
diff --git a/psutil/arch/windows/socks.c b/psutil/arch/windows/socks.c
new file mode 100644
index 00000000..b44a247b
--- /dev/null
+++ b/psutil/arch/windows/socks.c
@@ -0,0 +1,484 @@
+/*
+ * Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// Fixes clash between winsock2.h and windows.h
+#define WIN32_LEAN_AND_MEAN
+
+#include <Python.h>
+#include <windows.h>
+#if (_WIN32_WINNT >= 0x0600) // Windows >= Vista
+#include <ws2tcpip.h>
+#endif
+
+#include "ntextapi.h"
+#include "global.h"
+#include "process_utils.h"
+#include "../../_psutil_common.h"
+
+
+#define BYTESWAP_USHORT(x) ((((USHORT)(x) << 8) | ((USHORT)(x) >> 8)) & 0xffff)
+
+#ifndef AF_INET6
+#define AF_INET6 23
+#endif
+
+
+// https://msdn.microsoft.com/library/aa365928.aspx
+// TODO properly handle return code
+static DWORD __GetExtendedTcpTable(_GetExtendedTcpTable call,
+ ULONG address_family,
+ PVOID * data, DWORD * size)
+{
+ // Due to other processes being active on the machine, it's possible
+ // that the size of the table increases between the moment where we
+ // query the size and the moment where we query the data. Therefore, it's
+ // important to call this in a loop to retry if that happens.
+ // See https://github.com/giampaolo/psutil/pull/1335 concerning 0xC0000001 error
+ // and https://github.com/giampaolo/psutil/issues/1294
+ DWORD error = ERROR_INSUFFICIENT_BUFFER;
+ *size = 0;
+ *data = NULL;
+ error = call(NULL, size, FALSE, address_family,
+ TCP_TABLE_OWNER_PID_ALL, 0);
+ while (error == ERROR_INSUFFICIENT_BUFFER || error == 0xC0000001)
+ {
+ *data = malloc(*size);
+ if (*data == NULL) {
+ error = ERROR_NOT_ENOUGH_MEMORY;
+ continue;
+ }
+ error = call(*data, size, FALSE, address_family,
+ TCP_TABLE_OWNER_PID_ALL, 0);
+ if (error != NO_ERROR) {
+ free(*data);
+ *data = NULL;
+ }
+ }
+ return error;
+}
+
+
+// https://msdn.microsoft.com/library/aa365930.aspx
+// TODO properly check return value
+static DWORD __GetExtendedUdpTable(_GetExtendedUdpTable call,
+ ULONG address_family,
+ PVOID * data, DWORD * size)
+{
+ // Due to other processes being active on the machine, it's possible
+ // that the size of the table increases between the moment where we
+ // query the size and the moment where we query the data. Therefore, it's
+ // important to call this in a loop to retry if that happens.
+ // See https://github.com/giampaolo/psutil/pull/1335 concerning 0xC0000001 error
+ // and https://github.com/giampaolo/psutil/issues/1294
+ DWORD error = ERROR_INSUFFICIENT_BUFFER;
+ *size = 0;
+ *data = NULL;
+ error = call(NULL, size, FALSE, address_family,
+ UDP_TABLE_OWNER_PID, 0);
+ while (error == ERROR_INSUFFICIENT_BUFFER || error == 0xC0000001)
+ {
+ *data = malloc(*size);
+ if (*data == NULL) {
+ error = ERROR_NOT_ENOUGH_MEMORY;
+ continue;
+ }
+ error = call(*data, size, FALSE, address_family,
+ UDP_TABLE_OWNER_PID, 0);
+ if (error != NO_ERROR) {
+ free(*data);
+ *data = NULL;
+ }
+ }
+
+ if (error == ERROR_NOT_ENOUGH_MEMORY) {
+ PyErr_NoMemory();
+ return 1;
+ }
+ if (error != NO_ERROR) {
+ PyErr_SetFromWindowsErr(error);
+ return 1;
+ }
+ return 0;
+}
+
+
+#define psutil_conn_decref_objs() \
+ Py_DECREF(_AF_INET); \
+ Py_DECREF(_AF_INET6);\
+ Py_DECREF(_SOCK_STREAM);\
+ Py_DECREF(_SOCK_DGRAM);
+
+
+/*
+ * Return a list of network connections opened by a process
+ */
+PyObject *
+psutil_net_connections(PyObject *self, PyObject *args) {
+ static long null_address[4] = { 0, 0, 0, 0 };
+ unsigned long pid;
+ int pid_return;
+ PVOID table = NULL;
+ DWORD tableSize;
+ DWORD error;
+ 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];
+ CHAR addressBufferRemote[65];
+
+ PyObject *py_retlist;
+ PyObject *py_conn_tuple = NULL;
+ PyObject *py_af_filter = NULL;
+ PyObject *py_type_filter = NULL;
+ PyObject *py_addr_tuple_local = NULL;
+ PyObject *py_addr_tuple_remote = NULL;
+ PyObject *_AF_INET = PyLong_FromLong((long)AF_INET);
+ PyObject *_AF_INET6 = PyLong_FromLong((long)AF_INET6);
+ PyObject *_SOCK_STREAM = PyLong_FromLong((long)SOCK_STREAM);
+ PyObject *_SOCK_DGRAM = PyLong_FromLong((long)SOCK_DGRAM);
+
+ // Import some functions.
+ if (! PyArg_ParseTuple(args, "lOO", &pid, &py_af_filter, &py_type_filter))
+ goto error;
+
+ if (!PySequence_Check(py_af_filter) || !PySequence_Check(py_type_filter)) {
+ psutil_conn_decref_objs();
+ PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence");
+ return NULL;
+ }
+
+ if (pid != -1) {
+ pid_return = psutil_pid_is_running(pid);
+ if (pid_return == 0) {
+ psutil_conn_decref_objs();
+ return NoSuchProcess("");
+ }
+ else if (pid_return == -1) {
+ psutil_conn_decref_objs();
+ return NULL;
+ }
+ }
+
+ py_retlist = PyList_New(0);
+ if (py_retlist == NULL) {
+ psutil_conn_decref_objs();
+ return NULL;
+ }
+
+ // TCP IPv4
+
+ if ((PySequence_Contains(py_af_filter, _AF_INET) == 1) &&
+ (PySequence_Contains(py_type_filter, _SOCK_STREAM) == 1))
+ {
+ table = NULL;
+ py_conn_tuple = NULL;
+ py_addr_tuple_local = NULL;
+ py_addr_tuple_remote = NULL;
+ tableSize = 0;
+
+ error = __GetExtendedTcpTable(psutil_GetExtendedTcpTable,
+ AF_INET, &table, &tableSize);
+ if (error != 0)
+ goto error;
+ tcp4Table = table;
+ for (i = 0; i < tcp4Table->dwNumEntries; i++) {
+ if (pid != -1) {
+ 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;
+ psutil_rtlIpv4AddressToStringA(&addr, addressBufferLocal);
+ py_addr_tuple_local = Py_BuildValue(
+ "(si)",
+ addressBufferLocal,
+ BYTESWAP_USHORT(tcp4Table->table[i].dwLocalPort));
+ }
+ else {
+ py_addr_tuple_local = PyTuple_New(0);
+ }
+
+ if (py_addr_tuple_local == NULL)
+ goto error;
+
+ // 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;
+ psutil_rtlIpv4AddressToStringA(&addr, addressBufferRemote);
+ py_addr_tuple_remote = Py_BuildValue(
+ "(si)",
+ addressBufferRemote,
+ BYTESWAP_USHORT(tcp4Table->table[i].dwRemotePort));
+ }
+ else
+ {
+ py_addr_tuple_remote = PyTuple_New(0);
+ }
+
+ if (py_addr_tuple_remote == NULL)
+ goto error;
+
+ py_conn_tuple = Py_BuildValue(
+ "(iiiNNiI)",
+ -1,
+ AF_INET,
+ SOCK_STREAM,
+ py_addr_tuple_local,
+ py_addr_tuple_remote,
+ tcp4Table->table[i].dwState,
+ tcp4Table->table[i].dwOwningPid);
+ if (!py_conn_tuple)
+ goto error;
+ if (PyList_Append(py_retlist, py_conn_tuple))
+ goto error;
+ Py_CLEAR(py_conn_tuple);
+ }
+
+ free(table);
+ table = NULL;
+ tableSize = 0;
+ }
+
+ // TCP IPv6
+ if ((PySequence_Contains(py_af_filter, _AF_INET6) == 1) &&
+ (PySequence_Contains(py_type_filter, _SOCK_STREAM) == 1) &&
+ (psutil_rtlIpv6AddressToStringA != NULL))
+ {
+ table = NULL;
+ py_conn_tuple = NULL;
+ py_addr_tuple_local = NULL;
+ py_addr_tuple_remote = NULL;
+ tableSize = 0;
+
+ error = __GetExtendedTcpTable(psutil_GetExtendedTcpTable,
+ AF_INET6, &table, &tableSize);
+ if (error != 0)
+ goto error;
+ tcp6Table = table;
+ for (i = 0; i < tcp6Table->dwNumEntries; i++)
+ {
+ if (pid != -1) {
+ 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);
+ psutil_rtlIpv6AddressToStringA(&addr, addressBufferLocal);
+ py_addr_tuple_local = Py_BuildValue(
+ "(si)",
+ addressBufferLocal,
+ BYTESWAP_USHORT(tcp6Table->table[i].dwLocalPort));
+ }
+ else {
+ py_addr_tuple_local = PyTuple_New(0);
+ }
+
+ if (py_addr_tuple_local == NULL)
+ goto error;
+
+ // 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);
+ psutil_rtlIpv6AddressToStringA(&addr, addressBufferRemote);
+ py_addr_tuple_remote = Py_BuildValue(
+ "(si)",
+ addressBufferRemote,
+ BYTESWAP_USHORT(tcp6Table->table[i].dwRemotePort));
+ }
+ else {
+ py_addr_tuple_remote = PyTuple_New(0);
+ }
+
+ if (py_addr_tuple_remote == NULL)
+ goto error;
+
+ py_conn_tuple = Py_BuildValue(
+ "(iiiNNiI)",
+ -1,
+ AF_INET6,
+ SOCK_STREAM,
+ py_addr_tuple_local,
+ py_addr_tuple_remote,
+ tcp6Table->table[i].dwState,
+ tcp6Table->table[i].dwOwningPid);
+ if (!py_conn_tuple)
+ goto error;
+ if (PyList_Append(py_retlist, py_conn_tuple))
+ goto error;
+ Py_CLEAR(py_conn_tuple);
+ }
+
+ free(table);
+ table = NULL;
+ tableSize = 0;
+ }
+
+ // UDP IPv4
+
+ if ((PySequence_Contains(py_af_filter, _AF_INET) == 1) &&
+ (PySequence_Contains(py_type_filter, _SOCK_DGRAM) == 1))
+ {
+ table = NULL;
+ py_conn_tuple = NULL;
+ py_addr_tuple_local = NULL;
+ py_addr_tuple_remote = NULL;
+ tableSize = 0;
+ error = __GetExtendedUdpTable(psutil_GetExtendedUdpTable,
+ AF_INET, &table, &tableSize);
+ if (error != 0)
+ goto error;
+ udp4Table = table;
+ for (i = 0; i < udp4Table->dwNumEntries; i++)
+ {
+ if (pid != -1) {
+ 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;
+ psutil_rtlIpv4AddressToStringA(&addr, addressBufferLocal);
+ py_addr_tuple_local = Py_BuildValue(
+ "(si)",
+ addressBufferLocal,
+ BYTESWAP_USHORT(udp4Table->table[i].dwLocalPort));
+ }
+ else {
+ py_addr_tuple_local = PyTuple_New(0);
+ }
+
+ if (py_addr_tuple_local == NULL)
+ goto error;
+
+ py_conn_tuple = Py_BuildValue(
+ "(iiiNNiI)",
+ -1,
+ AF_INET,
+ SOCK_DGRAM,
+ py_addr_tuple_local,
+ PyTuple_New(0),
+ PSUTIL_CONN_NONE,
+ udp4Table->table[i].dwOwningPid);
+ if (!py_conn_tuple)
+ goto error;
+ if (PyList_Append(py_retlist, py_conn_tuple))
+ goto error;
+ Py_CLEAR(py_conn_tuple);
+ }
+
+ free(table);
+ table = NULL;
+ tableSize = 0;
+ }
+
+ // UDP IPv6
+
+ if ((PySequence_Contains(py_af_filter, _AF_INET6) == 1) &&
+ (PySequence_Contains(py_type_filter, _SOCK_DGRAM) == 1) &&
+ (psutil_rtlIpv6AddressToStringA != NULL))
+ {
+ table = NULL;
+ py_conn_tuple = NULL;
+ py_addr_tuple_local = NULL;
+ py_addr_tuple_remote = NULL;
+ tableSize = 0;
+ error = __GetExtendedUdpTable(psutil_GetExtendedUdpTable,
+ AF_INET6, &table, &tableSize);
+ if (error != 0)
+ goto error;
+ udp6Table = table;
+ for (i = 0; i < udp6Table->dwNumEntries; i++) {
+ if (pid != -1) {
+ 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);
+ psutil_rtlIpv6AddressToStringA(&addr, addressBufferLocal);
+ py_addr_tuple_local = Py_BuildValue(
+ "(si)",
+ addressBufferLocal,
+ BYTESWAP_USHORT(udp6Table->table[i].dwLocalPort));
+ }
+ else {
+ py_addr_tuple_local = PyTuple_New(0);
+ }
+
+ if (py_addr_tuple_local == NULL)
+ goto error;
+
+ py_conn_tuple = Py_BuildValue(
+ "(iiiNNiI)",
+ -1,
+ AF_INET6,
+ SOCK_DGRAM,
+ py_addr_tuple_local,
+ PyTuple_New(0),
+ PSUTIL_CONN_NONE,
+ udp6Table->table[i].dwOwningPid);
+ if (!py_conn_tuple)
+ goto error;
+ if (PyList_Append(py_retlist, py_conn_tuple))
+ goto error;
+ Py_CLEAR(py_conn_tuple);
+ }
+
+ free(table);
+ table = NULL;
+ tableSize = 0;
+ }
+
+ psutil_conn_decref_objs();
+ return py_retlist;
+
+error:
+ psutil_conn_decref_objs();
+ Py_XDECREF(py_conn_tuple);
+ Py_XDECREF(py_addr_tuple_local);
+ Py_XDECREF(py_addr_tuple_remote);
+ Py_DECREF(py_retlist);
+ if (table != NULL)
+ free(table);
+ return NULL;
+}
diff --git a/psutil/arch/windows/socks.h b/psutil/arch/windows/socks.h
new file mode 100644
index 00000000..cd9ba58d
--- /dev/null
+++ b/psutil/arch/windows/socks.h
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2009, Giampaolo Rodola', Jeff Tang. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <Python.h>
+
+PyObject *psutil_net_connections(PyObject *self, PyObject *args);
diff --git a/scripts/internal/winmake.py b/scripts/internal/winmake.py
index 116809ca..c471ad0b 100755
--- a/scripts/internal/winmake.py
+++ b/scripts/internal/winmake.py
@@ -12,6 +12,8 @@ that they should be deemed illegal!
"""
from __future__ import print_function
+import atexit
+import ctypes
import errno
import fnmatch
import functools
@@ -59,6 +61,12 @@ _cmds = {}
if PY3:
basestring = str
+GREEN = 2
+YELLOW = 6
+RED = 4
+DEFAULT_COLOR = 7
+
+
# ===================================================================
# utils
# ===================================================================
@@ -84,6 +92,26 @@ def safe_print(text, file=sys.stdout, flush=False):
file.write("\n")
+def stderr_handle():
+ GetStdHandle = ctypes.windll.Kernel32.GetStdHandle
+ STD_ERROR_HANDLE_ID = ctypes.c_ulong(0xfffffff4)
+ GetStdHandle.restype = ctypes.c_ulong
+ handle = GetStdHandle(STD_ERROR_HANDLE_ID)
+ atexit.register(ctypes.windll.Kernel32.CloseHandle, handle)
+ return handle
+
+
+def win_colorprint(s, color=3):
+ color += 8 # bold
+ handle = stderr_handle()
+ SetConsoleTextAttribute = ctypes.windll.Kernel32.SetConsoleTextAttribute
+ SetConsoleTextAttribute(handle, color)
+ try:
+ print(s)
+ finally:
+ SetConsoleTextAttribute(handle, DEFAULT_COLOR)
+
+
def sh(cmd, nolog=False):
if not nolog:
safe_print("cmd: " + cmd)
@@ -211,13 +239,37 @@ def build():
# Make sure setuptools is installed (needed for 'develop' /
# edit mode).
sh('%s -c "import setuptools"' % PYTHON)
- sh("%s setup.py build" % PYTHON)
+
+ # Print coloured warnings in real time.
+ cmd = [PYTHON, "setup.py", "build"]
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ try:
+ for line in iter(p.stdout.readline, b''):
+ if PY3:
+ line = line.decode()
+ line = line.strip()
+ if 'warning' in line:
+ win_colorprint(line, YELLOW)
+ elif 'error' in line:
+ win_colorprint(line, RED)
+ else:
+ print(line)
+ # retcode = p.poll()
+ p.communicate()
+ if p.returncode:
+ win_colorprint("failure", RED)
+ sys.exit(p.returncode)
+ finally:
+ p.terminate()
+ p.wait()
+
# Copies compiled *.pyd files in ./psutil directory in order to
# allow "import psutil" when using the interactive interpreter
# from within this directory.
sh("%s setup.py build_ext -i" % PYTHON)
# Make sure it actually worked.
sh('%s -c "import psutil"' % PYTHON)
+ win_colorprint("success", GREEN)
@cmd
diff --git a/setup.py b/setup.py
index a482e427..1ebad30a 100755
--- a/setup.py
+++ b/setup.py
@@ -142,12 +142,14 @@ if WINDOWS:
'psutil._psutil_windows',
sources=sources + [
'psutil/_psutil_windows.c',
+ 'psutil/arch/windows/process_utils.c',
'psutil/arch/windows/process_info.c',
'psutil/arch/windows/process_handles.c',
'psutil/arch/windows/security.c',
'psutil/arch/windows/inet_ntop.c',
'psutil/arch/windows/services.c',
'psutil/arch/windows/global.c',
+ 'psutil/arch/windows/socks.c',
'psutil/arch/windows/wmi.c',
],
define_macros=macros,
@@ -406,8 +408,8 @@ def main():
else:
ur = "http://www.microsoft.com/en-us/download/"
ur += "details.aspx?id=44266"
- print(hilite("VisualStudio is not installed; get it from %s" % ur),
- ok=False, file=sys.stderr)
+ s = "VisualStudio is not installed; get it from %s" % ur
+ print(hilite(s, ok=False), file=sys.stderr)
if __name__ == '__main__':