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`
This commit is contained in:
xEgoist 2023-03-22 05:57:14 -05:00
parent cc44183787
commit 70469d428d
3 changed files with 111 additions and 3 deletions

View File

@ -137,6 +137,7 @@ pub const ChildProcess = struct {
os.SetIdError ||
os.ChangeCurDirError ||
windows.CreateProcessError ||
windows.GetProcessMemoryInfoError ||
windows.WaitForSingleObjectError;
pub const Term = union(enum) {
@ -374,9 +375,8 @@ pub const ChildProcess = struct {
if (self.request_resource_usage_statistics) {
var pmc: windows.PROCESS_MEMORY_COUNTERS = undefined;
if (windows.kernel32.K32GetProcessMemoryInfo(self.id, &pmc, @sizeOf(windows.PROCESS_MEMORY_COUNTERS)) != 0) {
self.resource_usage_statistics.rusage = pmc;
}
try windows.GetProcessMemoryInfo(self.id, &pmc);
self.resource_usage_statistics.rusage = pmc;
}
os.close(self.id);

View File

@ -3947,6 +3947,20 @@ pub const PSAPI_WS_WATCH_INFORMATION = extern struct {
FaultingVa: LPVOID,
};
pub const VM_COUNTERS = extern struct {
PeakVirtualSize: SIZE_T,
VirtualSize: SIZE_T,
PageFaultCount: ULONG,
PeakWorkingSetSize: SIZE_T,
WorkingSetSize: SIZE_T,
QuotaPeakPagedPoolUsage: SIZE_T,
QuotaPagedPoolUsage: SIZE_T,
QuotaPeakNonPagedPoolUsage: SIZE_T,
QuotaNonPagedPoolUsage: SIZE_T,
PagefileUsage: SIZE_T,
PeakPagefileUsage: SIZE_T,
};
pub const PROCESS_MEMORY_COUNTERS = extern struct {
cb: DWORD,
PageFaultCount: DWORD,
@ -3974,6 +3988,37 @@ pub const PROCESS_MEMORY_COUNTERS_EX = extern struct {
PrivateUsage: SIZE_T,
};
pub const GetProcessMemoryInfoError = error{
AccessDenied,
InvalidHandle,
Unexpected,
};
pub fn GetProcessMemoryInfo(hProcess: HANDLE, out: *PROCESS_MEMORY_COUNTERS) GetProcessMemoryInfoError!void {
var vmc: VM_COUNTERS = undefined;
const rc = ntdll.NtQueryInformationProcess(hProcess, .ProcessVmCounters, &vmc, @sizeOf(VM_COUNTERS), null);
switch (rc) {
.SUCCESS => {
out.* = PROCESS_MEMORY_COUNTERS{
.cb = @sizeOf(PROCESS_MEMORY_COUNTERS),
.PageFaultCount = vmc.PageFaultCount,
.PeakWorkingSetSize = vmc.PeakWorkingSetSize,
.WorkingSetSize = vmc.WorkingSetSize,
.QuotaPeakPagedPoolUsage = vmc.QuotaPeakPagedPoolUsage,
.QuotaPagedPoolUsage = vmc.QuotaPagedPoolUsage,
.QuotaPeakNonPagedPoolUsage = vmc.QuotaPeakNonPagedPoolUsage,
.QuotaNonPagedPoolUsage = vmc.QuotaNonPagedPoolUsage,
.PagefileUsage = vmc.PagefileUsage,
.PeakPagefileUsage = vmc.PeakPagefileUsage,
};
},
.ACCESS_DENIED => return error.AccessDenied,
.INVALID_HANDLE => return error.InvalidHandle,
.INVALID_PARAMETER => unreachable,
else => return unexpectedStatus(rc),
}
}
pub const PERFORMANCE_INFORMATION = extern struct {
cb: DWORD,
CommitTotal: SIZE_T,

View File

@ -32,6 +32,69 @@ const RUNTIME_FUNCTION = windows.RUNTIME_FUNCTION;
const KNONVOLATILE_CONTEXT_POINTERS = windows.KNONVOLATILE_CONTEXT_POINTERS;
const EXCEPTION_ROUTINE = windows.EXCEPTION_ROUTINE;
pub const PROCESSINFOCLASS = enum(c_int) {
ProcessBasicInformation,
ProcessQuotaLimits,
ProcessIoCounters,
ProcessVmCounters,
ProcessTimes,
ProcessBasePriority,
ProcessRaisePriority,
ProcessDebugPort,
ProcessExceptionPort,
ProcessAccessToken,
ProcessLdtInformation,
ProcessLdtSize,
ProcessDefaultHardErrorMode,
ProcessIoPortHandlers,
ProcessPooledUsageAndLimits,
ProcessWorkingSetWatch,
ProcessUserModeIOPL,
ProcessEnableAlignmentFaultFixup,
ProcessPriorityClass,
ProcessWx86Information,
ProcessHandleCount,
ProcessAffinityMask,
ProcessPriorityBoost,
ProcessDeviceMap,
ProcessSessionInformation,
ProcessForegroundInformation,
ProcessWow64Information,
ProcessImageFileName,
ProcessLUIDDeviceMapsEnabled,
ProcessBreakOnTermination,
ProcessDebugObjectHandle,
ProcessDebugFlags,
ProcessHandleTracing,
ProcessIoPriority,
ProcessExecuteFlags,
ProcessTlsInformation,
ProcessCookie,
ProcessImageInformation,
ProcessCycleTime,
ProcessPagePriority,
ProcessInstrumentationCallback,
ProcessThreadStackAllocation,
ProcessWorkingSetWatchEx,
ProcessImageFileNameWin32,
ProcessImageFileMapping,
ProcessAffinityUpdateMode,
ProcessMemoryAllocationMode,
ProcessGroupInformation,
ProcessTokenVirtualizationEnabled,
ProcessConsoleHostProcess,
ProcessWindowInformation,
MaxProcessInfoClass
};
pub extern "ntdll" fn NtQueryInformationProcess(
ProcessHandle: HANDLE,
ProcessInformationClass: PROCESSINFOCLASS,
ProcessInformation: *anyopaque,
ProcessInformationLength: ULONG,
ReturnLength: ?*ULONG,
) callconv(WINAPI) NTSTATUS;
pub const THREADINFOCLASS = enum(c_int) {
ThreadBasicInformation,
ThreadTimes,