diff options
author | Giampaolo Rodola <g.rodola@gmail.com> | 2022-10-21 13:23:26 -0700 |
---|---|---|
committer | Giampaolo Rodola <g.rodola@gmail.com> | 2022-10-21 13:23:26 -0700 |
commit | 1cd46a0076b52a3d2ccf8e0b077fe0adae38549b (patch) | |
tree | 597b7ce2c5d0e2d2bbe19cfc3170d5d5a9146e67 | |
parent | 8e4099d9f063ceb4ee3da5845562c5b934f83544 (diff) | |
download | psutil-1cd46a0076b52a3d2ccf8e0b077fe0adae38549b.tar.gz |
expose disk_swaps() on Windows
-rw-r--r-- | psutil/arch/windows/disk.c | 83 | ||||
-rw-r--r-- | psutil/arch/windows/ntextapi.h | 11 |
2 files changed, 94 insertions, 0 deletions
diff --git a/psutil/arch/windows/disk.c b/psutil/arch/windows/disk.c index 7c35e812..c3a38082 100644 --- a/psutil/arch/windows/disk.c +++ b/psutil/arch/windows/disk.c @@ -360,6 +360,89 @@ error: /* + * Return information about the disk page files as a list. + * A page file is basically the same thing as a swap partition. + */ +PyObject * +psutil_disk_swaps(PyObject *self, PyObject *args) { + NTSTATUS status; + PVOID buffer = NULL; + ULONG bufferSize = 0x200; + PSYSTEM_PAGEFILE_INFORMATION pInfo; + PyObject *py_tuple = NULL; + PyObject *py_path = NULL; + PyObject *py_retlist = PyList_New(0); + + if (! py_retlist) + return NULL; + + // Enumerate page files. + buffer = MALLOC_ZERO(bufferSize); + while ((status = NtQuerySystemInformation( + SystemPageFileInformation, + buffer, + bufferSize, + NULL)) == STATUS_INFO_LENGTH_MISMATCH) + { + FREE(buffer); + bufferSize *= 2; + buffer = MALLOC_ZERO(bufferSize); + } + + if (! NT_SUCCESS(status)) { + psutil_SetFromNTStatusErr(status, "NtQuerySystemInformation"); + goto error; + } + + // Traverse the resulting struct. + // A TotalSize of 0 is used to indicate that there are no pagefiles. + pInfo = (SYSTEM_PAGEFILE_INFORMATION *)buffer; + if (pInfo->TotalSize != 0) { + while (TRUE) { + // construct python list + py_path = PyUnicode_FromWideChar( + pInfo->PageFileName.Buffer, + wcslen(pInfo->PageFileName.Buffer)); + if (! py_path) + goto error; + + py_tuple = Py_BuildValue( + "Okkk", + py_path, + pInfo->TotalSize * PSUTIL_SYSTEM_INFO.dwPageSize, + pInfo->TotalInUse * PSUTIL_SYSTEM_INFO.dwPageSize, + pInfo->PeakUsage * PSUTIL_SYSTEM_INFO.dwPageSize + ); + if (!py_tuple) + goto error; + if (PyList_Append(py_retlist, py_tuple)) + goto error; + Py_CLEAR(py_tuple); + Py_CLEAR(py_path); + + // end of list + if (pInfo->NextEntryOffset == 0) + break; + // set pointer to the next pInfo struct + pInfo = (SYSTEM_PAGEFILE_INFORMATION *) \ + ((BYTE *)pInfo + pInfo->NextEntryOffset); + } + } + + FREE(buffer); + return py_retlist; + +error: + if (buffer != NULL) + FREE(buffer); + Py_XDECREF(py_tuple); + Py_XDECREF(py_path); + Py_DECREF(py_retlist); + return NULL; +} + + +/* 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. diff --git a/psutil/arch/windows/ntextapi.h b/psutil/arch/windows/ntextapi.h index e0662fa0..a07f9831 100644 --- a/psutil/arch/windows/ntextapi.h +++ b/psutil/arch/windows/ntextapi.h @@ -41,6 +41,8 @@ typedef LONG NTSTATUS; #define ProcessWow64Information 26 #undef SystemProcessIdInformation #define SystemProcessIdInformation 88 +#undef SystemPageFileInformation +#define SystemPageFileInformation 18 // process suspend() / resume() typedef enum _KTHREAD_STATE { @@ -448,6 +450,15 @@ typedef struct _SYSTEM_PROCESS_ID_INFORMATION { UNICODE_STRING ImageName; } SYSTEM_PROCESS_ID_INFORMATION, *PSYSTEM_PROCESS_ID_INFORMATION; +// disk_swaps() +typedef struct _SYSTEM_PAGEFILE_INFORMATION { + ULONG NextEntryOffset; + ULONG TotalSize; + ULONG TotalInUse; + ULONG PeakUsage; + UNICODE_STRING PageFileName; +} SYSTEM_PAGEFILE_INFORMATION, *PSYSTEM_PAGEFILE_INFORMATION; + // ==================================================================== // PEB structs for cmdline(), cwd(), environ() // ==================================================================== |