You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WoW64环境下NtQuerySystemInformation的SystemSessionProcessInformation接口是否异常?

WoW64环境下NtQuerySystemInformation获取SystemSessionProcessInformation时ReturnLength始终为0的问题

问题背景

我通过NtQuerySystemInformation接口获取三类系统信息:SystemProcessInformation、SystemExtendedProcessInformation和SystemSessionProcessInformation。常规循环逻辑(检查STATUS_INFO_LENGTH_MISMATCH状态,根据ReturnLength返回值调整缓冲大小)在前两类信息的获取中运行正常,但针对SystemSessionProcessInformation时出现异常:

  • 该信息需通过SYSTEM_SESSION_PROCESS_INFORMATION结构的二级缓冲获取数据,微调后的逻辑在原生架构(32位进程运行在32位系统、64位进程运行在64位系统)下可正常工作;
  • 在WoW64环境(32位进程运行在64位系统)中,当返回STATUS_INFO_LENGTH_MISMATCH时,ReturnLength始终为0,导致常规的缓冲调整逻辑失效,只能通过持续增大缓冲大小直至函数返回STATUS_SUCCESS或非STATUS_INFO_LENGTH_MISMATCH状态。

想确认这是微软WoW64层的兼容性疏漏,还是我对接口的理解存在误区?

可复现代码

SYSTEM_SESSION_PROCESS_INFORMATION SessionInfo = { 0 };
SessionInfo.SessionId = 1;
NTSTATUS Status = STATUS_SUCCESS;
PVOID Info = NULL;
ULONG InfoLength = 0;
for (;;)
{
    Status = NtQuerySystemInformation(SystemSessionProcessInformation, &SessionInfo, sizeof(SessionInfo), &InfoLength);
    if (Status != STATUS_INFO_LENGTH_MISMATCH)
    {
        break;
    }
    // NOTE: InfoLength is always 0 here
    //       only workaround is to continually increase buffer size and try again
    //       e.g. InfoLength += 0x1000
    SessionInfo.Buffer = malloc(InfoLength);
    SessionInfo.SizeOfBuf = InfoLength;
}

原因分析

这属于WoW64层的兼容性疏漏,并非你的理解错误。

核心原因在于:SystemSessionProcessInformation这类依赖二级缓冲的信息类型,WoW64层在处理STATUS_INFO_LENGTH_MISMATCH返回时,没有正确将64位系统侧计算出的所需缓冲长度回传给32位进程的ReturnLength参数。而SystemProcessInformation、SystemExtendedProcessInformation这类直接返回单缓冲数据的信息类型,WoW64层的长度回传逻辑是正常的。

解决方案

既然无法依赖ReturnLength获取准确的所需缓冲大小,只能采用逐步扩容重试的方案:

  1. 初始设置一个合理的缓冲大小(如0x1000字节);
  2. 每次遇到STATUS_INFO_LENGTH_MISMATCH时,按固定增量(如0x1000或0x4000字节)增大缓冲;
  3. 循环直到函数返回STATUS_SUCCESS或非STATUS_INFO_LENGTH_MISMATCH的错误状态;
  4. 注意在循环中释放之前分配的旧缓冲,避免内存泄漏。

调整后的示例代码:

SYSTEM_SESSION_PROCESS_INFORMATION SessionInfo = { 0 };
SessionInfo.SessionId = 1;
NTSTATUS Status = STATUS_SUCCESS;
ULONG InfoLength = 0x1000; // 初始缓冲大小
PVOID OldBuffer = NULL;

for (;;)
{
    // 释放上一次分配的旧缓冲
    if (OldBuffer != NULL)
    {
        free(OldBuffer);
        OldBuffer = NULL;
    }

    SessionInfo.Buffer = malloc(InfoLength);
    SessionInfo.SizeOfBuf = InfoLength;
    OldBuffer = SessionInfo.Buffer;

    Status = NtQuerySystemInformation(SystemSessionProcessInformation, &SessionInfo, sizeof(SessionInfo), &InfoLength);
    if (Status != STATUS_INFO_LENGTH_MISMATCH)
    {
        break;
    }

    // 按固定增量扩容,可根据实际场景调整大小
    InfoLength += 0x1000;
}

// 使用完毕后释放缓冲
if (SessionInfo.Buffer != NULL)
{
    free(SessionInfo.Buffer);
}

内容的提问来源于stack exchange,提问作者Luke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 15:10:16