summaryrefslogtreecommitdiff
path: root/psutil/_psutil_windows.c
diff options
context:
space:
mode:
Diffstat (limited to 'psutil/_psutil_windows.c')
-rw-r--r--psutil/_psutil_windows.c787
1 files changed, 5 insertions, 782 deletions
diff --git a/psutil/_psutil_windows.c b/psutil/_psutil_windows.c
index 5ab41695..e0105cb2 100644
--- a/psutil/_psutil_windows.c
+++ b/psutil/_psutil_windows.c
@@ -21,12 +21,10 @@
#include <windows.h>
#include <Psapi.h>
#include <signal.h>
-#include <WinIoCtl.h> // disk_io_counters()
#include <tchar.h>
#include <tlhelp32.h>
#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 +35,19 @@
#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/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))
+// Raised by Process.wait().
+static PyObject *TimeoutExpired;
+static PyObject *TimeoutAbandoned;
#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;
-}
/*
@@ -127,16 +80,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.
*/
@@ -1574,418 +1517,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,314 +1913,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 *