IOCTL_TCP_QUERY_INFORMATION_EX IOCTL (tcpioctl.h)
[Esse código de controle pode ser alterado ou indisponível em versões futuras do Windows. Use a API auxiliar de protocolo de Internet em vez desse código de controle.]
Recupera informações do driver TCP/IP.
Para executar a operação IOCTL_TCP_QUERY_INFORMATION_EX , chame a função DeviceIoControl com os parâmetros a seguir.
BOOL DeviceIoControl(
(HANDLE) hDevice, // Open handle to the TCP driver
IOCTL_TCP_QUERY_INFORMATION_EX, // dwIoControlCode
NULL, // lpInBuffer (the output buffer is used for input too)
0, // nInBufferSize
(LPVOID) lpOutBuffer, // Pointer to the output buffer
(DWORD) nOutBufferSize, // Size of the output buffer
(LPDWORD) lpBytesReturned, // Number of bytes returned (if called synchronously)
(LPOVERLAPPED) lpOverlapped // OVERLAPPED structure (if called asynchronously)
);
Comentários
Para usar IOCTL_TCP_QUERY_INFORMATION_EX, você deve estar familiarizado com o Desenvolvimento de Driver do Windows, conforme documentado no WDK (Kit de Driver do Windows) e especificamente com drivers de TDI (Interface de Driver de Transporte). O WDK está disponível para download no site do MSDN.
Letras | Defender | Comentários |
---|---|---|
"AT" | Conversão de endereços | Resolução de endereços, como a fornecida pelo ARP (Protocolo de Resolução de Endereços). |
"NL" | Camada de rede | Como no modelo de referência OSI (Open Systems Interconnection). |
"TL" | Camada de transporte | Como no modelo de referência OSI. |
"CL" | Connection-Less | Um protocolo sem conexão baseado em pacotes de difusão. |
"CO" | Conectado | Um protocolo conectado com base em pacotes direcionados. |
"ER" | Solicitação/resposta de eco | Tipos de pacote usados pelo Ping para testar a conectividade TCP/IP. |
"SE" | Interface | Uma interface no sentido usado no SNMP. |
- Enumerar entidades TDI.
Para recuperar uma matriz de estruturas TDIEntityID que identifica todas as entidades TCP no computador, defina o membro ID.toi_entity.tei_entity da estrutura de entrada como GENERIC_ENTITY. ID.toi_class deve ser definido como INFO_CLASS_GENERIC, ID.toi_type deve ser definido como INFO_TYPE_PROVIDER e ID.toi_id deve ser definido como ENTITY_LIST_ID ou a operação falha com um código de erro TDI_INVALID_PARAMETER. O membro Context da estrutura de entrada é ignorado quando uma lista é solicitada. A saída nesse caso é uma matriz de estruturas TDIEntityID . A função GetEntityArray no primeiro exemplo de código abaixo mostra como recuperar essa matriz.
- Obter informações de tipo sobre uma entidade TDI específica.
Se o membro ID.toi_entity da estrutura de entrada identificar uma entidade específica (como no caso das estruturas TDIEntityID retornadas pela solicitação de enumeração acima), definir o ID.toi_class como INFO_CLASS_GENERIC, o ID.toi_type para INFO_TYPE_PROVIDER e o ID.toi_idpara ENTITY_TYPE_ID fará com que um ou mais valores de sinalizador sejam retornados em um longo sem sinal apontado pelo parâmetro lpOutBuffer . Esses valores de sinalizador identificam o tipo da entidade especificada. Mais uma vez, o membro Context da estrutura de entrada é ignorado.
Os possíveis valores de sinalizador de tipo que podem ser retornados são mostrados na tabela a seguir.
Sinalizador | Significado |
---|---|
AT_ARP | A entidade implementa o ARP (Protocolo de Resolução de Endereço). |
AT_NULL | A entidade não faz nenhuma tradução de endereço. |
CL_NL_IP | A entidade implementa IP (Protocolo de Internet), sem conexão na camada de rede. |
CL_NL_IPX | A entidade implementa o IPX (protocolo Internetwork Packet Exchange), sem conexão na camada de rede. |
CL_TL_NBF | A entidade implementa o NBF (protocolo NetBEUI Frame), sem conexão na camada de transporte. |
CL_TL_UDP | A entidade implementa udp (protocolo de datagrama de usuário) sem conexão na camada de transporte. |
CO_TL_NBF | A entidade implementa o NBF (protocolo NetBEUI Frame), pacotes direcionados na camada de transporte. |
CO_TL_SPP | A entidade implementa o SPP (Sequenced Packet Protocol), pacotes direcionados na camada de transporte. |
CO_TL_SPX | A entidade implementa o SPX (protocolo Sequenced Packet Exchange), pacotes direcionados na camada de transporte. |
CO_TL_TCP | A entidade implementa tcp (protocolo de controle de transmissão), pacotes direcionados na camada de transporte. |
ER_ICMP | A entidade implementa o ICMP (Protocolo de Mensagem de Controle da Internet) para Solicitação/Resposta de Eco. |
IF_GENERIC | A entidade implementa uma interface genérica. |
IF_MIB | A entidade implementa uma interface com suporte ao SNMP MIB-II. |
- Obtenha informações do MIB-II sobre uma entidade de interface.
Se o tipo de entidade for IF_MIB, uma solicitação MIB poderá ser enviada a ela que resulta no retorno de uma estrutura IFEntry . Defina o membro ID.toi_entity da estrutura de entrada para identificar a entidade, o ID.toi_class como INFO_CLASS_PROTOCOL, o ID.toi_type como INFO_TYPE_PROVIDER e o ID.toi_id para IF_MIB_STATS_ID.
Observe que, como IFEntry é uma estrutura de comprimento variável, o buffer de saída deve ser alocado não apenas como "sizeof(IFEntry)", mas como "sizeof(IFEntry) + MAX_ADAPTER_DESCRIPTION_LENGTH + 1".
- Obtenha informações do MIB-II sobre uma entidade DE IP específica.
As informações do MIB também podem ser recuperadas de uma entidade IP (cujo tipo é CL_NL_ENTITY) definindo o membro ID.toi_entity para identificar a entidade, o ID.toi_class para INFO_CLASS_PROTOCOL, o ID.toi_type para INFO_TYPE_PROVIDER e o ID.toi_id para IP_MIB_STATS_ID. Nesse caso, uma estrutura IPSNMPInfo é retornada e o buffer de saída pode ser alocado para "sizeof(IPSNMPInfo)".
- Obter informações de endereço sobre uma entidade DE IP específica.
Se o membro ipsi_numaddr da estrutura IPSNMPInfo retornado para uma entidade IP específica for diferente de zero, uma matriz de estruturas IPAddrEntry poderá ser recuperada definindo o membro ID.toi_entity para identificar a entidade, o ID.toi_class para INFO_CLASS_PROTOCOL, o ID.toi_type para INFO_TYPE_PROVIDER e o ID.toi_id para IP_MIB_ADDRTABLE_ENTRY_ID. Nesse caso, o buffer de saída deve ser alocado para conter uma matriz de tamanho:
sizeof(IPAddrEntry) * pIpSnmpInfoReturned->ipsi_numaddr
- Obter informações de interface sobre um endereço IP específico.
Mais informações de interface podem ser recuperadas para um determinado endereço IP retornado na matriz IPAddrEntry acima, deixando o membro ID.toi_entity definido para identificar a entidade IP, o ID.toi_class definido como INFO_CLASS_PROTOCOL e o ID.toi_type definido como INFO_TYPE_PROVIDER e, em seguida, definindo o ID.toi_id como IP_INTFC_INFO_ID e o membro Context do TCP_REQUEST_QUERY_INFORMATION_EX estrutura para o endereço IPv4 ou IPv6 em questão.
Aloque um buffer de saída grande o suficiente para conter sizeof(IPINTERFACEINFO) + MAX_PHYSADDR_SIZE
.
No retorno, o buffer de saída contém uma estrutura IPInterfaceInfo preenchida.
Exemplos
O exemplo a seguir mostra como obter uma lista das entidades presentes no adaptador TCP no computador atual.
#define UNICODE
#define _WIN32_WINNT 0x0500
#include <stdio.h>
#include <windows.h>
#include <iptypes.h>
#include "winternl.h"
#include "tdiinfo.h"
#include "tdistat.h"
#include "tcpioctl.h"
/* Function: GetTCPHandle
Description:
Opens a handle to the TCP driver
Parameters:
pTCPDriverHandle -- Pointer to a handle variable.
Return Value (DWORD): Returns TRUE if successful, and places
a valid handle to the TCP driver in the
handle pointed to by pTCPDriverHandle, or
returns FALSE otherwise, and sets the
handle to INVALID_HANDLE_VALUE.
*/
DWORD GetTCPHandle( PHANDLE pTCPDriverHandle )
{
#define FILE_OPEN_IF 0x00000003
#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020
#define OBJ_CASE_INSENSITIVE 0x00000040L
typedef NTSTATUS (NTAPI *P_NT_CREATE_FILE)(
OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER AllocationSize OPTIONAL,
IN ULONG FileAttributes,
IN ULONG ShareAccess,
IN ULONG CreateDisposition,
IN ULONG CreateOptions,
IN PVOID EaBuffer OPTIONAL,
IN ULONG EaLength );
HINSTANCE hNtDLL;
P_NT_CREATE_FILE pNtCreateFile;
NTSTATUS rVal;
WCHAR TCPDriverName[] = DD_TCP_DEVICE_NAME;
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK ioStatusBlock;
UNICODE_STRING UnicodeStr;
*pTCPDriverHandle = INVALID_HANDLE_VALUE;
if( ( hNtDLL = LoadLibrary( L"ntdll" ) ) == NULL )
return( FALSE );
pNtCreateFile = (P_NT_CREATE_FILE) GetProcAddress( hNtDLL,
"NtCreateFile" );
if( pNtCreateFile == NULL )
return( FALSE );
UnicodeStr.Buffer = TCPDriverName;
UnicodeStr.Length = (USHORT)(wcslen(TCPDriverName) * sizeof(WCHAR));
UnicodeStr.MaximumLength = UnicodeStr.Length + sizeof(UNICODE_NULL);
objectAttributes.Length = sizeof( OBJECT_ATTRIBUTES );
objectAttributes.ObjectName = &UnicodeStr;
objectAttributes.Attributes = OBJ_CASE_INSENSITIVE;
objectAttributes.RootDirectory = NULL;
objectAttributes.SecurityDescriptor = NULL;
objectAttributes.SecurityQualityOfService = NULL;
rVal = pNtCreateFile( pTCPDriverHandle,
SYNCHRONIZE | GENERIC_EXECUTE,
&objectAttributes,
&ioStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0 );
if( rVal < 0 )
{
printf( "\nFailed to create TCP Driver handle; NT status code = %d.", rVal );
*pTCPDriverHandle = INVALID_HANDLE_VALUE;
return( FALSE );
}
return( TRUE );
}
/* Function: GetEntityList
Description:
Allocates a buffer for and retrieves an array of TDIEntityID
structures that identifies the entities supported by
the TCP/IP device driver.
Parameters:
TCPDriverHandle -- An open handle to the TCP Driver; if
no such handle is available,
may be INVALID_HANDLE_VALUE.
lplpEntities -- Pointer to a buffer that contains
the array of TDIEntityID structures.
Must be freed by the calling process
using LocalFree( ).
Return Value:
DWORD -- the number of entity structures in the returned array
*/
DWORD GetEntityArray( IN HANDLE TCPDriverHandle,
OUT TDIEntityID **lplpEntities )
{
TCP_REQUEST_QUERY_INFORMATION_EX req;
DWORD arrayLen = sizeof(TDIEntityID) * MAX_TDI_ENTITIES;
DWORD bufferLen = arrayLen;
TDIEntityID * pEntity = NULL;
NTSTATUS status = TDI_SUCCESS;
DWORD temporaryHandle = 0;
int i;
// First, if the handle passed in is not valid, try to obtain one.
if( TCPDriverHandle == INVALID_HANDLE_VALUE )
{
if( GetTCPHandle( &TCPDriverHandle ) == FALSE )
{
*lplpEntities = NULL;
return( 0 );
}
temporaryHandle = TRUE;
}
// Next, set up the input structure for the IOCTL operation.
req.ID.toi_entity.tei_entity = GENERIC_ENTITY;
req.ID.toi_entity.tei_instance = 0;
req.ID.toi_class = INFO_CLASS_GENERIC;
req.ID.toi_type = INFO_TYPE_PROVIDER;
req.ID.toi_id = ENTITY_LIST_ID;
// The loop below is defensively engineered:
// (1) In the first place, it is unlikely that more
// than MAX_TDI_ENTITIES of TCP/IP entities exist,
// so the loop should execute only once.
// (2) Execution is limited to 4 iterations to rule out
// infinite looping in case of parameter corruption. Only 2
// iterations should ever be necessary unless entities are
// being added while the loop is running.
for( i = 0; i < 4; ++i )
{
if( pEntity != NULL )
{
LocalFree( pEntity );
pEntity = NULL;
bufferLen = arrayLen;
}
if( arrayLen == 0 )
break;
pEntity = (TDIEntityID *) LocalAlloc( LMEM_FIXED, bufferLen );
if( pEntity == NULL )
{
arrayLen = 0;
break;
}
if( !DeviceIoControl( TCPDriverHandle, // Handle to TCP driver
IOCTL_TCP_QUERY_INFORMATION_EX, // Cmd code
&req, // Pointer to input buffer
sizeof(req), // Size of ipt buffer
pEntity, // Ptr to output buffer
bufferLen, // Size of output buffer
&arrayLen, // Actual size of array
NULL ) )
status = GetLastError( );
// Even if the output buffer is too small, the TCP driver
// returns a status of TDI_SUCCESS; it is the value returned in
// arrayLen that indicates whether the entire array was
// successfully copied to the output buffer.
if( status == TDI_SUCCESS )
{
if( arrayLen && ( arrayLen <= bufferLen ) )
break;
}
else
arrayLen = 0;
}
if( temporaryHandle )
CloseHandle( TCPDriverHandle );
*lplpEntities = pEntity;
return( (DWORD)( arrayLen / sizeof(TDIEntityID) ) );
}
int main( )
{
DWORD i;
DWORD entityCount;
TDIEntityID
*entityArray,
*entityPtr;
if( !( entityCount = GetEntityArray( INVALID_HANDLE_VALUE,
&entityArray ) ) )
return( 1 );
entityPtr = entityArray;
printf( "\n\nList of %d Transport Driver Interface Entities on this machine:\n", entityCount );
for( i = 0; i < entityCount; ++i )
{
printf( "\n Entity #%d:\n Category (tei_entity) is ", i );
switch( entityPtr->tei_entity )
{
case GENERIC_ENTITY:
printf( "Generic." );
break;
case CL_NL_ENTITY:
printf( "Connectionless Network-Layer (CL_NL)" );
break;
case CO_NL_ENTITY:
printf( "Connected Network-Layer (CO_NL)" );
break;
case CL_TL_ENTITY:
printf( "Connectionless Transport-Layer (CL_TL)" );
break;
case CO_TL_ENTITY:
printf( "Connected Transport-Layer (CO_TL)" );
break;
case AT_ENTITY:
printf( "Address Translation (AT)" );
break;
case IF_ENTITY:
printf( "Interface (IF)" );
break;
case ER_ENTITY:
printf( "Echo Request/Response (ER)" );
break;
default:
printf( "[Unidentified Entity Type] = 0x%x",
entityPtr->tei_entity );
}
printf( "\n Instance (tei_instance) = %d\n",
entityPtr->tei_instance );
++entityPtr;
}
// Free the entity-array buffer before quitting.
LocalFree( entityArray );
return( 0 );
}
Requisitos
Requisito | Valor |
---|---|
Cabeçalho | tcpioctl.h |
Confira também
Comentários
https://aka.ms/ContentUserFeedback.
Em breve: Ao longo de 2024, eliminaremos os problemas do GitHub como o mecanismo de comentários para conteúdo e o substituiremos por um novo sistema de comentários. Para obter mais informações, consulteEnviar e exibir comentários de