Partager via


IOCTL_TCP_QUERY_INFORMATION_EX IOCTL (tcpioctl.h)

[Ce code de contrôle peut être modifié ou indisponible dans les futures versions de Windows. Utilisez l’API d’assistance de protocole Internet au lieu de ce code de contrôle.]

Récupère des informations à partir du pilote TCP/IP.

Pour effectuer l’opération IOCTL_TCP_QUERY_INFORMATION_EX, appelez la fonction DeviceIoControl avec les paramètres suivants.

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

Remarques

Pour utiliser IOCTL_TCP_QUERY_INFORMATION_EX, vous devez être familiarisé avec le développement de pilotes Windows, comme indiqué dans lekit de pilotes Windows (WDK) , et spécifiquement avec les pilotes TDI (Transport Driver Interface).

Remarque Pour utiliser ce code de contrôle, incluez le fichier d’en-tête Windows.h. En outre, incluez spécifiquement Tcpioctl.h, un fichier d’en-tête publié dans le Kit de développement logiciel (SDK) Windows à utiliser avec IOCTL_TCP_QUERY_INFORMATION_EX, ainsi que Tdiinfo.h et Tdistat.h, les fichiers d’en-tête publiés dans wdK pour le développement de pilotes TDI.
 
Remarque différents indicateurs et autres constantes définis dans le fichier d’en-tête WDK Tdiinfo.h pour l’opération de IOCTL_TCP_QUERY_INFORMATION_EX utilisez la convention d’affectation de noms suivante.
Lettres Stand for Commentaires
« AT » Traduction d’adresses Résolution d’adresses telle que celle fournie par ARP (Address Resolution Protocol).
« NL » Couche réseau Comme dans le modèle de référence OSI (Open Systems Interconnect).
« TL » Couche de transport Comme dans le modèle de référence OSI.
« CL » Connection-Less Protocole sans connexion basé sur les paquets de diffusion.
« CO » Relié Protocole connecté basé sur des paquets dirigés.
« ER » Demande d’écho/réponse Types de paquets utilisés par Ping pour tester la connectivité TCP/IP.
« IF » Interface Interface dans le sens utilisé dans SNMP.
 
 
L’opération de IOCTL_TCP_QUERY_INFORMATION_EX récupère différents types d’informations, selon la structure TCP_REQUEST_QUERY_INFORMATION_EX pointée par le paramètre lpInBuffer contient, comme décrit dans le paragraphe suivant et l’exemple de code.
  1. Énumérer les entités TDI.

Pour récupérer un tableau de structures TDIEntityID qui identifie toutes les entités TCP sur l’ordinateur, définissez le membre ID.toi_entity.tei_entity de la structure d’entrée sur GENERIC_ENTITY. ID.toi_class doit ensuite être défini sur INFO_CLASS_GENERIC, ID.toi_type doit être défini sur INFO_TYPE_PROVIDERet ID.toi_id doit être défini sur ENTITY_LIST_ID, ou l’opération échoue avec un code d’erreur TDI_INVALID_PARAMETER. Le Context membre de la structure d’entrée est ignoré lorsqu’une liste est demandée. La sortie dans ce cas est un tableau de structures TDIEntityID. La fonction GetEntityArray dans le premier exemple de code ci-dessous montre comment récupérer un tel tableau.

  1. Obtenez des informations de type sur une entité TDI spécifique.

Si le membre ID.toi_entity de la structure d’entrée identifie une entité spécifique (comme dans le cas de la TDIEntityID structures retournées par la demande d’énumération ci-dessus), définissez l'ID.toi_class sur INFO_CLASS_GENERIC, le ID.toi_type sur INFO_TYPE_PROVIDERet le ID.toi_idENTITY_TYPE_ID entraîne l’affectation d’une ou de plusieurs valeurs d’indicateur à une ou plusieurs valeurs d’indicateur. retourné dans un long non signé pointé par le paramètre lpOutBuffer. Ces valeurs d’indicateur identifient le type de l’entité spécifiée. Une fois de plus, le Context membre de la structure d’entrée est ignoré.

Les valeurs possibles d’indicateur de type qui peuvent être retournées sont indiquées dans le tableau suivant.

