summaryrefslogtreecommitdiff
path: root/psutil/_psutil_windows.c
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2020-01-02 13:05:10 -0800
committerGitHub <noreply@github.com>2020-01-02 13:05:10 -0800
commit1358fb7d734878b7e238c39af93ec19dfbe7c77e (patch)
tree8a652270f50a7e10c04e8195d24a25b6ff4c2434 /psutil/_psutil_windows.c
parentac61e733137dbd392635a8573db58c58207eb671 (diff)
downloadpsutil-1358fb7d734878b7e238c39af93ec19dfbe7c77e.tar.gz
Windows: split C modules (#1655)
Diffstat (limited to 'psutil/_psutil_windows.c')
-rw-r--r--psutil/_psutil_windows.c1077
1 files changed, 8 insertions, 1069 deletions
diff --git a/psutil/_psutil_windows.c b/psutil/_psutil_windows.c
index 5ab41695..9c430c5f 100644
--- a/psutil/_psutil_windows.c
+++ b/psutil/_psutil_windows.c
@@ -19,14 +19,10 @@
#include <Python.h>
#include <windows.h>
-#include <Psapi.h>
+#include <Psapi.h> // memory_info(), memory_maps()
#include <signal.h>
-#include <WinIoCtl.h> // disk_io_counters()
-#include <tchar.h>
-#include <tlhelp32.h>
+#include <tlhelp32.h> // threads(), PROCESSENTRY32
#include <wtsapi32.h> // users()
-#include <PowrProf.h> // cpu_freq()
-#include <ws2tcpip.h> // net_io_counters()
// Link with Iphlpapi.lib
#pragma comment(lib, "IPHLPAPI.lib")
@@ -37,64 +33,18 @@
#include "arch/windows/process_utils.h"
#include "arch/windows/process_info.h"
#include "arch/windows/process_handles.h"
+#include "arch/windows/disk.h"
+#include "arch/windows/cpu.h"
+#include "arch/windows/net.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"
-
-/*
- * ============================================================================
- * Utilities
- * ============================================================================
- */
-
-#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
-#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
-#define LO_T 1e-7
-#define HI_T 429.4967296
-#ifndef AF_INET6
-#define AF_INET6 23
-#endif
-
-
-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() syscall failed.");
- return NULL;
- }
-
- return pAddresses;
-}
+// Raised by Process.wait().
+static PyObject *TimeoutExpired;
+static PyObject *TimeoutAbandoned;
/*
@@ -127,16 +77,6 @@ psutil_get_num_cpus(int fail_on_err) {
/*
- * ============================================================================
- * Public Python API
- * ============================================================================
- */
-
-// Raised by Process.wait().
-static PyObject *TimeoutExpired;
-static PyObject *TimeoutAbandoned;
-
-/*
* Return a Python float representing the system uptime expressed in seconds
* since the epoch.
*/
@@ -466,104 +406,6 @@ psutil_proc_create_time(PyObject *self, PyObject *args) {
/*
- * Return the number of active, logical CPUs.
- */
-static PyObject *
-psutil_cpu_count_logical(PyObject *self, PyObject *args) {
- unsigned int ncpus;
-
- ncpus = psutil_get_num_cpus(0);
- if (ncpus != 0)
- return Py_BuildValue("I", ncpus);
- else
- Py_RETURN_NONE; // mimick os.cpu_count()
-}
-
-
-/*
- * Return the number of physical CPU cores (hyper-thread CPUs count
- * is excluded).
- */
-static PyObject *
-psutil_cpu_count_phys(PyObject *self, PyObject *args) {
- DWORD rc;
- PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX buffer = NULL;
- PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX ptr = NULL;
- DWORD length = 0;
- DWORD offset = 0;
- DWORD ncpus = 0;
- DWORD prev_processor_info_size = 0;
-
- // GetLogicalProcessorInformationEx() is available from Windows 7
- // onward. Differently from GetLogicalProcessorInformation()
- // it supports process groups, meaning this is able to report more
- // than 64 CPUs. See:
- // https://bugs.python.org/issue33166
- if (psutil_GetLogicalProcessorInformationEx == NULL) {
- psutil_debug("Win < 7; cpu_count_phys() forced to None");
- Py_RETURN_NONE;
- }
-
- while (1) {
- rc = psutil_GetLogicalProcessorInformationEx(
- RelationAll, buffer, &length);
- if (rc == FALSE) {
- if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
- if (buffer) {
- free(buffer);
- }
- buffer = \
- (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)malloc(length);
- if (NULL == buffer) {
- PyErr_NoMemory();
- return NULL;
- }
- }
- else {
- psutil_debug("GetLogicalProcessorInformationEx() returned ",
- GetLastError());
- goto return_none;
- }
- }
- else {
- break;
- }
- }
-
- ptr = buffer;
- while (offset < length) {
- // Advance ptr by the size of the previous
- // SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX struct.
- ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)\
- (((char*)ptr) + prev_processor_info_size);
-
- if (ptr->Relationship == RelationProcessorCore) {
- ncpus += 1;
- }
-
- // When offset == length, we've reached the last processor
- // info struct in the buffer.
- offset += ptr->Size;
- prev_processor_info_size = ptr->Size;
- }
-
- free(buffer);
- if (ncpus != 0) {
- return Py_BuildValue("I", ncpus);
- }
- else {
- psutil_debug("GetLogicalProcessorInformationEx() count was 0");
- Py_RETURN_NONE; // mimick os.cpu_count()
- }
-
-return_none:
- if (buffer != NULL)
- free(buffer);
- Py_RETURN_NONE;
-}
-
-
-/*
* Return process cmdline as a Python list of cmdline arguments.
*/
static PyObject *
@@ -1175,35 +1017,6 @@ psutil_proc_open_files(PyObject *self, PyObject *args) {
/*
- 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 *
@@ -1574,418 +1387,6 @@ psutil_proc_is_suspended(PyObject *self, PyObject *args) {
/*
- * 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_SetFromWindowsErrWithFilename(0, path);
- 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) {
- DWORD dwRetVal = 0;
- MIB_IF_ROW2 *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_IF_ROW2 *) malloc(sizeof(MIB_IF_ROW2));
- if (pIfRow == NULL) {
- PyErr_NoMemory();
- goto error;
- }
-
- SecureZeroMemory((PVOID)pIfRow, sizeof(MIB_IF_ROW2));
- pIfRow->InterfaceIndex = pCurrAddresses->IfIndex;
- dwRetVal = GetIfEntry2(pIfRow);
- if (dwRetVal != NO_ERROR) {
- PyErr_SetString(PyExc_RuntimeError,
- "GetIfEntry() or GetIfEntry2() syscalls failed.");
- goto error;
- }
-
- py_nic_info = Py_BuildValue("(KKKKKKKK)",
- pIfRow->OutOctets,
- pIfRow->InOctets,
- (pIfRow->OutUcastPkts + pIfRow->OutNUcastPkts),
- (pIfRow->InUcastPkts + pIfRow->InNUcastPkts),
- pIfRow->InErrors,
- pIfRow->OutErrors,
- pIfRow->InDiscards,
- pIfRow->OutDiscards);
- if (!py_nic_info)
- goto error;
-
- py_nic_name = PyUnicode_FromWideChar(
- pCurrAddresses->FriendlyName,
- wcslen(pCurrAddresses->FriendlyName));
-
- if (py_nic_name == NULL)
- goto error;
- if (PyDict_SetItem(py_retdict, py_nic_name, py_nic_info))
- goto error;
- Py_CLEAR(py_nic_name);
- Py_CLEAR(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. This may
- * require running "diskperf -y" command first.
- */
-static PyObject *
-psutil_disk_io_counters(PyObject *self, PyObject *args) {
- DISK_PERFORMANCE diskPerformance;
- DWORD dwSize;
- HANDLE hDevice = NULL;
- char szDevice[MAX_PATH];
- char szDeviceDisplay[MAX_PATH];
- int devNum;
- int i;
- DWORD ioctrlSize;
- BOOL ret;
- PyObject *py_retdict = PyDict_New();
- PyObject *py_tuple = 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_tuple = 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;
-
- // DeviceIoControl() sucks!
- i = 0;
- ioctrlSize = sizeof(diskPerformance);
- while (1) {
- i += 1;
- ret = DeviceIoControl(
- hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, &diskPerformance,
- ioctrlSize, &dwSize, NULL);
- if (ret != 0)
- break; // OK!
- if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
- // Retry with a bigger buffer (+ limit for retries).
- if (i <= 1024) {
- ioctrlSize *= 2;
- continue;
- }
- }
- else if (GetLastError() == ERROR_INVALID_FUNCTION) {
- // This happens on AppVeyor:
- // https://ci.appveyor.com/project/giampaolo/psutil/build/
- // 1364/job/ascpdi271b06jle3
- // Assume it means we're dealing with some exotic disk
- // and go on.
- psutil_debug("DeviceIoControl -> ERROR_INVALID_FUNCTION; "
- "ignore PhysicalDrive%i", devNum);
- goto next;
- }
- else if (GetLastError() == ERROR_NOT_SUPPORTED) {
- // Again, let's assume we're dealing with some exotic disk.
- psutil_debug("DeviceIoControl -> ERROR_NOT_SUPPORTED; "
- "ignore PhysicalDrive%i", devNum);
- goto next;
- }
- // XXX: it seems we should also catch ERROR_INVALID_PARAMETER:
- // https://sites.ualberta.ca/dept/aict/uts/software/openbsd/
- // ports/4.1/i386/openafs/w-openafs-1.4.14-transarc/
- // openafs-1.4.14/src/usd/usd_nt.c
-
- // XXX: we can also bump into ERROR_MORE_DATA in which case
- // (quoting doc) we're supposed to retry with a bigger buffer
- // and specify a new "starting point", whatever it means.
- PyErr_SetFromWindowsErr(0);
- goto error;
- }
-
- sprintf_s(szDeviceDisplay, MAX_PATH, "PhysicalDrive%i", devNum);
- py_tuple = Py_BuildValue(
- "(IILLKK)",
- diskPerformance.ReadCount,
- diskPerformance.WriteCount,
- diskPerformance.BytesRead,
- diskPerformance.BytesWritten,
- // convert to ms:
- // https://github.com/giampaolo/psutil/issues/1012
- (unsigned long long)
- (diskPerformance.ReadTime.QuadPart) / 10000000,
- (unsigned long long)
- (diskPerformance.WriteTime.QuadPart) / 10000000);
- if (!py_tuple)
- goto error;
- if (PyDict_SetItemString(py_retdict, szDeviceDisplay, py_tuple))
- goto error;
- Py_CLEAR(py_tuple);
-
-next:
- CloseHandle(hDevice);
- }
-
- return py_retdict;
-
-error:
- Py_XDECREF(py_tuple);
- 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;
- char mp_buf[MAX_PATH];
- char mp_path[MAX_PATH];
- int all;
- int type;
- int ret;
- unsigned int old_mode = 0;
- char opts[20];
- HANDLE mp_h;
- BOOL mp_flag= TRUE;
- 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
- old_mode = 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");
-
- // Check for mount points on this volume and add/get info
- // (checks first to know if we can even have mount points)
- if (pflags & FILE_SUPPORTS_REPARSE_POINTS) {
-
- mp_h = FindFirstVolumeMountPoint(drive_letter, mp_buf, MAX_PATH);
- if (mp_h != INVALID_HANDLE_VALUE) {
- while (mp_flag) {
-
- // Append full mount path with drive letter
- strcpy_s(mp_path, _countof(mp_path), drive_letter);
- strcat_s(mp_path, _countof(mp_path), mp_buf);
-
- py_tuple = Py_BuildValue(
- "(ssss)",
- drive_letter,
- mp_path,
- fs_type, // Typically NTFS
- opts);
-
- if (!py_tuple || PyList_Append(py_retlist, py_tuple) == -1) {
- FindVolumeMountPointClose(mp_h);
- goto error;
- }
-
- Py_CLEAR(py_tuple);
-
- // Continue looking for more mount points
- mp_flag = FindNextVolumeMountPoint(mp_h, mp_buf, MAX_PATH);
- }
- FindVolumeMountPointClose(mp_h);
- }
-
- }
- }
-
- 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_CLEAR(py_tuple);
- goto next;
-
-next:
- drive_letter = strchr(drive_letter, 0) + 1;
- }
-
- SetErrorMode(old_mode);
- return py_retlist;
-
-error:
- SetErrorMode(old_mode);
- Py_XDECREF(py_tuple);
- Py_DECREF(py_retlist);
- return NULL;
-}
-
-/*
* Return a Python dict of tuples for disk I/O information
*/
static PyObject *
@@ -2382,468 +1783,6 @@ error:
/*
- * Return NICs addresses.
- */
-
-static PyObject *
-psutil_net_if_addrs(PyObject *self, PyObject *args) {
- unsigned int i = 0;
- ULONG family;
- PCTSTR intRet;
- PCTSTR netmaskIntRet;
- char *ptr;
- char buff_addr[1024];
- char buff_macaddr[1024];
- char buff_netmask[1024];
- DWORD dwRetVal = 0;
- ULONG converted_netmask;
- UINT netmask_bits;
- struct in_addr in_netmask;
- 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;
- PyObject *py_nic_name = NULL;
- PyObject *py_netmask = NULL;
-
- if (py_retlist == NULL)
- return NULL;
-
- pAddresses = psutil_get_nic_addresses();
- if (pAddresses == NULL)
- goto error;
- pCurrAddresses = pAddresses;
-
- while (pCurrAddresses) {
- pUnicast = pCurrAddresses->FirstUnicastAddress;
-
- netmaskIntRet = NULL;
- py_nic_name = NULL;
- py_nic_name = PyUnicode_FromWideChar(
- pCurrAddresses->FriendlyName,
- wcslen(pCurrAddresses->FriendlyName));
- if (py_nic_name == NULL)
- goto error;
-
- // MAC address
- if (pCurrAddresses->PhysicalAddressLength != 0) {
- ptr = buff_macaddr;
- *ptr = '\0';
- for (i = 0; i < (int) pCurrAddresses->PhysicalAddressLength; i++) {
- if (i == (pCurrAddresses->PhysicalAddressLength - 1)) {
- sprintf_s(ptr, _countof(buff_macaddr), "%.2X\n",
- (int)pCurrAddresses->PhysicalAddress[i]);
- }
- else {
- sprintf_s(ptr, _countof(buff_macaddr), "%.2X-",
- (int)pCurrAddresses->PhysicalAddress[i]);
- }
- ptr += 3;
- }
- *--ptr = '\0';
-
- py_mac_address = Py_BuildValue("s", buff_macaddr);
- if (py_mac_address == NULL)
- goto error;
-
- Py_INCREF(Py_None);
- Py_INCREF(Py_None);
- Py_INCREF(Py_None);
- py_tuple = Py_BuildValue(
- "(OiOOOO)",
- py_nic_name,
- -1, // this will be converted later to AF_LINK
- py_mac_address,
- Py_None, // netmask (not supported)
- Py_None, // broadcast (not supported)
- Py_None // ptp (not supported on Windows)
- );
- if (! py_tuple)
- goto error;
- if (PyList_Append(py_retlist, py_tuple))
- goto error;
- Py_CLEAR(py_tuple);
- Py_CLEAR(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_addr,
- sizeof(buff_addr));
- if (!intRet)
- goto error;
- netmask_bits = pUnicast->OnLinkPrefixLength;
- dwRetVal = ConvertLengthToIpv4Mask(netmask_bits, &converted_netmask);
- if (dwRetVal == NO_ERROR) {
- in_netmask.s_addr = converted_netmask;
- netmaskIntRet = inet_ntop(
- AF_INET, &in_netmask, buff_netmask,
- sizeof(buff_netmask));
- if (!netmaskIntRet)
- goto error;
- }
- }
- 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_addr, sizeof(buff_addr));
- if (!intRet)
- goto error;
- }
- else {
- // we should never get here
- pUnicast = pUnicast->Next;
- continue;
- }
-
-#if PY_MAJOR_VERSION >= 3
- py_address = PyUnicode_FromString(buff_addr);
-#else
- py_address = PyString_FromString(buff_addr);
-#endif
- if (py_address == NULL)
- goto error;
-
- if (netmaskIntRet != NULL) {
-#if PY_MAJOR_VERSION >= 3
- py_netmask = PyUnicode_FromString(buff_netmask);
-#else
- py_netmask = PyString_FromString(buff_netmask);
-#endif
- } else {
- Py_INCREF(Py_None);
- py_netmask = Py_None;
- }
-
- Py_INCREF(Py_None);
- Py_INCREF(Py_None);
- py_tuple = Py_BuildValue(
- "(OiOOOO)",
- py_nic_name,
- family,
- py_address,
- py_netmask,
- Py_None, // broadcast (not supported)
- Py_None // ptp (not supported on Windows)
- );
-
- if (! py_tuple)
- goto error;
- if (PyList_Append(py_retlist, py_tuple))
- goto error;
- Py_CLEAR(py_tuple);
- Py_CLEAR(py_address);
- Py_CLEAR(py_netmask);
-
- pUnicast = pUnicast->Next;
- }
- }
- Py_CLEAR(py_nic_name);
- 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);
- Py_XDECREF(py_nic_name);
- Py_XDECREF(py_netmask);
- 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 descr[MAX_PATH];
- int ifname_found;
-
- PyObject *py_nic_name = NULL;
- 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() syscall 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) {
- py_nic_name = PyUnicode_FromWideChar(
- pCurrAddresses->FriendlyName,
- wcslen(pCurrAddresses->FriendlyName));
- if (py_nic_name == NULL)
- goto error;
- 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_SetItem(py_retdict, py_nic_name, py_ifc_info))
- goto error;
- Py_CLEAR(py_nic_name);
- Py_CLEAR(py_ifc_info);
- }
-
- free(pIfTable);
- free(pAddresses);
- return py_retdict;
-
-error:
- Py_XDECREF(py_is_up);
- Py_XDECREF(py_ifc_info);
- Py_XDECREF(py_nic_name);
- Py_DECREF(py_retdict);
- if (pIfTable != NULL)
- free(pIfTable);
- if (pAddresses != NULL)
- free(pAddresses);
- return NULL;
-}
-
-
-/*
- * Return CPU statistics.
- */
-static PyObject *
-psutil_cpu_stats(PyObject *self, PyObject *args) {
- NTSTATUS status;
- _SYSTEM_PERFORMANCE_INFORMATION *spi = NULL;
- _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi = NULL;
- _SYSTEM_INTERRUPT_INFORMATION *InterruptInformation = NULL;
- unsigned int ncpus;
- UINT i;
- ULONG64 dpcs = 0;
- ULONG interrupts = 0;
-
- // retrieves number of processors
- ncpus = psutil_get_num_cpus(1);
- if (ncpus == 0)
- goto error;
-
- // get syscalls / ctx switches
- spi = (_SYSTEM_PERFORMANCE_INFORMATION *) \
- malloc(ncpus * sizeof(_SYSTEM_PERFORMANCE_INFORMATION));
- if (spi == NULL) {
- PyErr_NoMemory();
- goto error;
- }
- status = psutil_NtQuerySystemInformation(
- SystemPerformanceInformation,
- spi,
- ncpus * sizeof(_SYSTEM_PERFORMANCE_INFORMATION),
- NULL);
- if (! NT_SUCCESS(status)) {
- psutil_SetFromNTStatusErr(
- status, "NtQuerySystemInformation(SystemPerformanceInformation)");
- goto error;
- }
-
- // get DPCs
- InterruptInformation = \
- malloc(sizeof(_SYSTEM_INTERRUPT_INFORMATION) * ncpus);
- if (InterruptInformation == NULL) {
- PyErr_NoMemory();
- goto error;
- }
-
- status = psutil_NtQuerySystemInformation(
- SystemInterruptInformation,
- InterruptInformation,
- ncpus * sizeof(SYSTEM_INTERRUPT_INFORMATION),
- NULL);
- if (! NT_SUCCESS(status)) {
- psutil_SetFromNTStatusErr(
- status, "NtQuerySystemInformation(SystemInterruptInformation)");
- goto error;
- }
- for (i = 0; i < ncpus; i++) {
- dpcs += InterruptInformation[i].DpcCount;
- }
-
- // get interrupts
- sppi = (_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *) \
- malloc(ncpus * sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
- if (sppi == NULL) {
- PyErr_NoMemory();
- goto error;
- }
-
- status = psutil_NtQuerySystemInformation(
- SystemProcessorPerformanceInformation,
- sppi,
- ncpus * sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION),
- NULL);
- if (! NT_SUCCESS(status)) {
- psutil_SetFromNTStatusErr(
- status,
- "NtQuerySystemInformation(SystemProcessorPerformanceInformation)");
- goto error;
- }
-
- for (i = 0; i < ncpus; i++) {
- interrupts += sppi[i].InterruptCount;
- }
-
- // done
- free(spi);
- free(InterruptInformation);
- free(sppi);
- return Py_BuildValue(
- "kkkk",
- spi->ContextSwitches,
- interrupts,
- (unsigned long)dpcs,
- spi->SystemCalls
- );
-
-error:
- if (spi)
- free(spi);
- if (InterruptInformation)
- free(InterruptInformation);
- if (sppi)
- free(sppi);
- return NULL;
-}
-
-
-/*
- * Return CPU frequency.
- */
-static PyObject *
-psutil_cpu_freq(PyObject *self, PyObject *args) {
- PROCESSOR_POWER_INFORMATION *ppi;
- NTSTATUS ret;
- ULONG size;
- LPBYTE pBuffer = NULL;
- ULONG current;
- ULONG max;
- unsigned int ncpus;
-
- // Get the number of CPUs.
- ncpus = psutil_get_num_cpus(1);
- if (ncpus == 0)
- return NULL;
-
- // Allocate size.
- size = ncpus * sizeof(PROCESSOR_POWER_INFORMATION);
- pBuffer = (BYTE*)LocalAlloc(LPTR, size);
- if (! pBuffer)
- return PyErr_SetFromWindowsErr(0);
-
- // Syscall.
- ret = CallNtPowerInformation(
- ProcessorInformation, NULL, 0, pBuffer, size);
- if (ret != 0) {
- PyErr_SetString(PyExc_RuntimeError,
- "CallNtPowerInformation syscall failed");
- goto error;
- }
-
- // Results.
- ppi = (PROCESSOR_POWER_INFORMATION *)pBuffer;
- max = ppi->MaxMhz;
- current = ppi->CurrentMhz;
- LocalFree(pBuffer);
-
- return Py_BuildValue("kk", current, max);
-
-error:
- if (pBuffer != NULL)
- LocalFree(pBuffer);
- return NULL;
-}
-
-
-/*
* Return battery usage stats.
*/
static PyObject *