|
49 | 49 | #include <crtdbg.h> |
50 | 50 | #include "winreparse.h" |
51 | 51 |
|
| 52 | +// PSAPI_VERSION=2 redirects GetProcessMemoryInfo() to |
| 53 | +// K32GetProcessMemoryInfo() in kernel32.dll, so we don't need to link |
| 54 | +// psapi.lib. See: |
| 55 | +// https://learn.microsoft.com/windows/win32/api/psapi/nf-psapi-getprocessmemoryinfo |
| 56 | +#define PSAPI_VERSION 2 |
| 57 | +#include <psapi.h> // GetProcessMemoryInfo() |
| 58 | + |
52 | 59 | #if defined(MS_WIN32) && !defined(MS_WIN64) |
53 | 60 | #define HANDLE_TO_PYNUM(handle) \ |
54 | 61 | PyLong_FromUnsignedLong((unsigned long) handle) |
@@ -3080,6 +3087,61 @@ _winapi_ReportEvent_impl(PyObject *module, HANDLE handle, |
3080 | 3087 | } |
3081 | 3088 |
|
3082 | 3089 |
|
| 3090 | +/*[clinic input] |
| 3091 | +_winapi.GetProcessMemoryInfo |
| 3092 | + handle: HANDLE |
| 3093 | + / |
| 3094 | +
|
| 3095 | +Return the memory usage of the given process handle as a dict. |
| 3096 | +[clinic start generated code]*/ |
| 3097 | + |
| 3098 | +static PyObject * |
| 3099 | +_winapi_GetProcessMemoryInfo_impl(PyObject *module, HANDLE handle) |
| 3100 | +/*[clinic end generated code: output=00a5d09732e84120 input=5b90ad61cdc68d2a]*/ |
| 3101 | +{ |
| 3102 | + PROCESS_MEMORY_COUNTERS pmc; |
| 3103 | + if (!GetProcessMemoryInfo(handle, &pmc, sizeof(pmc))) { |
| 3104 | + return PyErr_SetFromWindowsErr(0); |
| 3105 | + } |
| 3106 | + |
| 3107 | + PyObject *result = PyDict_New(); |
| 3108 | + if (result == NULL) { |
| 3109 | + return NULL; |
| 3110 | + } |
| 3111 | + |
| 3112 | +#define ADD(ATTR) \ |
| 3113 | + do { \ |
| 3114 | + PyObject *obj = PyLong_FromSize_t(pmc.ATTR); \ |
| 3115 | + if (obj == NULL) { \ |
| 3116 | + goto error; \ |
| 3117 | + } \ |
| 3118 | + if (PyDict_SetItemString(result, #ATTR, obj) < 0) { \ |
| 3119 | + Py_DECREF(obj); \ |
| 3120 | + goto error; \ |
| 3121 | + } \ |
| 3122 | + Py_DECREF(obj); \ |
| 3123 | + } while (0) |
| 3124 | + |
| 3125 | + ADD(PageFaultCount); |
| 3126 | + ADD(PeakWorkingSetSize); |
| 3127 | + ADD(WorkingSetSize); |
| 3128 | + ADD(QuotaPeakPagedPoolUsage); |
| 3129 | + ADD(QuotaPagedPoolUsage); |
| 3130 | + ADD(QuotaPeakNonPagedPoolUsage); |
| 3131 | + ADD(QuotaNonPagedPoolUsage); |
| 3132 | + ADD(PagefileUsage); |
| 3133 | + ADD(PeakPagefileUsage); |
| 3134 | + |
| 3135 | +#undef ADD |
| 3136 | + |
| 3137 | + return result; |
| 3138 | + |
| 3139 | +error: |
| 3140 | + Py_DECREF(result); |
| 3141 | + return NULL; |
| 3142 | +} |
| 3143 | + |
| 3144 | + |
3083 | 3145 | static PyMethodDef winapi_functions[] = { |
3084 | 3146 | _WINAPI_CLOSEHANDLE_METHODDEF |
3085 | 3147 | _WINAPI_CONNECTNAMEDPIPE_METHODDEF |
@@ -3130,6 +3192,7 @@ static PyMethodDef winapi_functions[] = { |
3130 | 3192 | _WINAPI__MIMETYPES_READ_WINDOWS_REGISTRY_METHODDEF |
3131 | 3193 | _WINAPI_NEEDCURRENTDIRECTORYFOREXEPATH_METHODDEF |
3132 | 3194 | _WINAPI_COPYFILE2_METHODDEF |
| 3195 | + _WINAPI_GETPROCESSMEMORYINFO_METHODDEF |
3133 | 3196 | {NULL, NULL} |
3134 | 3197 | }; |
3135 | 3198 |
|
@@ -3226,6 +3289,7 @@ static int winapi_exec(PyObject *m) |
3226 | 3289 | WINAPI_CONSTANT(F_DWORD, PROCESS_ALL_ACCESS); |
3227 | 3290 | WINAPI_CONSTANT(F_DWORD, SYNCHRONIZE); |
3228 | 3291 | WINAPI_CONSTANT(F_DWORD, PROCESS_DUP_HANDLE); |
| 3292 | + WINAPI_CONSTANT(F_DWORD, PROCESS_QUERY_LIMITED_INFORMATION); |
3229 | 3293 | WINAPI_CONSTANT(F_DWORD, SEC_COMMIT); |
3230 | 3294 | WINAPI_CONSTANT(F_DWORD, SEC_IMAGE); |
3231 | 3295 | WINAPI_CONSTANT(F_DWORD, SEC_LARGE_PAGES); |
|
0 commit comments