NtDeviceIoControlFile - 获取缓冲区的大小 [英] NtDeviceIoControlFile - Getting size of buffer

查看:52
本文介绍了NtDeviceIoControlFile - 获取缓冲区的大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 IOCTL_TCP_QUERY_INFORMATION_EX 控制代码调用 NtDeviceIoControlFile,但在执行真正的调用之前,我需要获取输出缓冲区的大小,以便我可以分配适当的它的大小.

I am calling NtDeviceIoControlFile with the IOCTL_TCP_QUERY_INFORMATION_EX control code, but before performing the real call, I need to get the size of the output buffer so I can allocate an appropriate size for it.

这是我的代码:

    TCP_REQUEST_QUERY_INFORMATION_EX TcpRequestQuery;
    IO_STATUS_BLOCK StatusBlock;
    DWORD BufferSize = sizeof(TDIENTITYID) * 4096;

    memset(&TcpRequestQuery, 0, sizeof(TcpRequestQuery));
    TcpRequestQuery.ID.toi_class = 0x100;
    TcpRequestQuery.ID.toi_type = 0x100;
    TcpRequestQuery.ID.toi_id = 0;
    TcpRequestQuery.ID.toi_entity.tei_entity = 0;
    TcpRequestQuery.ID.toi_entity.tei_instance = 0;

    *EntityList = (TDIENTITYID *) GlobalAlloc (GMEM_ZEROINIT, BufferSize);
    NTSTATUS Status = NtDeviceIoControlFile(
        TcpFile, NULL, NULL, NULL, &IOBlock, IOCTL_TCP_QUERY_INFORMATION_EX,
        &TcpQueryInfo, sizeof(TcpQueryInfo), *EntityList, BufferSize);

    if (!NT_SUCCESS(Status))
        return Status;

    BufferSize = StatusBlock.uInformation;

问题是第一次调用 NtDeviceIoControlFile 返回 ERROR_INVALID_PARAMETER (87).正在打开 TCP 设备对象的句柄并设置 SYNCHRONIZE 标志.

The problem is that the first call to NtDeviceIoControlFile returns ERROR_INVALID_PARAMETER (87). The handle to the TCP device object is being opened with the SYNCHRONIZE flag set.

问题是为什么,在哪里?

Question is why, and where?

推荐答案

#include <tdiinfo.h>
#include <tcpioctl.h>

NTSTATUS QueryTcp()
{
    NTSTATUS status;
#ifndef _WIN64

    struct TCP_REQUEST_QUERY_INFORMATION_EX_WOW 
    {
        TDIObjectID     ID;                     // object ID to query.
        ULONG           pad;                    // ! for wow64 only - Context must be aligned on 8 byte in 64bit windows
        uchar           Context[CONTEXT_SIZE];  // multi-request context. Zeroed
    };

    PVOID Wow;
    status = NtQueryInformationProcess(NtCurrentProcess(), ProcessWow64Information, &Wow, sizeof(Wow), 0);
    if (0 > status)
    {
        return status;
    }
#endif

    static const UNICODE_STRING ObjectName = RTL_CONSTANT_STRING(L"\\device\\tcp");
    static const OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, const_cast<PUNICODE_STRING>(&ObjectName), OBJ_CASE_INSENSITIVE };

    HANDLE hFile;
    IO_STATUS_BLOCK iosb;
    status = NtOpenFile(&hFile, SYNCHRONIZE, 
        const_cast<POBJECT_ATTRIBUTES>(&oa), &iosb, FILE_SHARE_VALID_FLAGS, FILE_SYNCHRONOUS_IO_NONALERT);

    if (0 <= status)
    {
        PVOID InputBuffer;
        ULONG InputBufferLength;

#ifndef _WIN64
        if (Wow)
        {
            TCP_REQUEST_QUERY_INFORMATION_EX_WOW req = {
                { { GENERIC_ENTITY }, INFO_CLASS_GENERIC, INFO_TYPE_PROVIDER, ENTITY_LIST_ID }
            };

            InputBuffer = &req, InputBufferLength = sizeof(req);
        }
        else
#endif
        {
            TCP_REQUEST_QUERY_INFORMATION_EX req = {
                { { GENERIC_ENTITY }, INFO_CLASS_GENERIC, INFO_TYPE_PROVIDER, ENTITY_LIST_ID }
            };

            InputBuffer = &req, InputBufferLength = sizeof(req);
        }

        union {
            PVOID buf;
            TDIEntityID* pEntity;
        };

        volatile static UCHAR guz;

        PVOID stack = alloca(guz);

        ULONG cbAllocated = 0, cbNeed = 8 * sizeof(TDIEntityID);

        do 
        {
            if (cbAllocated < cbNeed)
            {
                cbAllocated = RtlPointerToOffset(buf = alloca(cbNeed - cbAllocated), stack);
            }

            if (0 <= (status = NtDeviceIoControlFile(hFile, 0, 0, 0, &iosb, 
                IOCTL_TCP_QUERY_INFORMATION_EX, InputBuffer, InputBufferLength, buf, cbAllocated)))
            {
                if (ULONG n = (ULONG)iosb.Information / sizeof(TDIEntityID))
                {
                    do 
                    {
                        DbgPrint("{ %08x, %08x }\n", pEntity->tei_entity, pEntity->tei_instance);
                    } while (pEntity++, --n);
                }
            }

            cbNeed += 8 * sizeof(TDIEntityID);

        } while (status == STATUS_BUFFER_OVERFLOW || status == STATUS_BUFFER_TOO_SMALL);

        NtClose(hFile);
    }

    return status;
}

和输出

{ 00000400, 00000000 }
{ 00000401, 00000000 }
{ 00000301, 00000000 }
{ 00000301, 00000001 }
{ 00000380, 00000000 }
{ 00000380, 00000001 }
{ 00000200, 00000015 }
{ 00000200, 00000014 }
{ 00000200, 00000013 }
{ 00000200, 00000012 }
{ 00000200, 00000011 }
{ 00000200, 00000010 }
{ 00000200, 0000000f }
{ 00000200, 0000000e }
{ 00000200, 0000000d }

然后我们可以从输出数组中获取具体的 TDIEntityID,将其复制到 TCP_REQUEST_QUERY_INFORMATION_EX 并对这个实体发出详细请求,如下所述 - https://msdn.microsoft.com/en-us/library/bb432313(v=vs.85).aspx

then we can get concrete TDIEntityID from output array, copy it to TCP_REQUEST_QUERY_INFORMATION_EX and make detail request on this entity, as described here - https://msdn.microsoft.com/en-us/library/bb432313(v=vs.85).aspx

这篇关于NtDeviceIoControlFile - 获取缓冲区的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