Skip to content

Commit 58612f5

Browse files
committed
Implemented Zig wrapper for GetProcessMemoryInfo
`GetProcessMemoryInfo` is implemented using `NtQueryInformationProcess` with `ProcessVmCounters` to obtain `VM_COUNTERS`. The structs, enum definitions are found in `winternl.h` or `ntddk.h` in the latest WDK. This should give the same results as using `K32GetProcessMemoryInfo`
1 parent 4600d2f commit 58612f5

File tree

3 files changed

+111
-3
lines changed

3 files changed

+111
-3
lines changed

lib/std/child_process.zig

+3-3
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ pub const ChildProcess = struct {
137137
os.SetIdError ||
138138
os.ChangeCurDirError ||
139139
windows.CreateProcessError ||
140+
windows.GetProcessMemoryInfoError ||
140141
windows.WaitForSingleObjectError;
141142

142143
pub const Term = union(enum) {
@@ -374,9 +375,8 @@ pub const ChildProcess = struct {
374375

375376
if (self.request_resource_usage_statistics) {
376377
var pmc: windows.PROCESS_MEMORY_COUNTERS = undefined;
377-
if (windows.kernel32.K32GetProcessMemoryInfo(self.id, &pmc, @sizeOf(windows.PROCESS_MEMORY_COUNTERS)) != 0) {
378-
self.resource_usage_statistics.rusage = pmc;
379-
}
378+
try windows.GetProcessMemoryInfo(self.id, &pmc);
379+
self.resource_usage_statistics.rusage = pmc;
380380
}
381381

382382
os.close(self.id);

lib/std/os/windows.zig

+45
Original file line numberDiff line numberDiff line change
@@ -3947,6 +3947,20 @@ pub const PSAPI_WS_WATCH_INFORMATION = extern struct {
39473947
FaultingVa: LPVOID,
39483948
};
39493949

3950+
pub const VM_COUNTERS = extern struct {
3951+
PeakVirtualSize: SIZE_T,
3952+
VirtualSize: SIZE_T,
3953+
PageFaultCount: ULONG,
3954+
PeakWorkingSetSize: SIZE_T,
3955+
WorkingSetSize: SIZE_T,
3956+
QuotaPeakPagedPoolUsage: SIZE_T,
3957+
QuotaPagedPoolUsage: SIZE_T,
3958+
QuotaPeakNonPagedPoolUsage: SIZE_T,
3959+
QuotaNonPagedPoolUsage: SIZE_T,
3960+
PagefileUsage: SIZE_T,
3961+
PeakPagefileUsage: SIZE_T,
3962+
};
3963+
39503964
pub const PROCESS_MEMORY_COUNTERS = extern struct {
39513965
cb: DWORD,
39523966
PageFaultCount: DWORD,
@@ -3974,6 +3988,37 @@ pub const PROCESS_MEMORY_COUNTERS_EX = extern struct {
39743988
PrivateUsage: SIZE_T,
39753989
};
39763990

3991+
pub const GetProcessMemoryInfoError = error{
3992+
AccessDenied,
3993+
InvalidHandle,
3994+
Unexpected,
3995+
};
3996+
3997+
pub fn GetProcessMemoryInfo(hProcess: HANDLE, out: *PROCESS_MEMORY_COUNTERS) GetProcessMemoryInfoError!void {
3998+
var vmc: VM_COUNTERS = undefined;
3999+
const rc = ntdll.NtQueryInformationProcess(hProcess, .ProcessVmCounters, &vmc, @sizeOf(VM_COUNTERS), null);
4000+
switch (rc) {
4001+
.SUCCESS => {
4002+
out.* = PROCESS_MEMORY_COUNTERS{
4003+
.cb = @sizeOf(PROCESS_MEMORY_COUNTERS),
4004+
.PageFaultCount = vmc.PageFaultCount,
4005+
.PeakWorkingSetSize = vmc.PeakWorkingSetSize,
4006+
.WorkingSetSize = vmc.WorkingSetSize,
4007+
.QuotaPeakPagedPoolUsage = vmc.QuotaPeakPagedPoolUsage,
4008+
.QuotaPagedPoolUsage = vmc.QuotaPagedPoolUsage,
4009+
.QuotaPeakNonPagedPoolUsage = vmc.QuotaPeakNonPagedPoolUsage,
4010+
.QuotaNonPagedPoolUsage = vmc.QuotaNonPagedPoolUsage,
4011+
.PagefileUsage = vmc.PagefileUsage,
4012+
.PeakPagefileUsage = vmc.PeakPagefileUsage,
4013+
};
4014+
},
4015+
.ACCESS_DENIED => return error.AccessDenied,
4016+
.INVALID_HANDLE => return error.InvalidHandle,
4017+
.INVALID_PARAMETER => unreachable,
4018+
else => return unexpectedStatus(rc),
4019+
}
4020+
}
4021+
39774022
pub const PERFORMANCE_INFORMATION = extern struct {
39784023
cb: DWORD,
39794024
CommitTotal: SIZE_T,

lib/std/os/windows/ntdll.zig

+63
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,69 @@ const RUNTIME_FUNCTION = windows.RUNTIME_FUNCTION;
3232
const KNONVOLATILE_CONTEXT_POINTERS = windows.KNONVOLATILE_CONTEXT_POINTERS;
3333
const EXCEPTION_ROUTINE = windows.EXCEPTION_ROUTINE;
3434

35+
pub const PROCESSINFOCLASS = enum(c_int) {
36+
ProcessBasicInformation,
37+
ProcessQuotaLimits,
38+
ProcessIoCounters,
39+
ProcessVmCounters,
40+
ProcessTimes,
41+
ProcessBasePriority,
42+
ProcessRaisePriority,
43+
ProcessDebugPort,
44+
ProcessExceptionPort,
45+
ProcessAccessToken,
46+
ProcessLdtInformation,
47+
ProcessLdtSize,
48+
ProcessDefaultHardErrorMode,
49+
ProcessIoPortHandlers,
50+
ProcessPooledUsageAndLimits,
51+
ProcessWorkingSetWatch,
52+
ProcessUserModeIOPL,
53+
ProcessEnableAlignmentFaultFixup,
54+
ProcessPriorityClass,
55+
ProcessWx86Information,
56+
ProcessHandleCount,
57+
ProcessAffinityMask,
58+
ProcessPriorityBoost,
59+
ProcessDeviceMap,
60+
ProcessSessionInformation,
61+
ProcessForegroundInformation,
62+
ProcessWow64Information,
63+
ProcessImageFileName,
64+
ProcessLUIDDeviceMapsEnabled,
65+
ProcessBreakOnTermination,
66+
ProcessDebugObjectHandle,
67+
ProcessDebugFlags,
68+
ProcessHandleTracing,
69+
ProcessIoPriority,
70+
ProcessExecuteFlags,
71+
ProcessTlsInformation,
72+
ProcessCookie,
73+
ProcessImageInformation,
74+
ProcessCycleTime,
75+
ProcessPagePriority,
76+
ProcessInstrumentationCallback,
77+
ProcessThreadStackAllocation,
78+
ProcessWorkingSetWatchEx,
79+
ProcessImageFileNameWin32,
80+
ProcessImageFileMapping,
81+
ProcessAffinityUpdateMode,
82+
ProcessMemoryAllocationMode,
83+
ProcessGroupInformation,
84+
ProcessTokenVirtualizationEnabled,
85+
ProcessConsoleHostProcess,
86+
ProcessWindowInformation,
87+
MaxProcessInfoClass
88+
};
89+
90+
pub extern "ntdll" fn NtQueryInformationProcess(
91+
ProcessHandle: HANDLE,
92+
ProcessInformationClass: PROCESSINFOCLASS,
93+
ProcessInformation: *anyopaque,
94+
ProcessInformationLength: ULONG,
95+
ReturnLength: ?*ULONG,
96+
) callconv(WINAPI) NTSTATUS;
97+
3598
pub const THREADINFOCLASS = enum(c_int) {
3699
ThreadBasicInformation,
37100
ThreadTimes,

0 commit comments

Comments
 (0)