blob: 3e0f7a7cdc8e08d3d6cdbb7d7fb6ef2948b2ef7f [file] [log] [blame]
/*
* 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.
*
* Windows platform-specific module methods for _psutil_windows
*/
// Fixes clash between winsock2.h and windows.h
#define WIN32_LEAN_AND_MEAN
#include <Python.h>
#include <windows.h>
#include <Psapi.h>
#include <time.h>
#include <lm.h>
#include <WinIoCtl.h>
#include <tchar.h>
#include <tlhelp32.h>
#include <winsock2.h>
#include <iphlpapi.h>
#include <wtsapi32.h>
#include <ws2tcpip.h>
// Link with Iphlpapi.lib
#pragma comment(lib, "IPHLPAPI.lib")
#include "_psutil_windows.h"
#include "_psutil_common.h"
#include "arch/windows/security.h"
#include "arch/windows/process_info.h"
#include "arch/windows/process_handles.h"
#include "arch/windows/ntextapi.h"
#include "arch/windows/inet_ntop.h"
#ifdef __MINGW32__
#include "arch/windows/glpi.h"
#endif
/*
* ============================================================================
* Utilities
* ============================================================================
*/
// a flag for connections without an actual status
static int PSUTIL_CONN_NONE = 128;
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
#define LO_T ((float)1e-7)
#define HI_T (LO_T*4294967296.0)
#define BYTESWAP_USHORT(x) ((((USHORT)(x) << 8) | ((USHORT)(x) >> 8)) & 0xffff)
#ifndef AF_INET6
#define AF_INET6 23
#endif
#define _psutil_conn_decref_objs() \
Py_DECREF(_AF_INET); \
Py_DECREF(_AF_INET6);\
Py_DECREF(_SOCK_STREAM);\
Py_DECREF(_SOCK_DGRAM);
typedef BOOL (WINAPI *LPFN_GLPI)
(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
// fix for mingw32, see
// https://github.com/giampaolo/psutil/issues/351#c2
typedef struct _DISK_PERFORMANCE_WIN_2008 {
LARGE_INTEGER BytesRead;
LARGE_INTEGER BytesWritten;
LARGE_INTEGER ReadTime;
LARGE_INTEGER WriteTime;
LARGE_INTEGER IdleTime;
DWORD ReadCount;
DWORD WriteCount;
DWORD QueueDepth;
DWORD SplitCount;
LARGE_INTEGER QueryTime;
DWORD StorageDeviceNumber;
WCHAR StorageManagerName[8];
} DISK_PERFORMANCE_WIN_2008;
// --- network connections mingw32 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
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;
PIP_ADAPTER_ADDRESSES
psutil_get_nic_addresses() {
// allocate a 15 KB buffer to start with
int outBufLen = 15000;
DWORD dwRetVal = 0;
ULONG attempts = 0;
PIP_ADAPTER_ADDRESSES pAddresses = NULL;
do {
pAddresses = (IP_ADAPTER_ADDRESSES *) malloc(outBufLen);
if (pAddresses == NULL) {
PyErr_NoMemory();
return NULL;
}
dwRetVal = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, pAddresses,
&outBufLen);
if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
free(pAddresses);
pAddresses = NULL;
}
else {
break;
}
attempts++;
} while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (attempts < 3));
if (dwRetVal != NO_ERROR) {
PyErr_SetString(PyExc_RuntimeError, "GetAdaptersAddresses() failed.");
return NULL;
}
return pAddresses;
}
/*
* ============================================================================
* Public Python API
* ============================================================================
*/
/*
* Return a Python float representing the system uptime expressed in seconds
* since the epoch.
*/
static PyObject *
psutil_boot_time(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 *
psutil_pid_exists(PyObject *self, PyObject *args)
{
long pid;
int status;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
status = psutil_pid_is_running(pid);
if (-1 == status)
return NULL; // exception raised in psutil_pid_is_running()
return PyBool_FromLong(status);
}
/*
* Return a Python list of all the PIDs running on the system.
*/
static PyObject *
psutil_pids(PyObject *self, PyObject *args)
{
DWORD *proclist = NULL;
DWORD numberOfReturnedPIDs;
DWORD i;
PyObject *pid = NULL;
PyObject *retlist = PyList_New(0);
if (retlist == NULL)
return NULL;
proclist = psutil_get_pids(&numberOfReturnedPIDs);
if (proclist == NULL)
goto error;
for (i = 0; i < numberOfReturnedPIDs; i++) {
pid = Py_BuildValue("I", proclist[i]);
if (!pid)
goto error;
if (PyList_Append(retlist, pid))
goto error;
Py_DECREF(pid);
}
// free C array allocated for PIDs
free(proclist);
return retlist;
error:
Py_XDECREF(pid);
Py_DECREF(retlist);
if (proclist != NULL)
free(proclist);
return NULL;
}
/*
* Kill a process given its PID.
*/
static PyObject *
psutil_proc_kill(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 https://github.com/giampaolo/psutil/issues/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_RETURN_NONE;
}
/*
* Wait for process to terminate and return its exit code.
*/
static PyObject *
psutil_proc_wait(PyObject *self, PyObject *args)
{
HANDLE hProcess;
DWORD ExitCode;
DWORD retVal;
long pid;
long timeout;
if (! PyArg_ParseTuple(args, "ll", &pid, &timeout))
return NULL;
if (pid == 0)
return AccessDenied();
hProcess = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,
FALSE, pid);
if (hProcess == NULL) {
if (GetLastError() == ERROR_INVALID_PARAMETER) {
// no such process; we do not want to raise NSP but
// return None instead.
Py_RETURN_NONE;
}
else {
PyErr_SetFromWindowsErr(0);
return NULL;
}
}
// wait until the process has terminated
Py_BEGIN_ALLOW_THREADS
retVal = WaitForSingleObject(hProcess, timeout);
Py_END_ALLOW_THREADS
if (retVal == WAIT_FAILED) {
CloseHandle(hProcess);
return PyErr_SetFromWindowsErr(GetLastError());
}
if (retVal == WAIT_TIMEOUT) {
CloseHandle(hProcess);
return Py_BuildValue("l", WAIT_TIMEOUT);
}
// get the exit code; note: subprocess module (erroneously?) uses
// what returned by WaitForSingleObject
if (GetExitCodeProcess(hProcess, &ExitCode) == 0) {
CloseHandle(hProcess);
return PyErr_SetFromWindowsErr(GetLastError());
}
CloseHandle(hProcess);
#if PY_MAJOR_VERSION >= 3
return PyLong_FromLong((long) ExitCode);
#else
return PyInt_FromLong((long) ExitCode);
#endif
}
/*
* Return a Python tuple (user_time, kernel_time)
*/
static PyObject *
psutil_proc_cpu_times(PyObject *self, PyObject *args)
{
long pid;
HANDLE hProcess;
FILETIME ftCreate, ftExit, ftKernel, ftUser;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
hProcess = psutil_handle_from_pid(pid);
if (hProcess == NULL)
return NULL;
if (! GetProcessTimes(hProcess, &ftCreate, &ftExit, &ftKernel, &ftUser)) {
CloseHandle(hProcess);
if (GetLastError() == ERROR_ACCESS_DENIED) {
// usually means the process has died so we throw a NoSuchProcess
// here
return NoSuchProcess();
}
else {
PyErr_SetFromWindowsErr(0);
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 *
psutil_proc_create_time(PyObject *self, PyObject *args)
{
long pid;
long long unix_time;
DWORD exitCode;
HANDLE hProcess;
BOOL ret;
FILETIME ftCreate, ftExit, ftKernel, ftUser;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
// special case for PIDs 0 and 4, return system boot time
if (0 == pid || 4 == pid)
return psutil_boot_time(NULL, NULL);
hProcess = psutil_handle_from_pid(pid);
if (hProcess == NULL)
return NULL;
if (! GetProcessTimes(hProcess, &ftCreate, &ftExit, &ftKernel, &ftUser)) {
CloseHandle(hProcess);
if (GetLastError() == ERROR_ACCESS_DENIED) {
// usually means the process has died so we throw a
// NoSuchProcess here
return NoSuchProcess();
}
else {
PyErr_SetFromWindowsErr(0);
return NULL;
}
}
// Make sure the process is not gone as OpenProcess alone seems to be
// unreliable in doing so (it seems a previous call to p.wait() makes
// it unreliable).
// This check is important as creation time is used to make sure the
// process is still running.
ret = GetExitCodeProcess(hProcess, &exitCode);
CloseHandle(hProcess);
if (ret != 0) {
if (exitCode != STILL_ACTIVE)
return NoSuchProcess();
}
else {
// Ignore access denied as it means the process is still alive.
// For all other errors, we want an exception.
if (GetLastError() != ERROR_ACCESS_DENIED) {
PyErr_SetFromWindowsErr(0);
return NULL;
}
}
/*
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 the number of logical CPUs.
*/
static PyObject *
psutil_cpu_count_logical(PyObject *self, PyObject *args)
{
SYSTEM_INFO system_info;
system_info.dwNumberOfProcessors = 0;
GetSystemInfo(&system_info);
if (system_info.dwNumberOfProcessors == 0)
Py_RETURN_NONE; // mimic os.cpu_count()
else
return Py_BuildValue("I", system_info.dwNumberOfProcessors);
}
/*
* Return the number of physical CPU cores.
*/
static PyObject *
psutil_cpu_count_phys(PyObject *self, PyObject *args)
{
LPFN_GLPI glpi;
DWORD rc;
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL;
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL;
DWORD length = 0;
DWORD offset = 0;
int ncpus = 0;
glpi = (LPFN_GLPI)GetProcAddress(GetModuleHandle(TEXT("kernel32")),
"GetLogicalProcessorInformation");
if (glpi == NULL)
goto return_none;
while (1) {
rc = glpi(buffer, &length);
if (rc == FALSE) {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
if (buffer)
free(buffer);
buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(
length);
if (NULL == buffer) {
PyErr_NoMemory();
return NULL;
}
}
else {
goto return_none;
}
}
else {
break;
}
}
ptr = buffer;
while (offset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= length) {
if (ptr->Relationship == RelationProcessorCore)
ncpus += 1;
offset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
ptr++;
}
free(buffer);
if (ncpus == 0)
goto return_none;
else
return Py_BuildValue("i", ncpus);
return_none:
// mimic os.cpu_count()
if (buffer != NULL)
free(buffer);
Py_RETURN_NONE;
}
/*
* Return process cmdline as a Python list of cmdline arguments.
*/
static PyObject *
psutil_proc_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 = psutil_pid_is_running(pid);
if (pid_return == 0)
return NoSuchProcess();
if (pid_return == -1)
return NULL;
// XXX the assumptio below probably needs to go away
// 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 = psutil_get_arg_list(pid);
if ( NULL == arglist ) {
// carry on anyway, clear any exceptions too
PyErr_Clear();
return Py_BuildValue("[]");
}
return arglist;
}
/*
* Return process executable path.
*/
static PyObject *
psutil_proc_exe(PyObject *self, PyObject *args) {
long pid;
HANDLE hProcess;
wchar_t exe[MAX_PATH];
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
hProcess = psutil_handle_from_pid_waccess(pid, PROCESS_QUERY_INFORMATION);
if (NULL == hProcess)
return NULL;
if (GetProcessImageFileNameW(hProcess, exe, MAX_PATH) == 0) {
CloseHandle(hProcess);
PyErr_SetFromWindowsErr(0);
return NULL;
}
CloseHandle(hProcess);
return Py_BuildValue("u", exe);
}
/*
* Return process base name.
* Note: psutil_proc_exe() is attempted first because it's faster
* but it raise AccessDenied for processes owned by other users
* in which case we fall back on using this.
*/
static PyObject *
psutil_proc_name(PyObject *self, PyObject *args) {
long pid;
int ok;
PROCESSENTRY32 pentry;
HANDLE hSnapShot;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, pid);
if (hSnapShot == INVALID_HANDLE_VALUE) {
PyErr_SetFromWindowsErr(0);
return NULL;
}
pentry.dwSize = sizeof(PROCESSENTRY32);
ok = Process32First(hSnapShot, &pentry);
if (! ok) {
CloseHandle(hSnapShot);
PyErr_SetFromWindowsErr(0);
return NULL;
}
while (ok) {
if (pentry.th32ProcessID == pid) {
CloseHandle(hSnapShot);
return Py_BuildValue("s", pentry.szExeFile);
}
ok = Process32Next(hSnapShot, &pentry);
}
CloseHandle(hSnapShot);
NoSuchProcess();
return NULL;
}
/*
* Return process memory information as a Python tuple.
*/
static PyObject *
psutil_proc_memory_info(PyObject *self, PyObject *args)
{
HANDLE hProcess;
DWORD pid;
#if (_WIN32_WINNT >= 0x0501) // Windows XP with SP2
PROCESS_MEMORY_COUNTERS_EX cnt;
#else
PROCESS_MEMORY_COUNTERS cnt;
#endif
SIZE_T private = 0;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
hProcess = psutil_handle_from_pid(pid);
if (NULL == hProcess)
return NULL;
if (! GetProcessMemoryInfo(hProcess, (PPROCESS_MEMORY_COUNTERS)&cnt,
sizeof(cnt))) {
CloseHandle(hProcess);
return PyErr_SetFromWindowsErr(0);
}
#if (_WIN32_WINNT >= 0x0501) // Windows XP with SP2
private = cnt.PrivateUsage;
#endif
CloseHandle(hProcess);
// PROCESS_MEMORY_COUNTERS values are defined as SIZE_T which on 64bits
// is an (unsigned long long) and on 32bits is an (unsigned int).
// "_WIN64" is defined if we're running a 64bit Python interpreter not
// exclusively if the *system* is 64bit.
#if defined(_WIN64)
return Py_BuildValue(
"(kKKKKKKKKK)",
cnt.PageFaultCount, // unsigned long
(unsigned long long)cnt.PeakWorkingSetSize,
(unsigned long long)cnt.WorkingSetSize,
(unsigned long long)cnt.QuotaPeakPagedPoolUsage,
(unsigned long long)cnt.QuotaPagedPoolUsage,
(unsigned long long)cnt.QuotaPeakNonPagedPoolUsage,
(unsigned long long)cnt.QuotaNonPagedPoolUsage,
(unsigned long long)cnt.PagefileUsage,
(unsigned long long)cnt.PeakPagefileUsage,
(unsigned long long)private);
#else
return Py_BuildValue(
"(kIIIIIIIII)",
cnt.PageFaultCount, // unsigned long
(unsigned int)cnt.PeakWorkingSetSize,
(unsigned int)cnt.WorkingSetSize,
(unsigned int)cnt.QuotaPeakPagedPoolUsage,
(unsigned int)cnt.QuotaPagedPoolUsage,
(unsigned int)cnt.QuotaPeakNonPagedPoolUsage,
(unsigned int)cnt.QuotaNonPagedPoolUsage,
(unsigned int)cnt.PagefileUsage,
(unsigned int)cnt.PeakPagefileUsage,
(unsigned int)private);
#endif
}
/*
* Alternative implementation of the one above but bypasses ACCESS DENIED.
*/
static PyObject *
psutil_proc_memory_info_2(PyObject *self, PyObject *args)
{
DWORD pid;
PSYSTEM_PROCESS_INFORMATION process;
PVOID buffer;
SIZE_T private;
unsigned long pfault_count;
#if defined(_WIN64)
unsigned long long m1, m2, m3, m4, m5, m6, m7, m8;
#else
unsigned int m1, m2, m3, m4, m5, m6, m7, m8;
#endif
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
if (! psutil_get_proc_info(pid, &process, &buffer))
return NULL;
#if (_WIN32_WINNT >= 0x0501) // Windows XP with SP2
private = process->PrivatePageCount;
#else
private = 0;
#endif
pfault_count = process->PageFaultCount;
m1 = process->PeakWorkingSetSize;
m2 = process->WorkingSetSize;
m3 = process->QuotaPeakPagedPoolUsage;
m4 = process->QuotaPagedPoolUsage;
m5 = process->QuotaPeakNonPagedPoolUsage;
m6 = process->QuotaNonPagedPoolUsage;
m7 = process->PagefileUsage;
m8 = process->PeakPagefileUsage;
free(buffer);
// SYSTEM_PROCESS_INFORMATION values are defined as SIZE_T which on 64
// bits is an (unsigned long long) and on 32bits is an (unsigned int).
// "_WIN64" is defined if we're running a 64bit Python interpreter not
// exclusively if the *system* is 64bit.
#if defined(_WIN64)
return Py_BuildValue("(kKKKKKKKKK)",
#else
return Py_BuildValue("(kIIIIIIIII)",
#endif
pfault_count, m1, m2, m3, m4, m5, m6, m7, m8, private);
}
/*
* Return a Python integer indicating the total amount of physical memory
* in bytes.
*/
static PyObject *
psutil_virtual_mem(PyObject *self, PyObject *args)
{
MEMORYSTATUSEX memInfo;
memInfo.dwLength = sizeof(MEMORYSTATUSEX);
if (! GlobalMemoryStatusEx(&memInfo))
return PyErr_SetFromWindowsErr(0);
return Py_BuildValue("(LLLLLL)",
memInfo.ullTotalPhys, // total
memInfo.ullAvailPhys, // avail
memInfo.ullTotalPageFile, // total page file
memInfo.ullAvailPageFile, // avail page file
memInfo.ullTotalVirtual, // total virtual
memInfo.ullAvailVirtual); // avail virtual
}
/*
* Retrieves system CPU timing information as a (user, system, idle)
* tuple. On a multiprocessor system, the values returned are the
* sum of the designated times across all processors.
*/
static PyObject *
psutil_cpu_times(PyObject *self, PyObject *args)
{
float idle, kernel, user, system;
FILETIME idle_time, kernel_time, 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.
// We return only busy kernel time subtracting idle time from
// kernel time.
system = (kernel - idle);
return Py_BuildValue("(fff)", user, system, idle);
}
/*
* Same as above but for all system CPUs.
*/
static PyObject *
psutil_per_cpu_times(PyObject *self, PyObject *args)
{
float idle, kernel, user;
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;
PyObject *arg = NULL;
PyObject *retlist = PyList_New(0);
if (retlist == NULL)
return NULL;
// 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++) {
arg = NULL;
user = (float)((HI_T * sppi[i].UserTime.HighPart) +
(LO_T * sppi[i].UserTime.LowPart));
idle = (float)((HI_T * sppi[i].IdleTime.HighPart) +
(LO_T * sppi[i].IdleTime.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
arg = Py_BuildValue("(ddd)",
user,
kernel - idle,
idle);
if (!arg)
goto error;
if (PyList_Append(retlist, arg))
goto error;
Py_DECREF(arg);
}
free(sppi);
FreeLibrary(hNtDll);
return retlist;
} // END NtQuerySystemInformation
} // END malloc SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
} // END GetProcAddress
} // END LoadLibrary
goto error;
error:
Py_XDECREF(arg);
Py_DECREF(retlist);
if (sppi)
free(sppi);
if (hNtDll)
FreeLibrary(hNtDll);
PyErr_SetFromWindowsErr(0);
return NULL;
}
/*
* Return process current working directory as a Python string.
*/
static PyObject *
psutil_proc_cwd(PyObject *self, PyObject *args)
{
long pid;
HANDLE processHandle = NULL;
PVOID pebAddress;
PVOID rtlUserProcParamsAddress;
UNICODE_STRING currentDirectory;
WCHAR *currentDirectoryContent = NULL;
PyObject *returnPyObj = NULL;
PyObject *cwd_from_wchar = NULL;
PyObject *cwd = NULL;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
processHandle = psutil_handle_from_pid(pid);
if (processHandle == NULL)
return NULL;
pebAddress = psutil_get_peb_address(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) {
// this occurs quite often with system processes
return AccessDenied();
}
else {
return PyErr_SetFromWindowsErr(0);
}
}
// Read the currentDirectory UNICODE_STRING structure.
// 0x24 refers to "CurrentDirectoryPath" of RTL_USER_PROCESS_PARAMETERS
// structure, see:
// 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) {
// this occurs quite often with system processes
return AccessDenied();
}
else {
return PyErr_SetFromWindowsErr(0);
}
}
// allocate memory to hold cwd
currentDirectoryContent = (WCHAR *)malloc(currentDirectory.Length + 1);
if (currentDirectoryContent == NULL) {
PyErr_NoMemory();
goto error;
}
// read cwd
if (!ReadProcessMemory(processHandle, currentDirectory.Buffer,
currentDirectoryContent, currentDirectory.Length,
NULL))
{
if (GetLastError() == ERROR_PARTIAL_COPY) {
// this occurs quite often with system processes
AccessDenied();
}
else {
PyErr_SetFromWindowsErr(0);
}
goto error;
}
// null-terminate the string to prevent wcslen from returning
// incorrect length the length specifier is in characters, but
// currentDirectory.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 (cwd_from_wchar == NULL)
goto error;
#if PY_MAJOR_VERSION >= 3
cwd = PyUnicode_FromObject(cwd_from_wchar);
#else
cwd = PyUnicode_AsUTF8String(cwd_from_wchar);
#endif
if (cwd == NULL)
goto error;
// decrement the reference count on our temp unicode str to avoid
// mem leak
returnPyObj = Py_BuildValue("N", cwd);
if (!returnPyObj)
goto error;
Py_DECREF(cwd_from_wchar);
CloseHandle(processHandle);
free(currentDirectoryContent);
return returnPyObj;
error:
Py_XDECREF(cwd_from_wchar);
Py_XDECREF(cwd);
Py_XDECREF(returnPyObj);
if (currentDirectoryContent != NULL)
free(currentDirectoryContent);
if (processHandle != NULL)
CloseHandle(processHandle);
return NULL;
}
/*
* Resume or suspends a process
*/
int
psutil_proc_suspend_or_resume(DWORD pid, int suspend)
{
// a huge thanks to http://www.codeproject.com/KB/threads/pausep.aspx
HANDLE hThreadSnap = NULL;
THREADENTRY32 te32 = {0};
if (pid == 0) {
AccessDenied();
return FALSE;
}
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));
CloseHandle(hThreadSnap);
return TRUE;
}
static PyObject *
psutil_proc_suspend(PyObject *self, PyObject *args)
{
long pid;
int suspend = 1;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
if (! psutil_proc_suspend_or_resume(pid, suspend))
return NULL;
Py_RETURN_NONE;
}
static PyObject *
psutil_proc_resume(PyObject *self, PyObject *args)
{
long pid;
int suspend = 0;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
if (! psutil_proc_suspend_or_resume(pid, suspend))
return NULL;
Py_RETURN_NONE;
}
static PyObject *
psutil_proc_threads(PyObject *self, PyObject *args)
{
HANDLE hThread;
THREADENTRY32 te32 = {0};
long pid;
int pid_return;
int rc;
FILETIME ftDummy, ftKernel, ftUser;
PyObject *retList = PyList_New(0);
PyObject *pyTuple = NULL;
HANDLE hThreadSnap = NULL;
if (retList == NULL)
return NULL;
if (! PyArg_ParseTuple(args, "l", &pid))
goto error;
if (pid == 0) {
// raise AD instead of returning 0 as procexp is able to
// retrieve useful information somehow
AccessDenied();
goto error;
}
pid_return = psutil_pid_is_running(pid);
if (pid_return == 0) {
NoSuchProcess();
goto error;
}
if (pid_return == -1)
goto error;
hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hThreadSnap == INVALID_HANDLE_VALUE) {
PyErr_SetFromWindowsErr(0);
goto error;
}
// Fill in the size of the structure before using it
te32.dwSize = sizeof(THREADENTRY32);
if (! Thread32First(hThreadSnap, &te32)) {
PyErr_SetFromWindowsErr(0);
goto error;
}
// 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) {
pyTuple = NULL;
hThread = NULL;
hThread = OpenThread(THREAD_QUERY_INFORMATION,
FALSE, te32.th32ThreadID);
if (hThread == NULL) {
// thread has disappeared on us
continue;
}
rc = GetThreadTimes(hThread, &ftDummy, &ftDummy, &ftKernel,
&ftUser);
if (rc == 0) {
PyErr_SetFromWindowsErr(0);
goto error;
}
/*
* 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
*/
pyTuple = Py_BuildValue(
"kdd",
te32.th32ThreadID,
(double)(ftUser.dwHighDateTime * 429.4967296 + \
ftUser.dwLowDateTime * 1e-7),
(double)(ftKernel.dwHighDateTime * 429.4967296 + \
ftKernel.dwLowDateTime * 1e-7));
if (!pyTuple)
goto error;
if (PyList_Append(retList, pyTuple))
goto error;
Py_DECREF(pyTuple);
CloseHandle(hThread);
}
} while (Thread32Next(hThreadSnap, &te32));
CloseHandle(hThreadSnap);
return retList;
error:
Py_XDECREF(pyTuple);
Py_DECREF(retList);
if (hThread != NULL)
CloseHandle(hThread);
if (hThreadSnap != NULL)
CloseHandle(hThreadSnap);
return NULL;
}
static PyObject *
psutil_proc_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 = psutil_handle_from_pid_waccess(pid, access);
if (processHandle == NULL)
return NULL;
filesList = psutil_get_open_files(pid, processHandle);
CloseHandle(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 *
psutil_win32_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) {
if (_tcscmp(lpDevicePath, szTarget) == 0) {
_stprintf_s(szBuff, _countof(szBuff), TEXT("%c:"), d);
return Py_BuildValue("s", szBuff);
}
}
d++;
}
return Py_BuildValue("s", "");
}
/*
* Return process username as a "DOMAIN//USERNAME" string.
*/
static PyObject *
psutil_proc_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 = psutil_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 (user == NULL)
return PyErr_NoMemory();
if (!GetTokenInformation(tokenHandle, TokenUser, user, bufferSize,
&bufferSize))
{
free(user);
user = malloc(bufferSize);
if (user == NULL) {
CloseHandle(tokenHandle);
return PyErr_NoMemory();
}
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));
if (name == NULL)
return PyErr_NoMemory();
domainName = malloc(domainNameSize * sizeof(TCHAR));
if (domainName == NULL)
return PyErr_NoMemory();
if (!LookupAccountSid(NULL, user->User.Sid, name, &nameSize, domainName,
&domainNameSize, &nameUse))
{
free(name);
free(domainName);
name = malloc(nameSize * sizeof(TCHAR));
if (name == NULL)
return PyErr_NoMemory();
domainName = malloc(domainNameSize * sizeof(TCHAR));
if (domainName == NULL)
return PyErr_NoMemory();
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));
if (fullName == NULL) {
free(name);
free(domainName);
free(user);
return PyErr_NoMemory();
}
memcpy(fullName, domainName, domainNameSize);
fullName[domainNameSize] = '\\';
memcpy(&fullName[domainNameSize + 1], name, nameSize);
fullName[domainNameSize + 1 + nameSize] = '\0';
returnObject = PyUnicode_Decode(
fullName, _tcslen(fullName), Py_FileSystemDefaultEncoding, "replace");
free(fullName);
free(name);
free(domainName);
free(user);
return returnObject;
}
/*
* 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;
PyObject *connectionsList;
PyObject *connectionTuple = NULL;
PyObject *af_filter = NULL;
PyObject *type_filter = 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);
typedef PSTR (NTAPI * _RtlIpv4AddressToStringA)(struct in_addr *, PSTR);
_RtlIpv4AddressToStringA rtlIpv4AddressToStringA;
typedef PSTR (NTAPI * _RtlIpv6AddressToStringA)(struct in6_addr *, PSTR);
_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 = NULL;
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 = NULL;
CHAR addressBufferRemote[65];
PyObject *addressTupleRemote = NULL;
if (! PyArg_ParseTuple(args, "lOO", &pid, &af_filter, &type_filter)) {
_psutil_conn_decref_objs();
return NULL;
}
if (!PySequence_Check(af_filter) || !PySequence_Check(type_filter)) {
_psutil_conn_decref_objs();
PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence");
return NULL;
}
if (pid != -1) {
if (psutil_pid_is_running(pid) == 0) {
_psutil_conn_decref_objs();
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");
FreeLibrary(ntdll);
FreeLibrary(iphlpapi);
}
if ((getExtendedTcpTable == NULL) || (getExtendedUdpTable == NULL)) {
PyErr_SetString(PyExc_NotImplementedError,
"feature not supported on this Windows version");
_psutil_conn_decref_objs();
return NULL;
}
connectionsList = PyList_New(0);
if (connectionsList == NULL) {
_psutil_conn_decref_objs();
return NULL;
}
// TCP IPv4
if ((PySequence_Contains(af_filter, _AF_INET) == 1) &&
(PySequence_Contains(type_filter, _SOCK_STREAM) == 1))
{
table = NULL;
connectionTuple = NULL;
addressTupleLocal = NULL;
addressTupleRemote = NULL;
tableSize = 0;
getExtendedTcpTable(NULL, &tableSize, FALSE, AF_INET,
TCP_TABLE_OWNER_PID_ALL, 0);
table = malloc(tableSize);
if (table == NULL) {
PyErr_NoMemory();
goto error;
}
if (getExtendedTcpTable(table, &tableSize, FALSE, AF_INET,
TCP_TABLE_OWNER_PID_ALL, 0) == 0)
{
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;
rtlIpv4AddressToStringA(&addr, addressBufferLocal);
addressTupleLocal = Py_BuildValue(
"(si)",
addressBufferLocal,
BYTESWAP_USHORT(tcp4Table->table[i].dwLocalPort));
}
else {
addressTupleLocal = PyTuple_New(0);
}
if (addressTupleLocal == 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;
rtlIpv4AddressToStringA(&addr, addressBufferRemote);
addressTupleRemote = Py_BuildValue(
"(si)",
addressBufferRemote,
BYTESWAP_USHORT(tcp4Table->table[i].dwRemotePort));
}
else
{
addressTupleRemote = PyTuple_New(0);
}
if (addressTupleRemote == NULL)
goto error;
connectionTuple = Py_BuildValue(
"(iiiNNiI)",
-1,
AF_INET,
SOCK_STREAM,
addressTupleLocal,
addressTupleRemote,
tcp4Table->table[i].dwState,
tcp4Table->table[i].dwOwningPid);
if (!connectionTuple)
goto error;
if (PyList_Append(connectionsList, connectionTuple))
goto error;
Py_DECREF(connectionTuple);
}
}
free(table);
}
// TCP IPv6
if ((PySequence_Contains(af_filter, _AF_INET6) == 1) &&
(PySequence_Contains(type_filter, _SOCK_STREAM) == 1))
{
table = NULL;
connectionTuple = NULL;
addressTupleLocal = NULL;
addressTupleRemote = NULL;
tableSize = 0;
getExtendedTcpTable(NULL, &tableSize, FALSE, AF_INET6,
TCP_TABLE_OWNER_PID_ALL, 0);
table = malloc(tableSize);
if (table == NULL) {
PyErr_NoMemory();
goto error;
}
if (getExtendedTcpTable(table, &tableSize, FALSE, AF_INET6,
TCP_TABLE_OWNER_PID_ALL, 0) == 0)
{
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);
rtlIpv6AddressToStringA(&addr, addressBufferLocal);
addressTupleLocal = Py_BuildValue(
"(si)",
addressBufferLocal,
BYTESWAP_USHORT(tcp6Table->table[i].dwLocalPort));
}
else
{
addressTupleLocal = PyTuple_New(0);
}
if (addressTupleLocal == 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);
rtlIpv6AddressToStringA(&addr, addressBufferRemote);
addressTupleRemote = Py_BuildValue(
"(si)",
addressBufferRemote,
BYTESWAP_USHORT(tcp6Table->table[i].dwRemotePort));
}
else
{
addressTupleRemote = PyTuple_New(0);
}
if (addressTupleRemote == NULL)
goto error;
connectionTuple = Py_BuildValue(
"(iiiNNiI)",
-1,
AF_INET6,
SOCK_STREAM,
addressTupleLocal,
addressTupleRemote,
tcp6Table->table[i].dwState,
tcp6Table->table[i].dwOwningPid);
if (!connectionTuple)
goto error;
if (PyList_Append(connectionsList, connectionTuple))
goto error;
Py_DECREF(connectionTuple);
}
}
free(table);
}
// UDP IPv4
if ((PySequence_Contains(af_filter, _AF_INET) == 1) &&
(PySequence_Contains(type_filter, _SOCK_DGRAM) == 1))
{
table = NULL;
connectionTuple = NULL;
addressTupleLocal = NULL;
addressTupleRemote = NULL;
tableSize = 0;
getExtendedUdpTable(NULL, &tableSize, FALSE, AF_INET,
UDP_TABLE_OWNER_PID, 0);
table = malloc(tableSize);
if (table == NULL) {
PyErr_NoMemory();
goto error;
}
if (getExtendedUdpTable(table, &tableSize, FALSE, AF_INET,
UDP_TABLE_OWNER_PID, 0) == 0)
{
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;
rtlIpv4AddressToStringA(&addr, addressBufferLocal);
addressTupleLocal = Py_BuildValue(
"(si)",
addressBufferLocal,
BYTESWAP_USHORT(udp4Table->table[i].dwLocalPort));
}
else {
addressTupleLocal = PyTuple_New(0);
}
if (addressTupleLocal == NULL)
goto error;
connectionTuple = Py_BuildValue(
"(iiiNNiI)",
-1,
AF_INET,
SOCK_DGRAM,
addressTupleLocal,
PyTuple_New(0),
PSUTIL_CONN_NONE,
udp4Table->table[i].dwOwningPid);
if (!connectionTuple)
goto error;
if (PyList_Append(connectionsList, connectionTuple))
goto error;
Py_DECREF(connectionTuple);
}
}
free(table);
}
// UDP IPv6
if ((PySequence_Contains(af_filter, _AF_INET6) == 1) &&
(PySequence_Contains(type_filter, _SOCK_DGRAM) == 1))
{
table = NULL;
connectionTuple = NULL;
addressTupleLocal = NULL;
addressTupleRemote = NULL;
tableSize = 0;
getExtendedUdpTable(NULL, &tableSize, FALSE,
AF_INET6, UDP_TABLE_OWNER_PID, 0);
table = malloc(tableSize);
if (table == NULL) {
PyErr_NoMemory();
goto error;
}
if (getExtendedUdpTable(table, &tableSize, FALSE, AF_INET6,
UDP_TABLE_OWNER_PID, 0) == 0)
{
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);
rtlIpv6AddressToStringA(&addr, addressBufferLocal);
addressTupleLocal = Py_BuildValue(
"(si)",
addressBufferLocal,
BYTESWAP_USHORT(udp6Table->table[i].dwLocalPort));
}
else {
addressTupleLocal = PyTuple_New(0);
}
if (addressTupleLocal == NULL)
goto error;
connectionTuple = Py_BuildValue(
"(iiiNNiI)",
-1,
AF_INET6,
SOCK_DGRAM,
addressTupleLocal,
PyTuple_New(0),
PSUTIL_CONN_NONE,
udp6Table->table[i].dwOwningPid);
if (!connectionTuple)
goto error;
if (PyList_Append(connectionsList, connectionTuple))
goto error;
Py_DECREF(connectionTuple);
}
}
free(table);
}
_psutil_conn_decref_objs();
return connectionsList;
error:
_psutil_conn_decref_objs();
Py_XDECREF(connectionTuple);
Py_XDECREF(addressTupleLocal);
Py_XDECREF(addressTupleRemote);
Py_DECREF(connectionsList);
if (table != NULL)
free(table);
return NULL;
}
/*
* Get process priority as a Python integer.
*/
static PyObject *
psutil_proc_priority_get(PyObject *self, PyObject *args)
{
long pid;
DWORD priority;
HANDLE hProcess;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
hProcess = psutil_handle_from_pid(pid);
if (hProcess == NULL) {
return NULL;
}
priority = GetPriorityClass(hProcess);
CloseHandle(hProcess);
if (priority == 0) {
PyErr_SetFromWindowsErr(0);
return NULL;
}
return Py_BuildValue("i", priority);
}
/*
* Set process priority.
*/
static PyObject *
psutil_proc_priority_set(PyObject *self, PyObject *args)
{
long pid;
int priority;
int retval;
HANDLE hProcess;
DWORD dwDesiredAccess = \
PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION;
if (! PyArg_ParseTuple(args, "li", &pid, &priority)) {
return NULL;
}
hProcess = psutil_handle_from_pid_waccess(pid, dwDesiredAccess);
if (hProcess == NULL) {
return NULL;
}
retval = SetPriorityClass(hProcess, priority);
CloseHandle(hProcess);
if (retval == 0) {
PyErr_SetFromWindowsErr(0);
return NULL;
}
Py_RETURN_NONE;
}
#if (_WIN32_WINNT >= 0x0600) // Windows Vista
/*
* Get process IO priority as a Python integer.
*/
static PyObject *
psutil_proc_io_priority_get(PyObject *self, PyObject *args)
{
long pid;
HANDLE hProcess;
PULONG IoPriority;
_NtQueryInformationProcess NtQueryInformationProcess =
(_NtQueryInformationProcess)GetProcAddress(
GetModuleHandleA("ntdll.dll"), "NtQueryInformationProcess");
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
hProcess = psutil_handle_from_pid(pid);
if (hProcess == NULL) {
return NULL;
}
NtQueryInformationProcess(
hProcess,
ProcessIoPriority,
&IoPriority,
sizeof(ULONG),
NULL
);
CloseHandle(hProcess);
return Py_BuildValue("i", IoPriority);
}
/*
* Set process IO priority.
*/
static PyObject *
psutil_proc_io_priority_set(PyObject *self, PyObject *args)
{
long pid;
int prio;
HANDLE hProcess;
_NtSetInformationProcess NtSetInformationProcess =
(_NtSetInformationProcess)GetProcAddress(
GetModuleHandleA("ntdll.dll"), "NtSetInformationProcess");
if (NtSetInformationProcess == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"couldn't get NtSetInformationProcess");
return NULL;
}
if (! PyArg_ParseTuple(args, "li", &pid, &prio)) {
return NULL;
}
hProcess = psutil_handle_from_pid_waccess(pid, PROCESS_ALL_ACCESS);
if (hProcess == NULL) {
return NULL;
}
NtSetInformationProcess(
hProcess,
ProcessIoPriority,
(PVOID)&prio,
sizeof((PVOID)prio)
);
CloseHandle(hProcess);
Py_RETURN_NONE;
}
#endif
/*
* Return a Python tuple referencing process I/O counters.
*/
static PyObject *
psutil_proc_io_counters(PyObject *self, PyObject *args)
{
DWORD pid;
HANDLE hProcess;
IO_COUNTERS IoCounters;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
hProcess = psutil_handle_from_pid(pid);
if (NULL == hProcess) {
return NULL;
}
if (! GetProcessIoCounters(hProcess, &IoCounters)) {
CloseHandle(hProcess);
return PyErr_SetFromWindowsErr(0);
}
CloseHandle(hProcess);
return Py_BuildValue("(KKKK)",
IoCounters.ReadOperationCount,
IoCounters.WriteOperationCount,
IoCounters.ReadTransferCount,
IoCounters.WriteTransferCount);
}
/*
* Return process CPU affinity as a bitmask
*/
static PyObject *
psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args)
{
DWORD pid;
HANDLE hProcess;
DWORD_PTR proc_mask;
DWORD_PTR system_mask;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
hProcess = psutil_handle_from_pid(pid);
if (hProcess == NULL) {
return NULL;
}
if (GetProcessAffinityMask(hProcess, &proc_mask, &system_mask) == 0) {
CloseHandle(hProcess);
return PyErr_SetFromWindowsErr(0);
}
CloseHandle(hProcess);
#ifdef _WIN64
return Py_BuildValue("K", (unsigned long long)proc_mask);
#else
return Py_BuildValue("k", (unsigned long)proc_mask);
#endif
}
/*
* Set process CPU affinity
*/
static PyObject *
psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args)
{
DWORD pid;
HANDLE hProcess;
DWORD dwDesiredAccess = \
PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION;
DWORD_PTR mask;
#ifdef _WIN64
if (! PyArg_ParseTuple(args, "lK", &pid, &mask))
#else
if (! PyArg_ParseTuple(args, "lk", &pid, &mask))
#endif
{
return NULL;
}
hProcess = psutil_handle_from_pid_waccess(pid, dwDesiredAccess);
if (hProcess == NULL) {
return NULL;
}
if (SetProcessAffinityMask(hProcess, mask) == 0) {
CloseHandle(hProcess);
return PyErr_SetFromWindowsErr(0);
}
CloseHandle(hProcess);
Py_RETURN_NONE;
}
/*
* Return True if one of the process threads is in a waiting or
* suspended status.
*/
static PyObject *
psutil_proc_is_suspended(PyObject *self, PyObject *args)
{
DWORD pid;
ULONG i;
PSYSTEM_PROCESS_INFORMATION process;
PVOID buffer;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
if (! psutil_get_proc_info(pid, &process, &buffer)) {
return NULL;
}
for (i = 0; i < process->NumberOfThreads; i++) {
if (process->Threads[i].ThreadState != Waiting ||
process->Threads[i].WaitReason != Suspended)
{
free(buffer);
Py_RETURN_FALSE;
}
}
free(buffer);
Py_RETURN_TRUE;
}
/*
* Return path's disk total and free as a Python tuple.
*/
static PyObject *
psutil_disk_usage(PyObject *self, PyObject *args)
{
BOOL retval;
ULARGE_INTEGER _, total, free;
char *path;
if (PyArg_ParseTuple(args, "u", &path)) {
Py_BEGIN_ALLOW_THREADS
retval = GetDiskFreeSpaceExW((LPCWSTR)path, &_, &total, &free);
Py_END_ALLOW_THREADS
goto return_;
}
// on Python 2 we also want to accept plain strings other
// than Unicode
#if PY_MAJOR_VERSION <= 2
PyErr_Clear(); // drop the argument parsing error
if (PyArg_ParseTuple(args, "s", &path)) {
Py_BEGIN_ALLOW_THREADS
retval = GetDiskFreeSpaceEx(path, &_, &total, &free);
Py_END_ALLOW_THREADS
goto return_;
}
#endif
return NULL;
return_:
if (retval == 0)
return PyErr_SetFromWindowsErr(0);
else
return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
}
/*
* Return a Python list of named tuples with overall network I/O information
*/
static PyObject *
psutil_net_io_counters(PyObject *self, PyObject *args)
{
char ifname[MAX_PATH];
DWORD dwRetVal = 0;
MIB_IFROW *pIfRow = NULL;
PIP_ADAPTER_ADDRESSES pAddresses = NULL;
PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
PyObject *py_retdict = PyDict_New();
PyObject *py_nic_info = NULL;
PyObject *py_nic_name = NULL;
if (py_retdict == NULL)
return NULL;
pAddresses = psutil_get_nic_addresses();
if (pAddresses == NULL)
goto error;
pCurrAddresses = pAddresses;
while (pCurrAddresses) {
py_nic_name = NULL;
py_nic_info = NULL;
pIfRow = (MIB_IFROW *) malloc(sizeof(MIB_IFROW));
if (pIfRow == NULL) {
PyErr_NoMemory();
goto error;
}
pIfRow->dwIndex = pCurrAddresses->IfIndex;
dwRetVal = GetIfEntry(pIfRow);
if (dwRetVal != NO_ERROR) {
PyErr_SetString(PyExc_RuntimeError, "GetIfEntry() failed.");
goto error;
}
py_nic_info = Py_BuildValue("(kkkkkkkk)",
pIfRow->dwOutOctets,
pIfRow->dwInOctets,
pIfRow->dwOutUcastPkts,
pIfRow->dwInUcastPkts,
pIfRow->dwInErrors,
pIfRow->dwOutErrors,
pIfRow->dwInDiscards,
pIfRow->dwOutDiscards);
if (!py_nic_info)
goto error;
sprintf_s(ifname, MAX_PATH, "%wS", pCurrAddresses->FriendlyName);
py_nic_name = PyUnicode_Decode(
ifname, _tcslen(ifname), Py_FileSystemDefaultEncoding, "replace");
if (py_nic_name == NULL)
goto error;
if (PyDict_SetItem(py_retdict, py_nic_name, py_nic_info))
goto error;
Py_XDECREF(py_nic_name);
Py_XDECREF(py_nic_info);
free(pIfRow);
pCurrAddresses = pCurrAddresses->Next;
}
free(pAddresses);
return py_retdict;
error:
Py_XDECREF(py_nic_name);
Py_XDECREF(py_nic_info);
Py_DECREF(py_retdict);
if (pAddresses != NULL)
free(pAddresses);
if (pIfRow != NULL)
free(pIfRow);
return NULL;
}
/*
* Return a Python dict of tuples for disk I/O information
*/
static PyObject *
psutil_disk_io_counters(PyObject *self, PyObject *args)
{
DISK_PERFORMANCE_WIN_2008 diskPerformance;
DWORD dwSize;
HANDLE hDevice = NULL;
char szDevice[MAX_PATH];
char szDeviceDisplay[MAX_PATH];
int devNum;
PyObject *py_retdict = PyDict_New();
PyObject *py_disk_info = NULL;
if (py_retdict == NULL) {
return NULL;
}
// Apparently there's no way to figure out how many times we have
// to iterate in order to find valid drives.
// Let's assume 32, which is higher than 26, the number of letters
// in the alphabet (from A:\ to Z:\).
for (devNum = 0; devNum <= 32; ++devNum) {
py_disk_info = NULL;
sprintf_s(szDevice, MAX_PATH, "\\\\.\\PhysicalDrive%d", devNum);
hDevice = CreateFile(szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE) {
continue;
}
if (DeviceIoControl(hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0,
&diskPerformance, sizeof(diskPerformance),
&dwSize, NULL))
{
sprintf_s(szDeviceDisplay, MAX_PATH, "PhysicalDrive%d", devNum);
py_disk_info = Py_BuildValue(
"(IILLKK)",
diskPerformance.ReadCount,
diskPerformance.WriteCount,
diskPerformance.BytesRead,
diskPerformance.BytesWritten,
(unsigned long long)(diskPerformance.ReadTime.QuadPart * 10) / 1000,
(unsigned long long)(diskPerformance.WriteTime.QuadPart * 10) / 1000);
if (!py_disk_info)
goto error;
if (PyDict_SetItemString(py_retdict, szDeviceDisplay,
py_disk_info))
{
goto error;
}
Py_XDECREF(py_disk_info);
}
else {
// XXX we might get here with ERROR_INSUFFICIENT_BUFFER when
// compiling with mingw32; not sure what to do.
// return PyErr_SetFromWindowsErr(0);
;;
}
CloseHandle(hDevice);
}
return py_retdict;
error:
Py_XDECREF(py_disk_info);
Py_DECREF(py_retdict);
if (hDevice != NULL)
CloseHandle(hDevice);
return NULL;
}
static char *psutil_get_drive_type(int type)
{
switch (type) {
case DRIVE_FIXED:
return "fixed";
case DRIVE_CDROM:
return "cdrom";
case DRIVE_REMOVABLE:
return "removable";
case DRIVE_UNKNOWN:
return "unknown";
case DRIVE_NO_ROOT_DIR:
return "unmounted";
case DRIVE_REMOTE:
return "remote";
case DRIVE_RAMDISK:
return "ramdisk";
default:
return "?";
}
}
#ifndef _ARRAYSIZE
#define _ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
#endif
/*
* Return disk partitions as a list of tuples such as
* (drive_letter, drive_letter, type, "")
*/
static PyObject *
psutil_disk_partitions(PyObject *self, PyObject *args)
{
DWORD num_bytes;
char drive_strings[255];
char *drive_letter = drive_strings;
int all;
int type;
int ret;
char opts[20];
LPTSTR fs_type[MAX_PATH + 1] = { 0 };
DWORD pflags = 0;
PyObject *py_all;
PyObject *py_retlist = PyList_New(0);
PyObject *py_tuple = NULL;
if (py_retlist == NULL) {
return NULL;
}
// avoid to visualize a message box in case something goes wrong
// see https://github.com/giampaolo/psutil/issues/264
SetErrorMode(SEM_FAILCRITICALERRORS);
if (! PyArg_ParseTuple(args, "O", &py_all)) {
goto error;
}
all = PyObject_IsTrue(py_all);
Py_BEGIN_ALLOW_THREADS
num_bytes = GetLogicalDriveStrings(254, drive_letter);
Py_END_ALLOW_THREADS
if (num_bytes == 0) {
PyErr_SetFromWindowsErr(0);
goto error;
}
while (*drive_letter != 0) {
py_tuple = NULL;
opts[0] = 0;
fs_type[0] = 0;
Py_BEGIN_ALLOW_THREADS
type = GetDriveType(drive_letter);
Py_END_ALLOW_THREADS
// by default we only show hard drives and cd-roms
if (all == 0) {
if ((type == DRIVE_UNKNOWN) ||
(type == DRIVE_NO_ROOT_DIR) ||
(type == DRIVE_REMOTE) ||
(type == DRIVE_RAMDISK)) {
goto next;
}
// floppy disk: skip it by default as it introduces a
// considerable slowdown.
if ((type == DRIVE_REMOVABLE) &&
(strcmp(drive_letter, "A:\\") == 0)) {
goto next;
}
}
ret = GetVolumeInformation(
(LPCTSTR)drive_letter, NULL, _ARRAYSIZE(drive_letter),
NULL, NULL, &pflags, (LPTSTR)fs_type, _ARRAYSIZE(fs_type));
if (ret == 0) {
// We might get here in case of a floppy hard drive, in
// which case the error is (21, "device not ready").
// Let's pretend it didn't happen as we already have
// the drive name and type ('removable').
strcat_s(opts, _countof(opts), "");
SetLastError(0);
}
else {
if (pflags & FILE_READ_ONLY_VOLUME) {
strcat_s(opts, _countof(opts), "ro");
}
else {
strcat_s(opts, _countof(opts), "rw");
}
if (pflags & FILE_VOLUME_IS_COMPRESSED) {
strcat_s(opts, _countof(opts), ",compressed");
}
}
if (strlen(opts) > 0) {
strcat_s(opts, _countof(opts), ",");
}
strcat_s(opts, _countof(opts), psutil_get_drive_type(type));
py_tuple = Py_BuildValue(
"(ssss)",
drive_letter,
drive_letter,
fs_type, // either FAT, FAT32, NTFS, HPFS, CDFS, UDF or NWFS
opts);
if (!py_tuple)
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
goto next;
next:
drive_letter = strchr(drive_letter, 0) + 1;
}
SetErrorMode(0);
return py_retlist;
error:
SetErrorMode(0);
Py_XDECREF(py_tuple);
Py_DECREF(py_retlist);
return NULL;
}
/*
* Return a Python dict of tuples for disk I/O information
*/
static PyObject *
psutil_users(PyObject *self, PyObject *args)
{
HANDLE hServer = NULL;
LPTSTR buffer_user = NULL;
LPTSTR buffer_addr = NULL;
PWTS_SESSION_INFO sessions = NULL;
DWORD count;
DWORD i;
DWORD sessionId;
DWORD bytes;
PWTS_CLIENT_ADDRESS address;
char address_str[50];
long long unix_time;
PWINSTATIONQUERYINFORMATIONW WinStationQueryInformationW;
WINSTATION_INFO station_info;
HINSTANCE hInstWinSta = NULL;
ULONG returnLen;
PyObject *py_retlist = PyList_New(0);
PyObject *py_tuple = NULL;
PyObject *py_address = NULL;
PyObject *py_buffer_user_encoded = NULL;
if (py_retlist == NULL) {
return NULL;
}
hInstWinSta = LoadLibraryA("winsta.dll");
WinStationQueryInformationW = (PWINSTATIONQUERYINFORMATIONW) \
GetProcAddress(hInstWinSta, "WinStationQueryInformationW");
hServer = WTSOpenServer('\0');
if (hServer == NULL) {
PyErr_SetFromWindowsErr(0);
goto error;
}
if (WTSEnumerateSessions(hServer, 0, 1, &sessions, &count) == 0) {
PyErr_SetFromWindowsErr(0);
goto error;
}
for (i = 0; i < count; i++) {
py_address = NULL;
py_tuple = NULL;
sessionId = sessions[i].SessionId;
if (buffer_user != NULL) {
WTSFreeMemory(buffer_user);
}
if (buffer_addr != NULL) {
WTSFreeMemory(buffer_addr);
}
buffer_user = NULL;
buffer_addr = NULL;
// username
bytes = 0;
if (WTSQuerySessionInformation(hServer, sessionId, WTSUserName,
&buffer_user, &bytes) == 0) {
PyErr_SetFromWindowsErr(0);
goto error;
}
if (bytes == 1) {
continue;
}
// address
bytes = 0;
if (WTSQuerySessionInformation(hServer, sessionId, WTSClientAddress,
&buffer_addr, &bytes) == 0) {
PyErr_SetFromWindowsErr(0);
goto error;
}
address = (PWTS_CLIENT_ADDRESS)buffer_addr;
if (address->AddressFamily == 0) { // AF_INET
sprintf_s(address_str,
_countof(address_str),
"%u.%u.%u.%u",
address->Address[0],
address->Address[1],
address->Address[2],
address->Address[3]);
py_address = Py_BuildValue("s", address_str);
if (!py_address)
goto error;
}
else {
py_address = Py_None;
}
// login time
if (!WinStationQueryInformationW(hServer,
sessionId,
WinStationInformation,
&station_info,
sizeof(station_info),
&returnLen))
{
goto error;
}
unix_time = ((LONGLONG)station_info.ConnectTime.dwHighDateTime) << 32;
unix_time += \
station_info.ConnectTime.dwLowDateTime - 116444736000000000LL;
unix_time /= 10000000;
py_buffer_user_encoded = PyUnicode_Decode(
buffer_user, _tcslen(buffer_user), Py_FileSystemDefaultEncoding,
"replace");
py_tuple = Py_BuildValue("OOd", py_buffer_user_encoded, py_address,
(double)unix_time);
if (!py_tuple)
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_XDECREF(py_buffer_user_encoded);
Py_XDECREF(py_address);
Py_XDECREF(py_tuple);
}
WTSCloseServer(hServer);
WTSFreeMemory(sessions);
WTSFreeMemory(buffer_user);
WTSFreeMemory(buffer_addr);
FreeLibrary(hInstWinSta);
return py_retlist;
error:
Py_XDECREF(py_buffer_user_encoded);
Py_XDECREF(py_tuple);
Py_XDECREF(py_address);
Py_DECREF(py_retlist);
if (hInstWinSta != NULL) {
FreeLibrary(hInstWinSta);
}
if (hServer != NULL) {
WTSCloseServer(hServer);
}
if (sessions != NULL) {
WTSFreeMemory(sessions);
}
if (buffer_user != NULL) {
WTSFreeMemory(buffer_user);
}
if (buffer_addr != NULL) {
WTSFreeMemory(buffer_addr);
}
return NULL;
}
/*
* Return the number of handles opened by process.
*/
static PyObject *
psutil_proc_num_handles(PyObject *self, PyObject *args)
{
DWORD pid;
HANDLE hProcess;
DWORD handleCount;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
hProcess = psutil_handle_from_pid(pid);
if (NULL == hProcess) {
return NULL;
}
if (! GetProcessHandleCount(hProcess, &handleCount)) {
CloseHandle(hProcess);
return PyErr_SetFromWindowsErr(0);
}
CloseHandle(hProcess);
return Py_BuildValue("k", handleCount);
}
/*
* Get various process information by using NtQuerySystemInformation.
* We use this as a fallback when faster functions fail with access
* denied. This is slower because it iterates over all processes.
* Returned tuple includes the following process info:
*
* - num_threads
* - ctx_switches
* - num_handles (fallback)
* - user/kernel times (fallback)
* - create time (fallback)
* - io counters (fallback)
*/
static PyObject *
psutil_proc_info(PyObject *self, PyObject *args)
{
DWORD pid;
PSYSTEM_PROCESS_INFORMATION process;
PVOID buffer;
ULONG num_handles;
ULONG i;
ULONG ctx_switches = 0;
double user_time;
double kernel_time;
long long create_time;
int num_threads;
LONGLONG io_rcount, io_wcount, io_rbytes, io_wbytes;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
if (! psutil_get_proc_info(pid, &process, &buffer))
return NULL;
num_handles = process->HandleCount;
for (i = 0; i < process->NumberOfThreads; i++)
ctx_switches += process->Threads[i].ContextSwitches;
user_time = (double)process->UserTime.HighPart * 429.4967296 + \
(double)process->UserTime.LowPart * 1e-7;
kernel_time = (double)process->KernelTime.HighPart * 429.4967296 + \
(double)process->KernelTime.LowPart * 1e-7;
// Convert the LARGE_INTEGER union 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.
if (0 == pid || 4 == pid) {
// the python module will translate this into BOOT_TIME later
create_time = 0;
}
else {
create_time = ((LONGLONG)process->CreateTime.HighPart) << 32;
create_time += process->CreateTime.LowPart - 116444736000000000LL;
create_time /= 10000000;
}
num_threads = (int)process->NumberOfThreads;
io_rcount = process->ReadOperationCount.QuadPart;
io_wcount = process->WriteOperationCount.QuadPart;
io_rbytes = process->ReadTransferCount.QuadPart;
io_wbytes = process->WriteTransferCount.QuadPart;
free(buffer);
return Py_BuildValue(
"kkdddiKKKK",
num_handles,
ctx_switches,
user_time,
kernel_time,
(double)create_time,
num_threads,
io_rcount,
io_wcount,
io_rbytes,
io_wbytes
);
}
static char *get_region_protection_string(ULONG protection)
{
switch (protection & 0xff) {
case PAGE_NOACCESS:
return "";
case PAGE_READONLY:
return "r";
case PAGE_READWRITE:
return "rw";
case PAGE_WRITECOPY:
return "wc";
case PAGE_EXECUTE:
return "x";
case PAGE_EXECUTE_READ:
return "xr";
case PAGE_EXECUTE_READWRITE:
return "xrw";
case PAGE_EXECUTE_WRITECOPY:
return "xwc";
default:
return "?";
}
}
/*
* Return a list of process's memory mappings.
*/
static PyObject *
psutil_proc_memory_maps(PyObject *self, PyObject *args)
{
DWORD pid;
HANDLE hProcess = NULL;
MEMORY_BASIC_INFORMATION basicInfo;
PVOID baseAddress;
PVOID previousAllocationBase;
CHAR mappedFileName[MAX_PATH];
SYSTEM_INFO system_info;
LPVOID maxAddr;
PyObject *py_list = PyList_New(0);
PyObject *py_tuple = NULL;
if (py_list == NULL) {
return NULL;
}
if (! PyArg_ParseTuple(args, "l", &pid)) {
goto error;
}
hProcess = psutil_handle_from_pid(pid);
if (NULL == hProcess) {
goto error;
}
GetSystemInfo(&system_info);
maxAddr = system_info.lpMaximumApplicationAddress;
baseAddress = NULL;
previousAllocationBase = NULL;
while (VirtualQueryEx(hProcess, baseAddress, &basicInfo,
sizeof(MEMORY_BASIC_INFORMATION)))
{
py_tuple = NULL;
if (baseAddress > maxAddr) {
break;
}
if (GetMappedFileNameA(hProcess, baseAddress, mappedFileName,
sizeof(mappedFileName)))
{
py_tuple = Py_BuildValue(
"(kssI)",
(unsigned long)baseAddress,
get_region_protection_string(basicInfo.Protect),
mappedFileName,
basicInfo.RegionSize);
if (!py_tuple)
goto error;
if (PyList_Append(py_list, py_tuple))
goto error;
Py_DECREF(py_tuple);
}
previousAllocationBase = basicInfo.AllocationBase;
baseAddress = (PCHAR)baseAddress + basicInfo.RegionSize;
}
CloseHandle(hProcess);
return py_list;
error:
Py_XDECREF(py_tuple);
Py_DECREF(py_list);
if (hProcess != NULL)
CloseHandle(hProcess);
return NULL;
}
/*
* Return a {pid:ppid, ...} dict for all running processes.
*/
static PyObject *
psutil_ppid_map(PyObject *self, PyObject *args)
{
PyObject *pid = NULL;
PyObject *ppid = NULL;
PyObject *py_retdict = PyDict_New();
HANDLE handle = NULL;
PROCESSENTRY32 pe = {0};
pe.dwSize = sizeof(PROCESSENTRY32);
if (py_retdict == NULL)
return NULL;
handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (handle == INVALID_HANDLE_VALUE) {
PyErr_SetFromWindowsErr(0);
Py_DECREF(py_retdict);
return NULL;
}
if (Process32First(handle, &pe)) {
do {
pid = Py_BuildValue("I", pe.th32ProcessID);
if (pid == NULL)
goto error;
ppid = Py_BuildValue("I", pe.th32ParentProcessID);
if (ppid == NULL)
goto error;
if (PyDict_SetItem(py_retdict, pid, ppid))
goto error;
Py_DECREF(pid);
Py_DECREF(ppid);
} while (Process32Next(handle, &pe));
}
CloseHandle(handle);
return py_retdict;
error:
Py_XDECREF(pid);
Py_XDECREF(ppid);
Py_DECREF(py_retdict);
CloseHandle(handle);
return NULL;
}
/*
* Return NICs addresses.
*/
static PyObject *
psutil_net_if_addrs(PyObject *self, PyObject *args)
{
unsigned int i = 0;
ULONG family;
PCTSTR intRet;
char *ptr;
char buff[100];
char ifname[MAX_PATH];
DWORD bufflen = 100;
PIP_ADAPTER_ADDRESSES pAddresses = NULL;
PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
PyObject *py_retlist = PyList_New(0);
PyObject *py_tuple = NULL;
PyObject *py_address = NULL;
PyObject *py_mac_address = NULL;
if (py_retlist == NULL)
return NULL;
pAddresses = psutil_get_nic_addresses();
if (pAddresses == NULL)
goto error;
pCurrAddresses = pAddresses;
while (pCurrAddresses) {
pUnicast = pCurrAddresses->FirstUnicastAddress;
sprintf_s(ifname, MAX_PATH, "%wS", pCurrAddresses->FriendlyName);
// MAC address
if (pCurrAddresses->PhysicalAddressLength != 0) {
ptr = buff;
*ptr = '\0';
for (i = 0; i < (int) pCurrAddresses->PhysicalAddressLength; i++) {
if (i == (pCurrAddresses->PhysicalAddressLength - 1)) {
sprintf_s(ptr, _countof(buff), "%.2X\n",
(int)pCurrAddresses->PhysicalAddress[i]);
}
else {
sprintf_s(ptr, _countof(buff), "%.2X-",
(int)pCurrAddresses->PhysicalAddress[i]);
}
ptr += 3;
}
*--ptr = '\0';
#if PY_MAJOR_VERSION >= 3
py_mac_address = PyUnicode_FromString(buff);
#else
py_mac_address = PyString_FromString(buff);
#endif
if (py_mac_address == NULL)
goto error;
Py_INCREF(Py_None);
Py_INCREF(Py_None);
py_tuple = Py_BuildValue(
"(siOOO)",
ifname,
-1, // this will be converted later to AF_LINK
py_mac_address,
Py_None,
Py_None
);
if (! py_tuple)
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
Py_DECREF(py_mac_address);
}
// find out the IP address associated with the NIC
if (pUnicast != NULL) {
for (i = 0; pUnicast != NULL; i++) {
family = pUnicast->Address.lpSockaddr->sa_family;
if (family == AF_INET) {
struct sockaddr_in *sa_in = (struct sockaddr_in *)
pUnicast->Address.lpSockaddr;
intRet = inet_ntop(AF_INET, &(sa_in->sin_addr), buff,
bufflen);
}
else if (family == AF_INET6) {
struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)
pUnicast->Address.lpSockaddr;
intRet = inet_ntop(AF_INET6, &(sa_in6->sin6_addr),
buff, bufflen);
}
else {
// we should never get here
pUnicast = pUnicast->Next;
continue;
}
if (intRet == NULL) {
PyErr_SetFromWindowsErr(GetLastError());
goto error;
}
#if PY_MAJOR_VERSION >= 3
py_address = PyUnicode_FromString(buff);
#else
py_address = PyString_FromString(buff);
#endif
if (py_address == NULL)
goto error;
Py_INCREF(Py_None);
Py_INCREF(Py_None);
py_tuple = Py_BuildValue(
"(siOOO)",
ifname,
family,
py_address,
Py_None,
Py_None
);
if (! py_tuple)
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
Py_DECREF(py_address);
pUnicast = pUnicast->Next;
}
}
pCurrAddresses = pCurrAddresses->Next;
}
free(pAddresses);
return py_retlist;
error:
if (pAddresses)
free(pAddresses);
Py_DECREF(py_retlist);
Py_XDECREF(py_tuple);
Py_XDECREF(py_address);
return NULL;
}
/*
* Provides stats about NIC interfaces installed on the system.
* TODO: get 'duplex' (currently it's hard coded to '2', aka
'full duplex')
*/
static PyObject *
psutil_net_if_stats(PyObject *self, PyObject *args)
{
int i;
DWORD dwSize = 0;
DWORD dwRetVal = 0;
MIB_IFTABLE *pIfTable;
MIB_IFROW *pIfRow;
PIP_ADAPTER_ADDRESSES pAddresses = NULL;
PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
char friendly_name[MAX_PATH];
char descr[MAX_PATH];
int ifname_found;
PyObject *py_retdict = PyDict_New();
PyObject *py_ifc_info = NULL;
PyObject *py_is_up = NULL;
if (py_retdict == NULL)
return NULL;
pAddresses = psutil_get_nic_addresses();
if (pAddresses == NULL)
goto error;
pIfTable = (MIB_IFTABLE *) malloc(sizeof (MIB_IFTABLE));
if (pIfTable == NULL) {
PyErr_NoMemory();
goto error;
}
dwSize = sizeof(MIB_IFTABLE);
if (GetIfTable(pIfTable, &dwSize, FALSE) == ERROR_INSUFFICIENT_BUFFER) {
free(pIfTable);
pIfTable = (MIB_IFTABLE *) malloc(dwSize);
if (pIfTable == NULL) {
PyErr_NoMemory();
goto error;
}
}
// Make a second call to GetIfTable to get the actual
// data we want.
if ((dwRetVal = GetIfTable(pIfTable, &dwSize, FALSE)) != NO_ERROR) {
PyErr_SetString(PyExc_RuntimeError, "GetIfTable() failed");
goto error;
}
for (i = 0; i < (int) pIfTable->dwNumEntries; i++) {
pIfRow = (MIB_IFROW *) & pIfTable->table[i];
// GetIfTable is not able to give us NIC with "friendly names"
// so we determine them via GetAdapterAddresses() which
// provides friendly names *and* descriptions and find the
// ones that match.
ifname_found = 0;
pCurrAddresses = pAddresses;
while (pCurrAddresses) {
sprintf_s(descr, MAX_PATH, "%wS", pCurrAddresses->Description);
if (lstrcmp(descr, pIfRow->bDescr) == 0) {
sprintf_s(friendly_name, MAX_PATH, "%wS", pCurrAddresses->FriendlyName);
ifname_found = 1;
break;
}
pCurrAddresses = pCurrAddresses->Next;
}
if (ifname_found == 0) {
// Name not found means GetAdapterAddresses() doesn't list
// this NIC, only GetIfTable, meaning it's not really a NIC
// interface so we skip it.
continue;
}
// is up?
if((pIfRow->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED ||
pIfRow->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL) &&
pIfRow->dwAdminStatus == 1 ) {
py_is_up = Py_True;
}
else {
py_is_up = Py_False;
}
Py_INCREF(py_is_up);
py_ifc_info = Py_BuildValue(
"(Oikk)",
py_is_up,
2, // there's no way to know duplex so let's assume 'full'
pIfRow->dwSpeed / 1000000, // expressed in bytes, we want Mb
pIfRow->dwMtu
);
if (!py_ifc_info)
goto error;
if (PyDict_SetItemString(py_retdict, friendly_name, py_ifc_info))
goto error;
Py_DECREF(py_ifc_info);
}
free(pIfTable);
free(pAddresses);
return py_retdict;
error:
Py_XDECREF(py_is_up);
Py_XDECREF(py_ifc_info);
Py_DECREF(py_retdict);
if (pIfTable != NULL)
free(pIfTable);
if (pAddresses != NULL)
free(pAddresses);
return NULL;
}
// ------------------------ Python init ---------------------------
static PyMethodDef
PsutilMethods[] =
{
// --- per-process functions
{"proc_cmdline", psutil_proc_cmdline, METH_VARARGS,
"Return process cmdline as a list of cmdline arguments"},
{"proc_exe", psutil_proc_exe, METH_VARARGS,
"Return path of the process executable"},
{"proc_name", psutil_proc_name, METH_VARARGS,
"Return process name"},
{"proc_kill", psutil_proc_kill, METH_VARARGS,
"Kill the process identified by the given PID"},
{"proc_cpu_times", psutil_proc_cpu_times, METH_VARARGS,
"Return tuple of user/kern time for the given PID"},
{"proc_create_time", psutil_proc_create_time, METH_VARARGS,
"Return a float indicating the process create time expressed in "
"seconds since the epoch"},
{"proc_memory_info", psutil_proc_memory_info, METH_VARARGS,
"Return a tuple of process memory information"},
{"proc_memory_info_2", psutil_proc_memory_info_2, METH_VARARGS,
"Alternate implementation"},
{"proc_cwd", psutil_proc_cwd, METH_VARARGS,
"Return process current working directory"},
{"proc_suspend", psutil_proc_suspend, METH_VARARGS,
"Suspend a process"},
{"proc_resume", psutil_proc_resume, METH_VARARGS,
"Resume a process"},
{"proc_open_files", psutil_proc_open_files, METH_VARARGS,
"Return files opened by process"},
{"proc_username", psutil_proc_username, METH_VARARGS,
"Return the username of a process"},
{"proc_threads", psutil_proc_threads, METH_VARARGS,
"Return process threads information as a list of tuple"},
{"proc_wait", psutil_proc_wait, METH_VARARGS,
"Wait for process to terminate and return its exit code."},
{"proc_priority_get", psutil_proc_priority_get, METH_VARARGS,
"Return process priority."},
{"proc_priority_set", psutil_proc_priority_set, METH_VARARGS,
"Set process priority."},
#if (_WIN32_WINNT >= 0x0600) // Windows Vista
{"proc_io_priority_get", psutil_proc_io_priority_get, METH_VARARGS,
"Return process IO priority."},
{"proc_io_priority_set", psutil_proc_io_priority_set, METH_VARARGS,
"Set process IO priority."},
#endif
{"proc_cpu_affinity_get", psutil_proc_cpu_affinity_get, METH_VARARGS,
"Return process CPU affinity as a bitmask."},
{"proc_cpu_affinity_set", psutil_proc_cpu_affinity_set, METH_VARARGS,
"Set process CPU affinity."},
{"proc_io_counters", psutil_proc_io_counters, METH_VARARGS,
"Get process I/O counters."},
{"proc_is_suspended", psutil_proc_is_suspended, METH_VARARGS,
"Return True if one of the process threads is in a suspended state"},
{"proc_num_handles", psutil_proc_num_handles, METH_VARARGS,
"Return the number of handles opened by process."},
{"proc_memory_maps", psutil_proc_memory_maps, METH_VARARGS,
"Return a list of process's memory mappings"},
// --- alternative pinfo interface
{"proc_info", psutil_proc_info, METH_VARARGS,
"Various process information"},
// --- system-related functions
{"pids", psutil_pids, METH_VARARGS,
"Returns a list of PIDs currently running on the system"},
{"ppid_map", psutil_ppid_map, METH_VARARGS,
"Return a {pid:ppid, ...} dict for all running processes"},
{"pid_exists", psutil_pid_exists, METH_VARARGS,
"Determine if the process exists in the current process list."},
{"cpu_count_logical", psutil_cpu_count_logical, METH_VARARGS,
"Returns the number of logical CPUs on the system"},
{"cpu_count_phys", psutil_cpu_count_phys, METH_VARARGS,
"Returns the number of physical CPUs on the system"},
{"boot_time", psutil_boot_time, METH_VARARGS,
"Return the system boot time expressed in seconds since the epoch."},
{"virtual_mem", psutil_virtual_mem, METH_VARARGS,
"Return the total amount of physical memory, in bytes"},
{"cpu_times", psutil_cpu_times, METH_VARARGS,
"Return system cpu times as a list"},
{"per_cpu_times", psutil_per_cpu_times, METH_VARARGS,
"Return system per-cpu times as a list of tuples"},
{"disk_usage", psutil_disk_usage, METH_VARARGS,
"Return path's disk total and free as a Python tuple."},
{"net_io_counters", psutil_net_io_counters, METH_VARARGS,
"Return dict of tuples of networks I/O information."},
{"disk_io_counters", psutil_disk_io_counters, METH_VARARGS,
"Return dict of tuples of disks I/O information."},
{"users", psutil_users, METH_VARARGS,
"Return a list of currently connected users."},
{"disk_partitions", psutil_disk_partitions, METH_VARARGS,
"Return disk partitions."},
{"net_connections", psutil_net_connections, METH_VARARGS,
"Return system-wide connections"},
{"net_if_addrs", psutil_net_if_addrs, METH_VARARGS,
"Return NICs addresses."},
{"net_if_stats", psutil_net_if_stats, METH_VARARGS,
"Return NICs stats."},
// --- windows API bindings
{"win32_QueryDosDevice", psutil_win32_QueryDosDevice, METH_VARARGS,
"QueryDosDevice binding"},
{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_windows_traverse(PyObject *m, visitproc visit, void *arg) {
Py_VISIT(GETSTATE(m)->error);
return 0;
}
static int psutil_windows_clear(PyObject *m) {
Py_CLEAR(GETSTATE(m)->error);
return 0;
}
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"psutil_windows",
NULL,
sizeof(struct module_state),
PsutilMethods,
NULL,
psutil_windows_traverse,
psutil_windows_clear,
NULL
};
#define INITERROR return NULL
PyMODINIT_FUNC PyInit__psutil_windows(void)
#else
#define INITERROR return
void init_psutil_windows(void)
#endif
{
struct module_state *st = NULL;
#if PY_MAJOR_VERSION >= 3
PyObject *module = PyModule_Create(&moduledef);
#else
PyObject *module = Py_InitModule("_psutil_windows", PsutilMethods);
#endif
if (module == NULL) {
INITERROR;
}
st = GETSTATE(module);
st->error = PyErr_NewException("_psutil_windows.Error", NULL, NULL);
if (st->error == NULL) {
Py_DECREF(module);
INITERROR;
}
PyModule_AddIntConstant(module, "version", PSUTIL_VERSION);
// process status constants
// http://msdn.microsoft.com/en-us/library/ms683211(v=vs.85).aspx
PyModule_AddIntConstant(
module, "ABOVE_NORMAL_PRIORITY_CLASS", ABOVE_NORMAL_PRIORITY_CLASS);
PyModule_AddIntConstant(
module, "BELOW_NORMAL_PRIORITY_CLASS", BELOW_NORMAL_PRIORITY_CLASS);
PyModule_AddIntConstant(
module, "HIGH_PRIORITY_CLASS", HIGH_PRIORITY_CLASS);
PyModule_AddIntConstant(
module, "IDLE_PRIORITY_CLASS", IDLE_PRIORITY_CLASS);
PyModule_AddIntConstant(
module, "NORMAL_PRIORITY_CLASS", NORMAL_PRIORITY_CLASS);
PyModule_AddIntConstant(
module, "REALTIME_PRIORITY_CLASS", REALTIME_PRIORITY_CLASS);
// connection status constants
// http://msdn.microsoft.com/en-us/library/cc669305.aspx
PyModule_AddIntConstant(
module, "MIB_TCP_STATE_CLOSED", MIB_TCP_STATE_CLOSED);
PyModule_AddIntConstant(
module, "MIB_TCP_STATE_CLOSING", MIB_TCP_STATE_CLOSING);
PyModule_AddIntConstant(
module, "MIB_TCP_STATE_CLOSE_WAIT", MIB_TCP_STATE_CLOSE_WAIT);
PyModule_AddIntConstant(
module, "MIB_TCP_STATE_LISTEN", MIB_TCP_STATE_LISTEN);
PyModule_AddIntConstant(
module, "MIB_TCP_STATE_ESTAB", MIB_TCP_STATE_ESTAB);
PyModule_AddIntConstant(
module, "MIB_TCP_STATE_SYN_SENT", MIB_TCP_STATE_SYN_SENT);
PyModule_AddIntConstant(
module, "MIB_TCP_STATE_SYN_RCVD", MIB_TCP_STATE_SYN_RCVD);
PyModule_AddIntConstant(
module, "MIB_TCP_STATE_FIN_WAIT1", MIB_TCP_STATE_FIN_WAIT1);
PyModule_AddIntConstant(
module, "MIB_TCP_STATE_FIN_WAIT2", MIB_TCP_STATE_FIN_WAIT2);
PyModule_AddIntConstant(
module, "MIB_TCP_STATE_LAST_ACK", MIB_TCP_STATE_LAST_ACK);
PyModule_AddIntConstant(
module, "MIB_TCP_STATE_TIME_WAIT", MIB_TCP_STATE_TIME_WAIT);
PyModule_AddIntConstant(
module, "MIB_TCP_STATE_TIME_WAIT", MIB_TCP_STATE_TIME_WAIT);
PyModule_AddIntConstant(
module, "MIB_TCP_STATE_DELETE_TCB", MIB_TCP_STATE_DELETE_TCB);
PyModule_AddIntConstant(
module, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE);
// ...for internal use in _psutil_windows.py
PyModule_AddIntConstant(
module, "INFINITE", INFINITE);
PyModule_AddIntConstant(
module, "ERROR_ACCESS_DENIED", ERROR_ACCESS_DENIED);
// set SeDebug for the current process
psutil_set_se_debug();
#if PY_MAJOR_VERSION >= 3
return module;
#endif
}