Share via


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.

Nota Para usar esse código de controle, inclua o arquivo de cabeçalho Windows.h. Além disso, inclua especificamente Tcpioctl.h, um arquivo de cabeçalho publicado no SDK do Windows para uso com IOCTL_TCP_QUERY_INFORMATION_EX e também Tdiinfo.h e Tdistat.h, arquivos de cabeçalho publicados no WDK para desenvolvimento de driver TDI.
 
Nota Vários sinalizadores e outras constantes definidas no arquivo de cabeçalho do WDK Tdiinfo.h para a operação de IOCTL_TCP_QUERY_INFORMATION_EX usam a convenção de nomenclatura a seguir.
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.
 
 
A operação IOCTL_TCP_QUERY_INFORMATION_EX recupera diferentes tipos de informações, dependendo do que a estrutura TCP_REQUEST_QUERY_INFORMATION_EX apontada pelo parâmetro lpInBuffer contém, conforme descrito no parágrafo e no código de exemplo a seguir.
  1. 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.

  1. 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.
 
  1. 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".

  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)".

  1. 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

  1. 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

DeviceIoControl

API auxiliar de protocolo da Internet

Referência de base de informações de gerenciamento