Compartir a través de


IOCTL_TCP_QUERY_INFORMATION_EX IOCTL (tcpioctl.h)

[Este código de control puede modificarse o no estar disponible en versiones futuras de Windows. Use la API auxiliar de protocolo de Internet en lugar de este código de control.

Recupera información del controlador TCP/IP.

Para realizar la operación de IOCTL_TCP_QUERY_INFORMATION_EX, llame a la función DeviceIoControl con los parámetros siguientes.

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)
);

Observaciones

Para usar IOCTL_TCP_QUERY_INFORMATION_EX, debe estar familiarizado con el desarrollo de controladores de Windows, como se documenta en laWindows Driver Kit (WDK) y específicamente con controladores de interfaz de controlador de transporte (TDI).

Nota Para usar este código de control, incluya el archivo de encabezado Windows.h. Además, incluye específicamente Tcpioctl.h, un archivo de encabezado publicado en Windows SDK para su uso con IOCTL_TCP_QUERY_INFORMATION_EX, y también Tdiinfo.h y Tdistat.h, archivos de encabezado publicados en WDK para el desarrollo de controladores TDI.
 
Nota Varias marcas y otras constantes definidas en el archivo de encabezado Tdiinfo.h WDK para la operación de IOCTL_TCP_QUERY_INFORMATION_EX usan la siguiente convención de nomenclatura.
Letras Representar Comentarios
"AT" Traducción de direcciones Resolución de direcciones, como la proporcionada por ARP (Protocolo de resolución de direcciones).
"NL" Capa de red Como en el modelo de referencia de interconexión de sistemas abiertos (OSI).
"TL" Capa de transporte Como en el modelo de referencia de OSI.
"CL" Connection-Less Un protocolo sin conexión basado en paquetes de difusión.
"CO" Conexo Un protocolo conectado basado en paquetes dirigidos.
"ER" Solicitud de eco/respuesta Tipos de paquetes usados por Ping para probar la conectividad TCP/IP.
"IF" Interfaz Interfaz en el sentido usado en SNMP.
 
 
La operación IOCTL_TCP_QUERY_INFORMATION_EX recupera diferentes tipos de información, en función de la estructura TCP_REQUEST_QUERY_INFORMATION_EX a la que apunta el parámetro lpInBuffer, tal como se describe en el siguiente párrafo y código de ejemplo.
  1. Enumerar entidades TDI.

Para recuperar una matriz de TDIEntityID estructuras que identifican todas las entidades TCP del equipo, establezca el miembro ID.toi_entity.tei_entity de la estructura de entrada en GENERIC_ENTITY. ID.toi_class debe establecerse en INFO_CLASS_GENERIC, ID.toi_type debe establecerse en INFO_TYPE_PROVIDERy ID.toi_id debe establecerse en ENTITY_LIST_IDo se produce un error en la operación con un código de error TDI_INVALID_PARAMETER. El context miembro de la estructura de entrada se omite cuando se solicita una lista. El resultado en este caso es una matriz de estructuras de TDIEntityID. La función GetEntityArray en el primer ejemplo de código siguiente muestra cómo recuperar dicha matriz.

  1. Obtenga información de tipo sobre una entidad TDI específica.

Si el miembro ID.toi_entity de la estructura de entrada identifica una entidad específica (como en el caso de las estructuras de TDIEntityID devueltas por la solicitud de enumeración anterior), establezca el ID.toi_class en INFO_CLASS_GENERIC, el ID.toi_type en INFO_TYPE_PROVIDERy el ID.toi_id en ENTITY_TYPE_ID hace que uno o varios valores de marca sean devuelto en un largo sin signo al que apunta el parámetro lpOutBuffer. Estos valores de marca identifican el tipo de la entidad especificada. Una vez más, se omite el context miembro de la estructura de entrada.

Los posibles valores de marca de tipo que se pueden devolver se muestran en la tabla siguiente.

