Here is my function:
PVOID QuerySystemInformation(SYSTEMINFOCLASS SystemEnum) {
DWORD MemorySize = NULL;
NTSTATUS Status = NtQuerySystemInformation(SystemEnum, NULL, 0, &MemorySize);
if (NT_SUCCESS(Status)) {
PVOID Memory = PVOID(Allocate(MemorySize));
if (Memory != ERROR) {
Status = NtQuerySystemInformation(SystemEnum, Memory, MemorySize, &MemorySize);
if (NT_SUCCESS(Status)) {
return Memory;
}
Free(Memory);
}
}
return ERROR;
}
I pass SystemBasicInformation
to the function. After the first call to NtQuerySystemInformation
, I get an error. The result of RtlNtStatusToDosError(Status)
is 24 (ERROR_BAD_LENGTH)
. Where is the problem?
NtQuerySystemInformation
if SystemInformationLength too small for hold info return errorSTATUS_INFO_LENGTH_MISMATCH
. (RtlNtStatusToDosError(STATUS_INFO_LENGTH_MISMATCH)==ERROR_BAD_LENGTH
)need understand that some SystemInformationClass return well known fixed size data. as example SystemBasicInformation
so you need do next for this fixed size Information Class :
but some Information Class return variable length data. required length is unknown at begin and
STATUS_INFO_LENGTH_MISMATCH
here absolute normal error (not fatal). the variable length Information Class you need always query in loop and check returned status forSTATUS_INFO_LENGTH_MISMATCH
as conditional continue loop:why in loop ? because the required length can change after system return to you size of buffer required to receive the requested information and before you call
ZwQuerySystemInformation
again with this buffer size.the bright example of this
SystemProcessInformation
which got information about all processes and threads running currently in system. after system return to you size of buffer required - new threads or processes can start in system - as result larger buffer can be need.we can query this info in next way:
or alternatively we can use cumulative allocation in stack (this is only for user mode, where we have huge stack size)