Memory (Windows): prefers NQSI

This commit is contained in:
李通洲
2026-08-29 20:09:48 +08:00
parent b04587e0cb
commit 753ddec3c5
2 changed files with 75 additions and 12 deletions
+56
View File
@@ -11,6 +11,7 @@ enum {
SystemFirmwareTableInformation = 76,
SystemBootEnvironmentInformation = 90,
SystemLogicalProcessorAndGroupInformation = 107,
SystemBasicPerformanceInformation = 123,
SystemSecureBootInformation = 146,
};
@@ -198,6 +199,13 @@ typedef struct _SYSTEM_FIRMWARE_TABLE_INFORMATION {
_Field_size_bytes_(TableBufferLength) UCHAR TableBuffer[];
} SYSTEM_FIRMWARE_TABLE_INFORMATION, *PSYSTEM_FIRMWARE_TABLE_INFORMATION;
typedef struct _SYSTEM_BASIC_PERFORMANCE_INFORMATION {
SIZE_T AvailablePages;
SIZE_T CommittedPages;
SIZE_T CommitLimit;
SIZE_T PeakCommitment;
} SYSTEM_BASIC_PERFORMANCE_INFORMATION, *PSYSTEM_BASIC_PERFORMANCE_INFORMATION;
NTSYSAPI NTSTATUS NTAPI NtDelayExecution(_In_ BOOLEAN Alertable, _In_ PLARGE_INTEGER DelayInterval);
/**
@@ -599,6 +607,54 @@ typedef struct _KUSER_SHARED_DATA {
};
};
//
// Reserved padding field to preserve structure alignment and compatibility.
//
ULONG DataFlagsPad[1];
//
// Depending on the processor, the code for fast system call will differ,
// Stub code is provided pointers below to access the appropriate code.
//
// N.B. The following field is only used on 32-bit systems.
//
ULONGLONG TestRetInstruction;
//
// Query-performance counter (QPC) frequency, in counts per second.
//
// N.B. This value represents the fixed frequency of the system's high-resolution
// performance counter. It is used by user-mode time routines to convert QPC
// ticks into elapsed time without requiring a system call. The frequency is
// constant for the lifetime of the system and reflects the hardware or
// virtualized timer source selected by the kernel.
//
LONGLONG QpcFrequency;
//
// On AMD64, this value is initialized to a nonzero value if the system
// operates with an altered view of the system service call mechanism.
//
ULONG SystemCall;
//
// Reserved field - do not use. Used to be UserCetAvailableEnvironments.
//
ULONG Reserved2;
//
// Full 64 bit version of the number of physical pages in the system.
// This can dynamically change as physical memory can be added or removed
// from a running system.
//
ULONGLONG FullNumberOfPhysicalPages;
// ... more fields follow, but we don't need them
} KUSER_SHARED_DATA, *PKUSER_SHARED_DATA;
+19 -12
View File
@@ -1,19 +1,26 @@
#include "memory.h"
#include <windows.h>
#include "common/windows/nt.h"
const char* ffDetectMemory(FFMemoryResult* ram) {
MEMORYSTATUSEX statex = {
.dwLength = sizeof(statex),
};
// GlobalMemoryStatusEx() internally uses
// NtQuerySystemInformation(SystemBasicPerformanceInformation) in Win 7, and
// NtQuerySystemInformation(SystemMemoryUsageInformation) in Win 10
if (!GlobalMemoryStatusEx(&statex)) {
return "GlobalMemoryStatusEx() failed";
}
// Note: GlobalMemoryStatusEx() internally uses SystemMemoryUsageInformation in Win 10
ram->bytesTotal = statex.ullTotalPhys;
ram->bytesUsed = statex.ullTotalPhys - statex.ullAvailPhys;
SYSTEM_BASIC_PERFORMANCE_INFORMATION sbpi;
if (!NT_SUCCESS(NtQuerySystemInformation(SystemBasicPerformanceInformation, &sbpi, sizeof(sbpi), NULL)))
return "Failed to query memory information";
uint64_t phyPages =
#if _WIN64
SharedUserData->FullNumberOfPhysicalPages;
if (__builtin_expect(phyPages == 0, false)) { // Not supported on Windows 8.1
phyPages = SharedUserData->NumberOfPhysicalPages; // ULONG, maximum 16 TB
}
#else
SharedUserData->NumberOfPhysicalPages;
#endif
uint64_t pageSize = instance.state.platform.sysinfo.pageSize;
ram->bytesTotal = phyPages * pageSize;
ram->bytesUsed = (phyPages - sbpi.AvailablePages) * pageSize;
return nullptr;
}