Drapeau Importance
AT_ARP Entity implémente ARP (Address Resolution Protocol).
AT_NULL L’entité ne fait aucune traduction d’adresse.
CL_NL_IP L’entité implémente IP (Protocole Internet), sans connexion sur la couche réseau.
CL_NL_IPX L’entité implémente IPX (protocole Internetwork Packet Exchange), sans connexion sur la couche réseau.
CL_TL_NBF Entity implémente le protocole NBF (NetBEUI Frame Protocol), sans connexion sur la couche de transport.
CL_TL_UDP Entity implémente UDP (User Datagram Protocol) sans connexion sur la couche de transport.
CO_TL_NBF L’entité implémente le protocole NBF (netBEUI Frame Protocol), les paquets dirigés sur la couche de transport.
CO_TL_SPP Entity implémente SPP (Sequenced Packet Protocol), des paquets dirigés sur la couche de transport.
CO_TL_SPX L’entité implémente SPX (protocole Sequenced Packet Exchange), dirigé les paquets sur la couche de transport.
CO_TL_TCP L’entité implémente TCP (Transmission Control Protocol), des paquets dirigés sur la couche de transport.
ER_ICMP L’entité implémente ICMP (Internet Control Message Protocol) pour echo Request/Reply.
IF_GENERIC L’entité implémente une interface générique.
IF_MIB L’entité implémente une interface avec la prise en charge des MIB-II SNMP.
 
  1. Obtenez MIB-II informations sur une entité d’interface.

Si le type d’entité est IF_MIB, une requête MIB peut être envoyée à celle-ci qui entraîne le retour d’une structure IFEntry. Définissez le membre ID.toi_entity de la structure d’entrée pour identifier l’entité, le ID.toi_class sur INFO_CLASS_PROTOCOL, le ID.toi_type sur INFO_TYPE_PROVIDERet le ID.toi_id sur IF_MIB_STATS_ID.

Notez que, étant donné que IFEntry est une structure de longueur variable, la mémoire tampon de sortie doit être allouée non seulement comme « sizeof(IFEntry) » mais comme « sizeof(IFEntry) + MAX_ADAPTER_DESCRIPTION_LENGTH + 1 ».

  1. Obtenez MIB-II informations sur une entité IP particulière.

Les informations MIB peuvent également être récupérées à partir d’une entité IP (dont le type est CL_NL_ENTITY) en définissant le membre ID.toi_entity pour identifier l’entité, le ID.toi_class sur INFO_CLASS_PROTOCOL, le ID.toi_type sur INFO_TYPE_PROVIDERet le ID.toi_id sur IP_MIB_STATS_ID. Dans ce cas, une structure IPSNMPInfo est retournée et la mémoire tampon de sortie peut être allouée à « sizeof(IPSNMPInfo) ».

  1. Obtenez des informations d’adresse sur une entité IP particulière.

Si le membre ipsi_numaddr de l'IPSNMPInfo structure retournée pour une entité IP particulière n’est pas zéro, un tableau de structures IPAddrEntry peut être récupéré en définissant le membre ID.toi_entity pour identifier l’entité, le ID.toi_class sur INFO_CLASS_PROTOCOL, le ID.toi_type à INFO_TYPE_PROVIDER, et le ID.toi_id à IP_MIB_ADDRTABLE_ENTRY_ID. Dans ce cas, la mémoire tampon de sortie doit être allouée pour contenir un tableau de taille :

sizeof(IPAddrEntry) * pIpSnmpInfoReturned->ipsi_numaddr

  1. Obtenir des informations d’interface sur une adresse IP particulière.

Vous pouvez récupérer d’autres informations d’interface pour une adresse IP donnée retournée dans le tableau IPAddrEntry ci-dessus en laissant le membre ID.toi_entity défini pour identifier l’entité IP, le ID.toi_class défini sur INFO_CLASS_PROTOCOLet le ID.toi_type défini sur INFO_TYPE_PROVIDER, puis en définissant le ID.toi_id sur IP_INTFC_INFO_ID et le membre Context de la structure TCP_REQUEST_QUERY_INFORMATION_EX sur l’adresse IPv4 ou IPv6 en question.

Allouez une mémoire tampon de sortie suffisamment grande pour contenir sizeof(IPINTERFACEINFO) + MAX_PHYSADDR_SIZE.

Lors du retour, la mémoire tampon de sortie contient une structure IPInterfaceInfo.

Exemples

L’exemple suivant montre comment obtenir une liste des entités présentes sur l’adaptateur TCP sur l’ordinateur actuel.

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


Exigences

Exigence Valeur
d’en-tête tcpioctl.h

Voir aussi

DeviceIoControl

API d’assistance de protocole Internet

Informations de référence sur la base d’informations de gestion