Bandera Importancia
AT_ARP La entidad implementa ARP (Protocolo de resolución de direcciones).
AT_NULL La entidad no realiza ninguna traducción de direcciones.
CL_NL_IP La entidad implementa IP (Protocolo de Internet), sin conexión en la capa de red.
CL_NL_IPX La entidad implementa IPX (protocolo internetwork Packet Exchange), sin conexión en la capa de red.
CL_TL_NBF La entidad implementa NBF (protocolo NetBEUI Frame), sin conexión en la capa de transporte.
CL_TL_UDP La entidad implementa UDP (protocolo de datagramas de usuario) sin conexión en la capa de transporte.
CO_TL_NBF La entidad implementa NBF (protocolo NetBEUI Frame), paquetes dirigidos en la capa de transporte.
CO_TL_SPP La entidad implementa SPP (protocolo de paquetes secuenciados), paquetes dirigidos en la capa de transporte.
CO_TL_SPX La entidad implementa SPX (protocolo de intercambio de paquetes secuenciados), paquetes dirigidos en la capa de transporte.
CO_TL_TCP La entidad implementa TCP (Protocolo de control de transmisión), paquetes dirigidos en la capa de transporte.
ER_ICMP La entidad implementa ICMP (Protocolo de mensajes de control de Internet) para la solicitud de eco/respuesta.
IF_GENERIC La entidad implementa una interfaz genérica.
IF_MIB La entidad implementa una interfaz con compatibilidad con SNMP MIB-II.
 
  1. Obtenga MIB-II información sobre una entidad de interfaz.

Si el tipo de entidad es IF_MIB, se puede enviar una solicitud MIB a ella que da como resultado la devolución de una estructura de IFEntry. Establezca el miembro ID.toi_entity de la estructura de entrada para identificar la entidad, el ID.toi_class en INFO_CLASS_PROTOCOL, el ID.toi_type en INFO_TYPE_PROVIDERy el ID.toi_id en IF_MIB_STATS_ID.

Tenga en cuenta que, dado que IFEntry es una estructura de longitud variable, el búfer de salida debe asignarse no solo como "sizeof(IFEntry)", sino como "sizeof(IFEntry) + MAX_ADAPTER_DESCRIPTION_LENGTH + 1".

  1. Obtenga MIB-II información sobre una entidad IP determinada.

La información de MIB también se puede recuperar de una entidad IP (uno cuyo tipo es CL_NL_ENTITY) estableciendo el miembro ID.toi_entity para identificar la entidad, el ID.toi_class en INFO_CLASS_PROTOCOL, el ID.toi_type en INFO_TYPE_PROVIDERy el ID.toi_id en IP_MIB_STATS_ID. En este caso, se devuelve una estructura de IPSNMPInfo y el búfer de salida se puede asignar a "sizeof(IPSNMPInfo)".

  1. Obtenga información de dirección sobre una entidad IP determinada.

Si el miembro ipsi_numaddr de la estructura de IPSNMPInfo devuelta para una entidad IP determinada es distinto de cero, se puede recuperar una matriz de estructuras IPAddrEntry estableciendo el miembro ID.toi_entity para identificar la entidad, el ID.toi_class en INFO_CLASS_PROTOCOL, el ID.toi_type en INFO_TYPE_PROVIDER, y el ID.toi_id para IP_MIB_ADDRTABLE_ENTRY_ID. En este caso, el búfer de salida debe asignarse para contener una matriz de tamaño:

sizeof(IPAddrEntry) * pIpSnmpInfoReturned->ipsi_numaddr

  1. Obtenga información de interfaz sobre una dirección IP determinada.

Se puede recuperar más información de interfaz para una dirección IP determinada devuelta en la matriz de IPAddrEntry anterior dejando el miembro de ID.toi_entity establecido para identificar la entidad IP, el ID.toi_class establecido en INFO_CLASS_PROTOCOLy el ID.toi_type establecido en INFO_TYPE_PROVIDER, y, después, establezca el ID.toi_id en IP_INTFC_INFO_ID y el miembro Context de la estructura de TCP_REQUEST_QUERY_INFORMATION_EX en la dirección IPv4 o IPv6 en cuestión.

Asigne un búfer de salida lo suficientemente grande como para contener sizeof(IPINTERFACEINFO) + MAX_PHYSADDR_SIZE.

A cambio, el búfer de salida contiene una estructura IPInterfaceInfo rellenada.

Ejemplos

En el ejemplo siguiente se muestra cómo obtener una lista de las entidades presentes en el adaptador TCP en la máquina actual.

#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
encabezado de tcpioctl.h

Consulte también

DeviceIoControl

api auxiliar de protocolo de Internet de

referencia base de información de administración de