NtDeviceIoControlFile – 获取缓冲区的大小

我使用IOCTL_TCP_QUERY_INFORMATION_EX控制代码调用NtDeviceIoControlFile ,但在执行实际调用之前,我需要获取输出缓冲区的大小,以便为其分配适当的大小。

这是我的代码:

  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) 。 正在使用SYNCHRONIZE标志设置打开TCP设备对象的句柄。

问题是为什么,在哪里?

 #include  #include  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(&ObjectName), OBJ_CASE_INSENSITIVE }; HANDLE hFile; IO_STATUS_BLOCK iosb; status = NtOpenFile(&hFile, SYNCHRONIZE, const_cast(&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