Index: third_party/psutil/psutil/_psutil_mswindows.c |
diff --git a/third_party/psutil/psutil/_psutil_mswindows.c b/third_party/psutil/psutil/_psutil_mswindows.c |
index 3964179ab97273ed3d401a1fab9bab55760a4767..484261866f929d69945b4a892ce10d123a5e054a 100644 |
--- a/third_party/psutil/psutil/_psutil_mswindows.c |
+++ b/third_party/psutil/psutil/_psutil_mswindows.c |
@@ -1,5 +1,5 @@ |
/* |
- * $Id: _psutil_mswindows.c 1142 2011-10-05 18:45:49Z g.rodola $ |
+ * $Id: _psutil_mswindows.c 1202 2011-10-24 19:00:50Z g.rodola $ |
* |
* 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 |
@@ -8,15 +8,23 @@ |
* Windows platform-specific module methods for _psutil_mswindows |
*/ |
+// 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> |
+// Link with Iphlpapi.lib |
+#pragma comment(lib, "IPHLPAPI.lib") |
+ |
#include "_psutil_mswindows.h" |
#include "_psutil_common.h" |
#include "arch/mswindows/security.h" |
@@ -473,9 +481,15 @@ get_memory_info(PyObject* self, PyObject* args) |
CloseHandle(hProcess); |
return PyErr_SetFromWindowsErr(0); |
} |
- |
- CloseHandle(hProcess); |
+ |
+// py 2.4 |
+#if (PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION <= 4) |
+ return Py_BuildValue("(II)", (unsigned int)counters.WorkingSetSize, |
+ (unsigned int)counters.PagefileUsage); |
+#else |
+// py >= 2.5 |
return Py_BuildValue("(nn)", counters.WorkingSetSize, counters.PagefileUsage); |
+#endif |
} |
@@ -1215,6 +1229,8 @@ get_process_connections(PyObject* self, PyObject* args) |
unsigned long pid; |
PyObject* connectionsList; |
PyObject* connectionTuple; |
+ PyObject *af_filter = NULL; |
+ PyObject *type_filter = NULL; |
typedef PSTR (NTAPI *_RtlIpv4AddressToStringA)(struct in_addr *, |
PSTR /* __out_ecount(16) */); |
_RtlIpv4AddressToStringA rtlIpv4AddressToStringA; |
@@ -1239,7 +1255,12 @@ get_process_connections(PyObject* self, PyObject* args) |
CHAR addressBufferRemote[65]; |
PyObject* addressTupleRemote; |
- if (!PyArg_ParseTuple(args, "l", &pid)) { |
+ if (! PyArg_ParseTuple(args, "lOO", &pid, &af_filter, &type_filter)) { |
+ return NULL; |
+ } |
+ |
+ if (!PySequence_Check(af_filter) || !PySequence_Check(type_filter)) { |
+ PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence"); |
return NULL; |
} |
@@ -1276,229 +1297,247 @@ get_process_connections(PyObject* self, PyObject* args) |
/* TCP IPv4 */ |
- tableSize = 0; |
- getExtendedTcpTable(NULL, &tableSize, FALSE, AF_INET, |
- TCP_TABLE_OWNER_PID_ALL, 0); |
- |
- table = malloc(tableSize); |
- |
- if (getExtendedTcpTable(table, &tableSize, FALSE, AF_INET, |
- TCP_TABLE_OWNER_PID_ALL, 0) == 0) |
+ if ((PySequence_Contains(af_filter, PyLong_FromLong((long)AF_INET)) == 1) && |
+ (PySequence_Contains(type_filter, PyLong_FromLong((long)SOCK_STREAM)) == 1)) |
{ |
- tcp4Table = table; |
+ tableSize = 0; |
+ getExtendedTcpTable(NULL, &tableSize, FALSE, AF_INET, |
+ TCP_TABLE_OWNER_PID_ALL, 0); |
+ |
+ table = malloc(tableSize); |
- for (i = 0; i < tcp4Table->dwNumEntries; i++) |
+ if (getExtendedTcpTable(table, &tableSize, FALSE, AF_INET, |
+ TCP_TABLE_OWNER_PID_ALL, 0) == 0) |
{ |
- if (tcp4Table->table[i].dwOwningPid != pid) { |
- continue; |
- } |
+ tcp4Table = table; |
- if (tcp4Table->table[i].dwLocalAddr != 0 || |
- tcp4Table->table[i].dwLocalPort != 0) |
+ for (i = 0; i < tcp4Table->dwNumEntries; i++) |
{ |
- struct in_addr addr; |
+ if (tcp4Table->table[i].dwOwningPid != pid) { |
+ continue; |
+ } |
- 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 (tcp4Table->table[i].dwLocalAddr != 0 || |
+ tcp4Table->table[i].dwLocalPort != 0) |
+ { |
+ struct in_addr addr; |
- // 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].dwLocalAddr; |
+ rtlIpv4AddressToStringA(&addr, addressBufferLocal); |
+ addressTupleLocal = Py_BuildValue("(si)", addressBufferLocal, |
+ BYTESWAP_USHORT(tcp4Table->table[i].dwLocalPort)); |
+ } |
+ else |
+ { |
+ addressTupleLocal = PyTuple_New(0); |
+ } |
- 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); |
- } |
+ // On Windows <= XP, remote addr is filled even if socket |
+ // is in LISTEN mode in which case we just ignore it. |
+ if ((tcp4Table->table[i].dwRemoteAddr != 0 || |
+ tcp4Table->table[i].dwRemotePort != 0) && |
+ (tcp4Table->table[i].dwState != MIB_TCP_STATE_LISTEN)) |
+ { |
+ struct in_addr addr; |
+ |
+ addr.S_un.S_addr = tcp4Table->table[i].dwRemoteAddr; |
+ rtlIpv4AddressToStringA(&addr, addressBufferRemote); |
+ addressTupleRemote = Py_BuildValue("(si)", addressBufferRemote, |
+ BYTESWAP_USHORT(tcp4Table->table[i].dwRemotePort)); |
+ } |
+ else |
+ { |
+ addressTupleRemote = PyTuple_New(0); |
+ } |
- connectionTuple = Py_BuildValue("(iiiNNs)", |
- -1, |
- AF_INET, |
- SOCK_STREAM, |
- addressTupleLocal, |
- addressTupleRemote, |
- state_to_string(tcp4Table->table[i].dwState) |
- ); |
- PyList_Append(connectionsList, connectionTuple); |
+ connectionTuple = Py_BuildValue("(iiiNNs)", |
+ -1, |
+ AF_INET, |
+ SOCK_STREAM, |
+ addressTupleLocal, |
+ addressTupleRemote, |
+ state_to_string(tcp4Table->table[i].dwState) |
+ ); |
+ PyList_Append(connectionsList, connectionTuple); |
+ } |
} |
- } |
- free(table); |
+ free(table); |
+ } |
/* TCP IPv6 */ |
- tableSize = 0; |
- getExtendedTcpTable(NULL, &tableSize, FALSE, AF_INET6, |
- TCP_TABLE_OWNER_PID_ALL, 0); |
- |
- table = malloc(tableSize); |
- |
- if (getExtendedTcpTable(table, &tableSize, FALSE, AF_INET6, |
- TCP_TABLE_OWNER_PID_ALL, 0) == 0) |
+ if ((PySequence_Contains(af_filter, PyLong_FromLong((long)AF_INET6)) == 1) && |
+ (PySequence_Contains(type_filter, PyLong_FromLong((long)SOCK_STREAM)) == 1)) |
{ |
- tcp6Table = table; |
+ tableSize = 0; |
+ getExtendedTcpTable(NULL, &tableSize, FALSE, AF_INET6, |
+ TCP_TABLE_OWNER_PID_ALL, 0); |
- for (i = 0; i < tcp6Table->dwNumEntries; i++) |
+ table = malloc(tableSize); |
+ |
+ if (getExtendedTcpTable(table, &tableSize, FALSE, AF_INET6, |
+ TCP_TABLE_OWNER_PID_ALL, 0) == 0) |
{ |
- if (tcp6Table->table[i].dwOwningPid != pid) { |
- continue; |
- } |
+ tcp6Table = table; |
- if (memcmp(tcp6Table->table[i].ucLocalAddr, null_address, 16) != 0 || |
- tcp6Table->table[i].dwLocalPort != 0) |
+ for (i = 0; i < tcp6Table->dwNumEntries; i++) |
{ |
- struct in6_addr addr; |
+ if (tcp6Table->table[i].dwOwningPid != pid) { |
+ continue; |
+ } |
- 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 (memcmp(tcp6Table->table[i].ucLocalAddr, null_address, 16) != 0 || |
+ tcp6Table->table[i].dwLocalPort != 0) |
+ { |
+ struct in6_addr addr; |
- // 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].ucLocalAddr, 16); |
+ rtlIpv6AddressToStringA(&addr, addressBufferLocal); |
+ addressTupleLocal = Py_BuildValue("(si)", addressBufferLocal, |
+ BYTESWAP_USHORT(tcp6Table->table[i].dwLocalPort)); |
+ } |
+ else |
+ { |
+ addressTupleLocal = PyTuple_New(0); |
+ } |
- 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); |
- } |
+ // 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; |
- connectionTuple = Py_BuildValue("(iiiNNs)", |
- -1, |
- AF_INET6, |
- SOCK_STREAM, |
- addressTupleLocal, |
- addressTupleRemote, |
- state_to_string(tcp6Table->table[i].dwState) |
- ); |
- PyList_Append(connectionsList, connectionTuple); |
+ memcpy(&addr, tcp6Table->table[i].ucRemoteAddr, 16); |
+ rtlIpv6AddressToStringA(&addr, addressBufferRemote); |
+ addressTupleRemote = Py_BuildValue("(si)", addressBufferRemote, |
+ BYTESWAP_USHORT(tcp6Table->table[i].dwRemotePort)); |
+ } |
+ else |
+ { |
+ addressTupleRemote = PyTuple_New(0); |
+ } |
+ |
+ connectionTuple = Py_BuildValue("(iiiNNs)", |
+ -1, |
+ AF_INET6, |
+ SOCK_STREAM, |
+ addressTupleLocal, |
+ addressTupleRemote, |
+ state_to_string(tcp6Table->table[i].dwState) |
+ ); |
+ PyList_Append(connectionsList, connectionTuple); |
+ } |
} |
- } |
- free(table); |
+ free(table); |
+ } |
/* UDP IPv4 */ |
- tableSize = 0; |
- getExtendedUdpTable(NULL, &tableSize, FALSE, AF_INET, |
- UDP_TABLE_OWNER_PID, 0); |
- |
- table = malloc(tableSize); |
- |
- if (getExtendedUdpTable(table, &tableSize, FALSE, AF_INET, |
- UDP_TABLE_OWNER_PID, 0) == 0) |
+ if ((PySequence_Contains(af_filter, PyLong_FromLong((long)AF_INET)) == 1) && |
+ (PySequence_Contains(type_filter, PyLong_FromLong((long)SOCK_DGRAM)) == 1)) |
{ |
- udp4Table = table; |
+ tableSize = 0; |
+ getExtendedUdpTable(NULL, &tableSize, FALSE, AF_INET, |
+ UDP_TABLE_OWNER_PID, 0); |
- for (i = 0; i < udp4Table->dwNumEntries; i++) |
+ table = malloc(tableSize); |
+ |
+ if (getExtendedUdpTable(table, &tableSize, FALSE, AF_INET, |
+ UDP_TABLE_OWNER_PID, 0) == 0) |
{ |
- if (udp4Table->table[i].dwOwningPid != pid) { |
- continue; |
- } |
+ udp4Table = table; |
- if (udp4Table->table[i].dwLocalAddr != 0 || |
- udp4Table->table[i].dwLocalPort != 0) |
+ for (i = 0; i < udp4Table->dwNumEntries; i++) |
{ |
- struct in_addr addr; |
+ if (udp4Table->table[i].dwOwningPid != pid) { |
+ continue; |
+ } |
- 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 (udp4Table->table[i].dwLocalAddr != 0 || |
+ udp4Table->table[i].dwLocalPort != 0) |
+ { |
+ struct in_addr addr; |
+ |
+ addr.S_un.S_addr = udp4Table->table[i].dwLocalAddr; |
+ rtlIpv4AddressToStringA(&addr, addressBufferLocal); |
+ addressTupleLocal = Py_BuildValue("(si)", addressBufferLocal, |
+ BYTESWAP_USHORT(udp4Table->table[i].dwLocalPort)); |
+ } |
+ else |
+ { |
+ addressTupleLocal = PyTuple_New(0); |
+ } |
- connectionTuple = Py_BuildValue("(iiiNNs)", |
- -1, |
- AF_INET, |
- SOCK_DGRAM, |
- addressTupleLocal, |
- PyTuple_New(0), |
- "" |
- ); |
- PyList_Append(connectionsList, connectionTuple); |
+ connectionTuple = Py_BuildValue("(iiiNNs)", |
+ -1, |
+ AF_INET, |
+ SOCK_DGRAM, |
+ addressTupleLocal, |
+ PyTuple_New(0), |
+ "" |
+ ); |
+ PyList_Append(connectionsList, connectionTuple); |
+ } |
} |
- } |
- free(table); |
+ free(table); |
+ } |
/* UDP IPv6 */ |
- tableSize = 0; |
- getExtendedUdpTable(NULL, &tableSize, FALSE, AF_INET6, UDP_TABLE_OWNER_PID, 0); |
- |
- table = malloc(tableSize); |
- |
- if (getExtendedUdpTable(table, &tableSize, FALSE, AF_INET6, UDP_TABLE_OWNER_PID, 0) == 0) |
+ if ((PySequence_Contains(af_filter, PyLong_FromLong((long)AF_INET6)) == 1) && |
+ (PySequence_Contains(type_filter, PyLong_FromLong((long)SOCK_DGRAM)) == 1)) |
{ |
- udp6Table = table; |
+ tableSize = 0; |
+ getExtendedUdpTable(NULL, &tableSize, FALSE, |
+ AF_INET6, UDP_TABLE_OWNER_PID, 0); |
+ |
+ table = malloc(tableSize); |
- for (i = 0; i < udp6Table->dwNumEntries; i++) |
+ if (getExtendedUdpTable(table, &tableSize, FALSE, AF_INET6, |
+ UDP_TABLE_OWNER_PID, 0) == 0) |
{ |
- if (udp6Table->table[i].dwOwningPid != pid) { |
- continue; |
- } |
+ udp6Table = table; |
- if (memcmp(udp6Table->table[i].ucLocalAddr, null_address, 16) != 0 || |
- udp6Table->table[i].dwLocalPort != 0) |
+ for (i = 0; i < udp6Table->dwNumEntries; i++) |
{ |
- struct in6_addr addr; |
+ if (udp6Table->table[i].dwOwningPid != pid) { |
+ continue; |
+ } |
- 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 (memcmp(udp6Table->table[i].ucLocalAddr, null_address, 16) != 0 || |
+ udp6Table->table[i].dwLocalPort != 0) |
+ { |
+ struct in6_addr addr; |
- connectionTuple = Py_BuildValue("(iiiNNs)", |
- -1, |
- AF_INET6, |
- SOCK_DGRAM, |
- addressTupleLocal, |
- PyTuple_New(0), |
- "" |
- ); |
- PyList_Append(connectionsList, connectionTuple); |
+ memcpy(&addr, udp6Table->table[i].ucLocalAddr, 16); |
+ rtlIpv6AddressToStringA(&addr, addressBufferLocal); |
+ addressTupleLocal = Py_BuildValue("(si)", addressBufferLocal, |
+ BYTESWAP_USHORT(udp6Table->table[i].dwLocalPort)); |
+ } |
+ else |
+ { |
+ addressTupleLocal = PyTuple_New(0); |
+ } |
+ |
+ connectionTuple = Py_BuildValue("(iiiNNs)", |
+ -1, |
+ AF_INET6, |
+ SOCK_DGRAM, |
+ addressTupleLocal, |
+ PyTuple_New(0), |
+ "" |
+ ); |
+ PyList_Append(connectionsList, connectionTuple); |
+ } |
} |
- } |
- free(table); |
+ free(table); |
+ } |
return connectionsList; |
} |
@@ -1658,7 +1697,155 @@ get_disk_usage(PyObject* self, PyObject* args) |
/* |
- * Return disk partitions as a list of namedtuples. |
+ * Return a Python list of named tuples with overall network I/O information |
+ */ |
+static PyObject* |
+get_network_io_counters(PyObject* self, PyObject* args) |
+{ |
+ PyObject* py_retdict = PyDict_New(); |
+ PyObject* py_nic_info = NULL; |
+ PyObject* py_pre_nic_name = NULL; |
+ PyObject* py_nic_name = NULL; |
+ |
+ int attempts = 0; |
+ int outBufLen = 15000; |
+ DWORD dwRetVal = 0; |
+ MIB_IFROW *pIfRow; |
+ ULONG flags = 0; |
+ ULONG family = AF_UNSPEC; |
+ PIP_ADAPTER_ADDRESSES pAddresses = NULL; |
+ PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; |
+ |
+ do { |
+ pAddresses = (IP_ADAPTER_ADDRESSES *) malloc(outBufLen); |
+ if (pAddresses == NULL) { |
+ Py_DECREF(py_retdict); |
+ PyErr_SetString(PyExc_RuntimeError, |
+ "memory allocation failed for IP_ADAPTER_ADDRESSES struct."); |
+ return NULL; |
+ } |
+ |
+ dwRetVal = GetAdaptersAddresses(family, flags, 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) { |
+ Py_DECREF(py_retdict); |
+ PyErr_SetString(PyExc_RuntimeError, "GetAdaptersAddresses() failed."); |
+ return NULL; |
+ } |
+ |
+ pCurrAddresses = pAddresses; |
+ while (pCurrAddresses) { |
+ pIfRow = (MIB_IFROW *) malloc(sizeof(MIB_IFROW)); |
+ |
+ if (pIfRow == NULL) { |
+ Py_DECREF(py_retdict); |
+ Py_XDECREF(py_pre_nic_name); |
+ Py_XDECREF(py_nic_name); |
+ Py_XDECREF(py_nic_info); |
+ PyErr_SetString(PyExc_RuntimeError, |
+ "memory allocation failed for MIB_IFROW struct."); |
+ return NULL; |
+ } |
+ |
+ pIfRow->dwIndex = pCurrAddresses->IfIndex; |
+ dwRetVal = GetIfEntry(pIfRow); |
+ if (dwRetVal != NO_ERROR) { |
+ Py_DECREF(py_retdict); |
+ Py_XDECREF(py_pre_nic_name); |
+ Py_XDECREF(py_nic_name); |
+ Py_XDECREF(py_nic_info); |
+ PyErr_SetString(PyExc_RuntimeError, |
+ "GetIfEntry() failed."); |
+ return NULL; |
+ } |
+ |
+ py_nic_info = Py_BuildValue("(IIII)", |
+ pIfRow->dwOutOctets, |
+ pIfRow->dwInOctets, |
+ pIfRow->dwOutUcastPkts, |
+ pIfRow->dwInUcastPkts); |
+ |
+ py_pre_nic_name = PyUnicode_FromWideChar( |
+ pCurrAddresses->FriendlyName, |
+ wcslen(pCurrAddresses->FriendlyName)); |
+ py_nic_name = PyUnicode_FromObject(py_pre_nic_name); |
+ PyDict_SetItem(py_retdict, py_nic_name, py_nic_info); |
+ Py_XDECREF(py_pre_nic_name); |
+ Py_XDECREF(py_nic_name); |
+ Py_XDECREF(py_nic_info); |
+ |
+ free(pIfRow); |
+ pCurrAddresses = pCurrAddresses->Next; |
+ } |
+ |
+ free(pAddresses); |
+ |
+ return py_retdict; |
+} |
+ |
+ |
+/* |
+ * Return a Python dict of tuples for disk I/O information |
+ */ |
+static PyObject* |
+get_disk_io_counters(PyObject* self, PyObject* args) |
+{ |
+ PyObject* py_retdict = PyDict_New(); |
+ PyObject* py_disk_info; |
+ |
+ DISK_PERFORMANCE diskPerformance; |
+ DWORD dwSize; |
+ HANDLE hDevice = NULL; |
+ char szDevice[MAX_PATH]; |
+ char szDeviceDisplay[MAX_PATH]; |
+ int devNum; |
+ |
+ for (devNum = 0;; devNum++) { |
+ sprintf (szDevice, "\\\\.\\PhysicalDrive%d", devNum); |
+ hDevice = CreateFile (szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, |
+ NULL, OPEN_EXISTING, 0, NULL); |
+ |
+ if (hDevice == INVALID_HANDLE_VALUE) |
+ break; |
+ |
+ if (DeviceIoControl (hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, |
+ &diskPerformance, sizeof (DISK_PERFORMANCE), &dwSize, NULL)) { |
+ sprintf (szDeviceDisplay, "PhysicalDrive%d", devNum); |
+ py_disk_info = Py_BuildValue("(IILLLL)", |
+ diskPerformance.ReadCount, |
+ diskPerformance.WriteCount, |
+ diskPerformance.BytesRead, |
+ diskPerformance.BytesWritten, |
+ (diskPerformance.ReadTime.QuadPart |
+ * 10) / 1000, |
+ (diskPerformance.WriteTime.QuadPart |
+ * 10) / 1000); |
+ PyDict_SetItemString(py_retdict, |
+ szDeviceDisplay, |
+ py_disk_info); |
+ Py_XDECREF(py_disk_info); |
+ } |
+ |
+ CloseHandle(hDevice); |
+ } |
+ |
+ return py_retdict; |
+} |
+ |
+ |
+/* |
+ * Return disk partitions as a list of strings. |
*/ |
static PyObject* |
win32_GetLogicalDriveStrings(PyObject* self, PyObject* args) |
@@ -1667,6 +1854,7 @@ win32_GetLogicalDriveStrings(PyObject* self, PyObject* args) |
char drive_strings[255]; |
char* drive_letter = drive_strings; |
PyObject* py_retlist = PyList_New(0); |
+ PyObject* py_string = NULL; |
Py_BEGIN_ALLOW_THREADS |
num_bytes = GetLogicalDriveStrings(254, drive_letter); |
@@ -1677,8 +1865,10 @@ win32_GetLogicalDriveStrings(PyObject* self, PyObject* args) |
} |
while (*drive_letter != 0) { |
- PyList_Append(py_retlist, Py_BuildValue("s", drive_letter)); |
- drive_letter = strchr(drive_letter, 0) +1; |
+ py_string = Py_BuildValue("s", drive_letter); |
+ PyList_Append(py_retlist, py_string); |
+ Py_DECREF(py_string); |
+ drive_letter = strchr(drive_letter, 0) + 1; |
} |
return py_retlist; |
@@ -1795,6 +1985,10 @@ PsutilMethods[] = |
"Return system per-cpu times as a list of tuples"}, |
{"get_disk_usage", get_disk_usage, METH_VARARGS, |
"Return path's disk total and free as a Python tuple."}, |
+ {"get_network_io_counters", get_network_io_counters, METH_VARARGS, |
+ "Return dict of tuples of networks I/O information."}, |
+ {"get_disk_io_counters", get_disk_io_counters, METH_VARARGS, |
+ "Return dict of tuples of disks I/O information."}, |
// --- windows API bindings |
{"win32_GetLogicalDriveStrings", win32_GetLogicalDriveStrings, METH_VARARGS, |
@@ -1892,6 +2086,3 @@ struct module_state { |
return module; |
#endif |
} |
- |
- |
- |