C NtQuerySystemInformation返回24(错误\u错误\u长度)

C NtQuerySystemInformation返回24(错误\u错误\u长度),c,winapi,nt,C,Winapi,Nt,以下是我的功能: PVOID QuerySystemInformation(SYSTEMINFOCLASS SystemEnum) { DWORD MemorySize = NULL; NTSTATUS Status = NtQuerySystemInformation(SystemEnum, NULL, 0, &MemorySize); if (NT_SUCCESS(Status)) { PVOID Memory

以下是我的功能:

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;
    }
我将
SystemBasicInformation
传递给函数。在第一次调用
NtQuerySystemInformation
后,我得到一个错误。
RtlNtStatusToDosError(Status)
的结果是
24(ERROR\u BAD\u LENGTH)
。问题出在哪里?

只需删除即可

if (NT_SUCCESS(Status)) {
并将其替换为:

if(MemorySize){

似乎没有问题-使用零
SystemInformationLength
参数的调用会出现错误

MSDN说:

ReturnLength[输出,可选]-第四个参数

指向函数写入所请求信息的实际大小的位置的可选指针。如果该大小小于或等于SystemInformationLength参数,则函数将信息复制到SystemInformation缓冲区中否则,它将返回NTSTATUS错误代码,并以ReturnLength的形式返回接收请求信息所需的缓冲区大小。

因此,请检查DWORD MemorySize是否包含非零大小。

如果系统信息长度太小,无法容纳信息返回错误
状态信息长度不匹配
。(
RtlNtStatusToDosError(状态信息长度不匹配)=错误错误长度

需要了解一些SystemInformationClass返回众所周知的固定大小数据。例如系统基本信息

因此,您需要为这个固定的大小信息类执行下一步操作:

SYSTEM_BASIC_INFORMATION sbi;
NTSTATUS status = ZwQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), 0);
if (0 <= status)
{
    // do something
}
为什么在循环中?因为在系统返回给您接收请求信息所需的缓冲区大小之后,以及在您再次使用此缓冲区大小调用
ZwQuerySystemInformation
之前,所需的长度可能会发生变化

这个
SystemProcessInformation
的一个很好的例子,它获取了有关当前在系统中运行的所有进程和线程的信息。在系统返回给您所需的缓冲区大小后—新线程或进程可以在系统中启动—结果可能需要更大的缓冲区

我们可以通过以下方式查询此信息:

NTSTATUS QueryProcessInformation()
{
    NTSTATUS status;

    ULONG cb = 0x10000;

    do 
    {
        status = STATUS_INSUFFICIENT_RESOURCES;

        if (void* buf = new BYTE[cb])
        {
            if (0 <= (status = ZwQuerySystemInformation(SystemProcessInformation, buf, cb, &cb)))
            {
                union {
                    PVOID pv;
                    PBYTE pb;
                    PSYSTEM_PROCESS_INFORMATION pspi;
                };

                pv = buf;

                ULONG NextEntryOffset = 0;

                do 
                {
                    pb += NextEntryOffset;

                    DbgPrint("%p %wZ\n", pspi->UniqueProcessId, &pspi->ImageName);

                } while (NextEntryOffset = pspi->NextEntryOffset);
            }

            delete [] buf;
        }

    } while (status == STATUS_INFO_LENGTH_MISMATCH);

    return status;
}
NTSTATUS QueryProcessInformation()
{
非关税国家地位;
ULONG cb=0x10000;
做
{
状态=状态资源不足;
if(void*buf=新字节[cb])
{
if(0 UniqueProcessId,&pspi->ImageName);
}而(NexteryOffset=pspi->NexteryOffset);
}
删除[]buf;
}
}而(状态==状态信息长度不匹配);
返回状态;
}
或者,我们也可以在堆栈中使用累积分配(这仅适用于用户模式,在这种模式下,我们有巨大的堆栈大小)

NTSTATUS QueryProcessInformation2()
{
非关税国家地位;
联合{
pvoidbuf;
PBYTE-pb;
PSI系统、过程、信息;
};
ULONG cb=0,rcb=0x10000;
易挥发的乌恰尔古兹;
PVOID stack=alloca(guz);
做
{
如果(cbImageName);
}而(NexteryOffset=pspi->NexteryOffset);
}
}而(状态==状态信息长度不匹配);
返回状态;
}

ooh。好的,非常感谢!我真傻,没注意文档!现在在同一个函数中,在调用Allocate()之后,我得到了
0xc000005:Access违例读取位置0x4865764A
,是否有任何明显的说明这背后的原因?我只能猜测,因为我不知道您使用的是什么分配器以及错误发生的确切位置。您不能使用调试器吗?
所以请检查DWORD MemorySize
-否。需要准确检查返回的状态以确定要执行的操作。这是错误。所有有条件的
如果
必须仅基于返回状态,请不要破坏您自己的帖子。更糟糕的是,您似乎得到了多个有用的答案。
NTSTATUS QueryProcessInformation()
{
    NTSTATUS status;

    ULONG cb = 0x10000;

    do 
    {
        status = STATUS_INSUFFICIENT_RESOURCES;

        if (void* buf = new BYTE[cb])
        {
            if (0 <= (status = ZwQuerySystemInformation(SystemProcessInformation, buf, cb, &cb)))
            {
                union {
                    PVOID pv;
                    PBYTE pb;
                    PSYSTEM_PROCESS_INFORMATION pspi;
                };

                pv = buf;

                ULONG NextEntryOffset = 0;

                do 
                {
                    pb += NextEntryOffset;

                    DbgPrint("%p %wZ\n", pspi->UniqueProcessId, &pspi->ImageName);

                } while (NextEntryOffset = pspi->NextEntryOffset);
            }

            delete [] buf;
        }

    } while (status == STATUS_INFO_LENGTH_MISMATCH);

    return status;
}
NTSTATUS QueryProcessInformation2()
{
    NTSTATUS status;

    union {
        PVOID buf;
        PBYTE pb;
        PSYSTEM_PROCESS_INFORMATION pspi;
    };

    ULONG cb = 0, rcb = 0x10000;

    volatile UCHAR guz;

    PVOID stack = alloca(guz);

    do 
    {
        if (cb < rcb)
        {
            cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
        }

        if (0 <= (status = ZwQuerySystemInformation(SystemProcessInformation, buf, cb, &rcb)))
        {
            ULONG NextEntryOffset = 0;

            do 
            {
                pb += NextEntryOffset;

                DbgPrint("%p %wZ\n", pspi->UniqueProcessId, &pspi->ImageName);

            } while (NextEntryOffset = pspi->NextEntryOffset);
        }

    } while (status == STATUS_INFO_LENGTH_MISMATCH);

    return status;
}