From 59504a56500a8332f0eb8563178e20f843ff8820 Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Tue, 18 Apr 2023 11:16:53 -0700 Subject: Win, C, refact: move boot_time() and users() in new sys.c --- psutil/_psutil_windows.c | 173 ++------------------------------------------ psutil/arch/windows/sys.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++ psutil/arch/windows/sys.h | 10 +++ setup.py | 7 +- 4 files changed, 198 insertions(+), 170 deletions(-) create mode 100644 psutil/arch/windows/sys.c create mode 100644 psutil/arch/windows/sys.h diff --git a/psutil/_psutil_windows.c b/psutil/_psutil_windows.c index d7ffbfe3..ef854332 100644 --- a/psutil/_psutil_windows.c +++ b/psutil/_psutil_windows.c @@ -27,17 +27,18 @@ #pragma comment(lib, "IPHLPAPI.lib") #include "_psutil_common.h" -#include "arch/windows/security.h" -#include "arch/windows/process_utils.h" -#include "arch/windows/process_info.h" -#include "arch/windows/process_handles.h" -#include "arch/windows/disk.h" #include "arch/windows/cpu.h" +#include "arch/windows/disk.h" #include "arch/windows/mem.h" #include "arch/windows/net.h" +#include "arch/windows/process_handles.h" +#include "arch/windows/process_info.h" +#include "arch/windows/process_utils.h" +#include "arch/windows/security.h" #include "arch/windows/sensors.h" #include "arch/windows/services.h" #include "arch/windows/socks.h" +#include "arch/windows/sys.h" #include "arch/windows/wmi.h" // Raised by Process.wait(). @@ -45,21 +46,6 @@ static PyObject *TimeoutExpired; static PyObject *TimeoutAbandoned; -/* - * Return a Python float representing the system uptime expressed in seconds - * since the epoch. - */ -static PyObject * -psutil_boot_time(PyObject *self, PyObject *args) { - ULONGLONG upTime; - FILETIME fileTime; - - GetSystemTimeAsFileTime(&fileTime); - // Number of milliseconds that have elapsed since the system was started. - upTime = GetTickCount64() / 1000ull; - return Py_BuildValue("d", psutil_FiletimeToUnixTime(fileTime) - upTime); -} - /* * Return 1 if PID exists in the current process list, else 0. @@ -1098,153 +1084,6 @@ psutil_proc_is_suspended(PyObject *self, PyObject *args) { } -/* - * Return a Python dict of tuples for disk I/O information - */ -static PyObject * -psutil_users(PyObject *self, PyObject *args) { - HANDLE hServer = WTS_CURRENT_SERVER_HANDLE; - LPWSTR buffer_user = NULL; - LPWSTR buffer_addr = NULL; - LPWSTR buffer_info = NULL; - PWTS_SESSION_INFOW sessions = NULL; - DWORD count; - DWORD i; - DWORD sessionId; - DWORD bytes; - PWTS_CLIENT_ADDRESS address; - char address_str[50]; - PWTSINFOW wts_info; - PyObject *py_tuple = NULL; - PyObject *py_address = NULL; - PyObject *py_username = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - - if (WTSEnumerateSessionsW == NULL || - WTSQuerySessionInformationW == NULL || - WTSFreeMemory == NULL) { - // If we don't run in an environment that is a Remote Desktop Services environment - // the Wtsapi32 proc might not be present. - // https://docs.microsoft.com/en-us/windows/win32/termserv/run-time-linking-to-wtsapi32-dll - return py_retlist; - } - - if (WTSEnumerateSessionsW(hServer, 0, 1, &sessions, &count) == 0) { - if (ERROR_CALL_NOT_IMPLEMENTED == GetLastError()) { - // On Windows Nano server, the Wtsapi32 API can be present, but return WinError 120. - return py_retlist; - } - PyErr_SetFromOSErrnoWithSyscall("WTSEnumerateSessionsW"); - 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); - if (buffer_info != NULL) - WTSFreeMemory(buffer_info); - - buffer_user = NULL; - buffer_addr = NULL; - buffer_info = NULL; - - // username - bytes = 0; - if (WTSQuerySessionInformationW(hServer, sessionId, WTSUserName, - &buffer_user, &bytes) == 0) { - PyErr_SetFromOSErrnoWithSyscall("WTSQuerySessionInformationW"); - goto error; - } - if (bytes <= 2) - continue; - - // address - bytes = 0; - if (WTSQuerySessionInformationW(hServer, sessionId, WTSClientAddress, - &buffer_addr, &bytes) == 0) { - PyErr_SetFromOSErrnoWithSyscall("WTSQuerySessionInformationW"); - goto error; - } - - address = (PWTS_CLIENT_ADDRESS)buffer_addr; - if (address->AddressFamily == 2) { // AF_INET == 2 - sprintf_s(address_str, - _countof(address_str), - "%u.%u.%u.%u", - // The IP address is offset by two bytes from the start of the Address member of the WTS_CLIENT_ADDRESS structure. - address->Address[2], - address->Address[3], - address->Address[4], - address->Address[5]); - py_address = Py_BuildValue("s", address_str); - if (!py_address) - goto error; - } - else { - Py_INCREF(Py_None); - py_address = Py_None; - } - - // login time - bytes = 0; - if (WTSQuerySessionInformationW(hServer, sessionId, WTSSessionInfo, - &buffer_info, &bytes) == 0) { - PyErr_SetFromOSErrnoWithSyscall("WTSQuerySessionInformationW"); - goto error; - } - wts_info = (PWTSINFOW)buffer_info; - - py_username = PyUnicode_FromWideChar(buffer_user, wcslen(buffer_user)); - if (py_username == NULL) - goto error; - - py_tuple = Py_BuildValue( - "OOd", - py_username, - py_address, - psutil_LargeIntegerToUnixTime(wts_info->ConnectTime) - ); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_username); - Py_CLEAR(py_address); - Py_CLEAR(py_tuple); - } - - WTSFreeMemory(sessions); - WTSFreeMemory(buffer_user); - WTSFreeMemory(buffer_addr); - WTSFreeMemory(buffer_info); - return py_retlist; - -error: - Py_XDECREF(py_username); - Py_XDECREF(py_tuple); - Py_XDECREF(py_address); - Py_DECREF(py_retlist); - - if (sessions != NULL) - WTSFreeMemory(sessions); - if (buffer_user != NULL) - WTSFreeMemory(buffer_user); - if (buffer_addr != NULL) - WTSFreeMemory(buffer_addr); - if (buffer_info != NULL) - WTSFreeMemory(buffer_info); - return NULL; -} - - /* * Return the number of handles opened by process. */ diff --git a/psutil/arch/windows/sys.c b/psutil/arch/windows/sys.c new file mode 100644 index 00000000..3e12e71b --- /dev/null +++ b/psutil/arch/windows/sys.c @@ -0,0 +1,178 @@ +/* + * 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. + */ + +/* +System related functions. Original code moved in here from +psutil/_psutil_windows.c in 2023. For reference, here's the GIT blame +history before the move: + +* boot_time(): https://github.com/giampaolo/psutil/blame/efd7ed3/psutil/_psutil_windows.c#L51-L60 +* users(): https://github.com/giampaolo/psutil/blame/efd7ed3/psutil/_psutil_windows.c#L1103-L1244 +*/ + +#include +#include + +#include "ntextapi.h" +#include "../../_psutil_common.h" + + +// Return a Python float representing the system uptime expressed in +// seconds since the epoch. +PyObject * +psutil_boot_time(PyObject *self, PyObject *args) { + ULONGLONG upTime; + FILETIME fileTime; + + GetSystemTimeAsFileTime(&fileTime); + // Number of milliseconds that have elapsed since the system was started. + upTime = GetTickCount64() / 1000ull; + return Py_BuildValue("d", psutil_FiletimeToUnixTime(fileTime) - upTime); +} + + +PyObject * +psutil_users(PyObject *self, PyObject *args) { + HANDLE hServer = WTS_CURRENT_SERVER_HANDLE; + LPWSTR buffer_user = NULL; + LPWSTR buffer_addr = NULL; + LPWSTR buffer_info = NULL; + PWTS_SESSION_INFOW sessions = NULL; + DWORD count; + DWORD i; + DWORD sessionId; + DWORD bytes; + PWTS_CLIENT_ADDRESS address; + char address_str[50]; + PWTSINFOW wts_info; + PyObject *py_tuple = NULL; + PyObject *py_address = NULL; + PyObject *py_username = NULL; + PyObject *py_retlist = PyList_New(0); + + if (py_retlist == NULL) + return NULL; + + if (WTSEnumerateSessionsW == NULL || + WTSQuerySessionInformationW == NULL || + WTSFreeMemory == NULL) { + // If we don't run in an environment that is a Remote Desktop Services environment + // the Wtsapi32 proc might not be present. + // https://docs.microsoft.com/en-us/windows/win32/termserv/run-time-linking-to-wtsapi32-dll + return py_retlist; + } + + if (WTSEnumerateSessionsW(hServer, 0, 1, &sessions, &count) == 0) { + if (ERROR_CALL_NOT_IMPLEMENTED == GetLastError()) { + // On Windows Nano server, the Wtsapi32 API can be present, but return WinError 120. + return py_retlist; + } + PyErr_SetFromOSErrnoWithSyscall("WTSEnumerateSessionsW"); + 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); + if (buffer_info != NULL) + WTSFreeMemory(buffer_info); + + buffer_user = NULL; + buffer_addr = NULL; + buffer_info = NULL; + + // username + bytes = 0; + if (WTSQuerySessionInformationW(hServer, sessionId, WTSUserName, + &buffer_user, &bytes) == 0) { + PyErr_SetFromOSErrnoWithSyscall("WTSQuerySessionInformationW"); + goto error; + } + if (bytes <= 2) + continue; + + // address + bytes = 0; + if (WTSQuerySessionInformationW(hServer, sessionId, WTSClientAddress, + &buffer_addr, &bytes) == 0) { + PyErr_SetFromOSErrnoWithSyscall("WTSQuerySessionInformationW"); + goto error; + } + + address = (PWTS_CLIENT_ADDRESS)buffer_addr; + if (address->AddressFamily == 2) { // AF_INET == 2 + sprintf_s(address_str, + _countof(address_str), + "%u.%u.%u.%u", + // The IP address is offset by two bytes from the start of the Address member of the WTS_CLIENT_ADDRESS structure. + address->Address[2], + address->Address[3], + address->Address[4], + address->Address[5]); + py_address = Py_BuildValue("s", address_str); + if (!py_address) + goto error; + } + else { + Py_INCREF(Py_None); + py_address = Py_None; + } + + // login time + bytes = 0; + if (WTSQuerySessionInformationW(hServer, sessionId, WTSSessionInfo, + &buffer_info, &bytes) == 0) { + PyErr_SetFromOSErrnoWithSyscall("WTSQuerySessionInformationW"); + goto error; + } + wts_info = (PWTSINFOW)buffer_info; + + py_username = PyUnicode_FromWideChar(buffer_user, wcslen(buffer_user)); + if (py_username == NULL) + goto error; + + py_tuple = Py_BuildValue( + "OOd", + py_username, + py_address, + psutil_LargeIntegerToUnixTime(wts_info->ConnectTime) + ); + if (!py_tuple) + goto error; + if (PyList_Append(py_retlist, py_tuple)) + goto error; + Py_CLEAR(py_username); + Py_CLEAR(py_address); + Py_CLEAR(py_tuple); + } + + WTSFreeMemory(sessions); + WTSFreeMemory(buffer_user); + WTSFreeMemory(buffer_addr); + WTSFreeMemory(buffer_info); + return py_retlist; + +error: + Py_XDECREF(py_username); + Py_XDECREF(py_tuple); + Py_XDECREF(py_address); + Py_DECREF(py_retlist); + + if (sessions != NULL) + WTSFreeMemory(sessions); + if (buffer_user != NULL) + WTSFreeMemory(buffer_user); + if (buffer_addr != NULL) + WTSFreeMemory(buffer_addr); + if (buffer_info != NULL) + WTSFreeMemory(buffer_info); + return NULL; +} diff --git a/psutil/arch/windows/sys.h b/psutil/arch/windows/sys.h new file mode 100644 index 00000000..344ca21d --- /dev/null +++ b/psutil/arch/windows/sys.h @@ -0,0 +1,10 @@ +/* + * 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. + */ + +#include + +PyObject *psutil_boot_time(PyObject *self, PyObject *args); +PyObject *psutil_users(PyObject *self, PyObject *args); diff --git a/setup.py b/setup.py index 434522d2..4923600a 100755 --- a/setup.py +++ b/setup.py @@ -210,17 +210,18 @@ if WINDOWS: 'psutil._psutil_windows', sources=sources + [ 'psutil/_psutil_windows.c', - 'psutil/arch/windows/process_utils.c', - 'psutil/arch/windows/process_info.c', - 'psutil/arch/windows/process_handles.c', 'psutil/arch/windows/cpu.c', 'psutil/arch/windows/disk.c', 'psutil/arch/windows/mem.c', 'psutil/arch/windows/net.c', + 'psutil/arch/windows/process_handles.c', + 'psutil/arch/windows/process_info.c', + 'psutil/arch/windows/process_utils.c', 'psutil/arch/windows/security.c', 'psutil/arch/windows/sensors.c', 'psutil/arch/windows/services.c', 'psutil/arch/windows/socks.c', + 'psutil/arch/windows/sys.c', 'psutil/arch/windows/wmi.c', ], define_macros=macros, -- cgit v1.2.1