While looking for ways to query specific information about a range of pages in windows I came across two solutions that were used commonly. However these two alternatives seem to return overlapping information.

VirtualQueryEx

Found on MSDN we see that it takes the parameters hProcess, lpAddress, lpBuffer and dwLength to query information for that range of pages. It returns this struct which tells us something about page state, protection and type. Oh well, so a good choice for querying page information right? But wait there is more!

QueryVirtualMemoryInformation

Also found on MSDN and does nearly the same thing. The difference is that it uses a DUMMYSTRUCTNAME and returns a memory structure that overlaps quite perfectly with the struct returned by VirtualQueryEx.

It seems like this could be an oversight and it doesn't matter which one to use. Maybe MS themselves don't even know why there are two overlapping variants inside a single OS. But for someone that does know: What's the difference here?

3

2 Answers

exist next NT api - NtQueryVirtualMemory

__kernel_entry NTSYSCALLAPI NTSTATUS NtQueryVirtualMemory( [in] HANDLE ProcessHandle, [in, optional] PVOID BaseAddress, [in] MEMORY_INFORMATION_CLASS MemoryInformationClass, [out] PVOID MemoryInformation, [in] SIZE_T MemoryInformationLength, [out, optional] PSIZE_T ReturnLength ); 

where MEMORY_INFORMATION_CLASS can have next values:

enum MEMORY_INFORMATION_CLASS { MemoryBasicInformation, // MEMORY_BASIC_INFORMATION MemoryWorkingSetInformation, // MEMORY_WORKING_SET_INFORMATION MemoryMappedFilenameInformation, // UNICODE_STRING MemoryRegionInformation, // MEMORY_REGION_INFORMATION MemoryWorkingSetExInformation, // MEMORY_WORKING_SET_EX_INFORMATION // since VISTA MemorySharedCommitInformation, // MEMORY_SHARED_COMMIT_INFORMATION // since WIN8 MemoryImageInformation, // MEMORY_IMAGE_INFORMATION MemoryRegionInformationEx, // MEMORY_REGION_INFORMATION MemoryPrivilegedBasicInformation, MemoryEnclaveImageInformation, // MEMORY_ENCLAVE_IMAGE_INFORMATION // since REDSTONE3 MemoryBasicInformationCapped, // 10 MemoryPhysicalContiguityInformation, // MEMORY_PHYSICAL_CONTIGUITY_INFORMATION // since 20H1 MemoryBadInformation, // since WIN11 MemoryBadInformationAllProcesses, // since 22H1 MaxMemoryInfoClass } ; 

both VirtualQueryEx and QueryVirtualMemoryInformation is thin shell over NtQueryVirtualMemory.

the VirtualQueryEx call NtQueryVirtualMemory with MemoryInformationClass = MemoryBasicInformation

SIZE_T WINAPI VirtualQueryEx( _In_ HANDLE hProcess, _In_opt_ LPCVOID VirtualAddress, _Out_writes_bytes_to_(dwLength,return) PMEMORY_BASIC_INFORMATION lpBuffer, _In_ SIZE_T dwLength ) { NTSTATUS status = NtQueryVirtualMemory(hProcess, VirtualAddress, MemoryBasicInformation, dwLength, &dwLength); if (0 > status) { RtlNtStatusToDosError(status); return 0; } return dwLength; } 

the QueryVirtualMemoryInformation call NtQueryVirtualMemory with MemoryInformationClass = MemoryRegionInformationEx. despite MemoryInformationClass parameter still exist, it accept only single value.

BOOL WINAPI QueryVirtualMemoryInformation( _In_ HANDLE Process, _In_ const VOID* VirtualAddress, _In_ WIN32_MEMORY_INFORMATION_CLASS MemoryInformationClass, _Out_writes_bytes_(MemoryInformationSize) PVOID MemoryInformation, _In_ SIZE_T MemoryInformationSize, _Out_opt_ PSIZE_T ReturnSize ) { NTSTATUS status = MemoryRegionInfo != MemoryInformationClass ? STATUS_INVALID_INFO_CLASS : NtQueryVirtualMemory(hProcess, VirtualAddress, MemoryRegionInformationEx, MemoryInformationSize, ReturnSize); if (0 > status) { RtlNtStatusToDosError(status); return FALSE; } return TRUE; } 

so because in both case the same NT api called internal - this 2 win32 api very similar.

1

VirtualQuery and VirtualQueryEx have existed since forever (NT v3.51).

QueryVirtualMemoryInformation is much newer (10 1607) and adds the information class parameter often seen in the NT API. This allows for future expansion. There is currently only one documented class value and the returned information is pretty similar to VirtualQueryEx but not exactly the same (BaseAddress, CommitSize etc).

DUMMYSTRUCTNAME is a compiler thing related to members without a name and has nothing to do with the actual data returned.

2

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.