IOCTL_TCP_QUERY_INFORMATION_EX IOCTL (tcpioctl.h)

[Questo codice di controllo può essere modificato o non disponibile nelle versioni future di Windows. Usare l'API helper del protocollo Internet anziché questo codice di controllo.

Recupera informazioni dal driver TCP/IP.

Per eseguire l'operazione di IOCTL_TCP_QUERY_INFORMATION_EX, chiamare la funzione DeviceIoControl con i parametri seguenti.

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

Osservazioni

Per usare IOCTL_TCP_QUERY_INFORMATION_EX, è necessario avere familiarità con Lo sviluppo di driver Windows, come documentato nella Windows Driver Kit (WDK)e in particolare con i driver TRANSPORT Driver Interface (TDI).

Nota Per usare questo codice di controllo, includere il file di intestazione Windows.h. Inoltre, in particolare, includono Tcpioctl.h, un file di intestazione pubblicato in Windows SDK per l'uso con IOCTL_TCP_QUERY_INFORMATION_EXe anche Tdiinfo.h e Tdistat.h, i file di intestazione pubblicati in WDK per lo sviluppo di driver TDI.
 
Nota Vari flag e altre costanti definite nel file di intestazione WDK Tdiinfo.h per l'operazione di IOCTL_TCP_QUERY_INFORMATION_EX usare la convenzione di denominazione seguente.
Lettere Stand per Commenti
"AT" Traduzione degli indirizzi Risoluzione degli indirizzi, ad esempio quella fornita da ARP (Address Resolution Protocol).
"NL" Livello di rete Come nel modello di riferimento OSI (Open Systems Interconnect).
"TL" Livello trasporto Come nel modello di riferimento OSI.
"CL" Connection-Less Protocollo senza connessione basato su pacchetti broadcast.
"CO" Connesso Protocollo connesso basato su pacchetti diretti.
"ER" Richiesta echo/risposta Tipi di pacchetti usati da Ping per testare la connettività TCP/IP.
"IF" Interfaccia Interfaccia nel senso usata in SNMP.
 
 
L'operazione IOCTL_TCP_QUERY_INFORMATION_EX recupera diversi tipi di informazioni, a seconda della struttura TCP_REQUEST_QUERY_INFORMATION_EX a cui punta il parametro lpInBuffer , come descritto nel paragrafo seguente e nel codice di esempio.
  1. Enumerare le entità TDI.

Per recuperare una matrice di strutture TDIEntityID che identifica tutte le entità TCP nel computer, impostare il membro ID.toi_entity.tei_entity della struttura di input su GENERIC_ENTITY. ID.toi_class deve quindi essere impostato su INFO_CLASS_GENERIC, ID.toi_type deve essere impostato su INFO_TYPE_PROVIDERe ID.toi_id deve essere impostato su ENTITY_LIST_IDoppure l'operazione non riesce con un codice di errore TDI_INVALID_PARAMETER. Il contesto membro della struttura di input viene ignorato quando viene richiesto un elenco. L'output in questo caso è una matrice di strutture TDIEntityID. La funzione GetEntityArray nel primo esempio di codice seguente illustra come recuperare tale matrice.

  1. Ottenere informazioni sul tipo su un'entità TDI specifica.

Se il membro ID.toi_entity della struttura di input identifica un'entità specifica (come nel caso delle strutture TDIEntityID restituite dalla richiesta di enumerazione precedente), impostando l'ID.toi_class su INFO_CLASS_GENERIC, l'ID.toi_type su INFO_TYPE_PROVIDERe l'ID.toi_id per ENTITY_TYPE_ID fa sì che uno o più valori di flag siano restituito in un unsigned long a cui punta il parametro lpOutBuffer . Questi valori flag identificano il tipo dell'entità specificata. Ancora una volta, il Context membro della struttura di input viene ignorato.

I possibili valori di flag di tipo che è possibile restituire sono illustrati nella tabella seguente.

Bandiera Significato
AT_ARP L'entità implementa ARP (Address Resolution Protocol).
AT_NULL L'entità non esegue la conversione degli indirizzi.
CL_NL_IP L'entità implementa l'indirizzo IP (Protocollo Internet), senza connessione nel livello di rete.
CL_NL_IPX L'entità implementa IPX (protocollo Internetwork Packet Exchange), senza connessione nel livello di rete.
CL_TL_NBF L'entità implementa il protocollo NBF (NetBEUI Frame Protocol), senza connessione nel livello di trasporto.
CL_TL_UDP L'entità implementa UDP (User Datagram Protocol) senza connessione nel livello di trasporto.
CO_TL_NBF L'entità implementa il protocollo NBF (NetBEUI Frame Protocol), i pacchetti diretti sul livello di trasporto.
CO_TL_SPP L'entità implementa SPP (Sequenced Packet Protocol), pacchetti diretti sul livello di trasporto.
CO_TL_SPX L'entità implementa SPX (sequenced packet exchange protocol), pacchetti diretti sul livello di trasporto.
CO_TL_TCP L'entità implementa TCP (Transmission Control Protocol), pacchetti diretti sul livello di trasporto.
ER_ICMP L'entità implementa ICMP (Internet Control Message Protocol) per Echo Request/Reply.
IF_GENERIC L'entità implementa un'interfaccia generica.
IF_MIB L'entità implementa un'interfaccia con il supporto MIB-II SNMP.
 
  1. Ottenere MIB-II informazioni su un'entità di interfaccia.

Se il tipo di entità è IF_MIB, è possibile inviare una richiesta MIB che restituisce una struttura IFEntry. Impostare il membro ID.toi_entity della struttura di input per identificare l'entità, il ID.toi_class su INFO_CLASS_PROTOCOL, l'ID.toi_type su INFO_TYPE_PROVIDERe l'ID.toi_id su IF_MIB_STATS_ID.

Si noti che poiché IFEntry è una struttura a lunghezza variabile, il buffer di output deve essere allocato non solo come "sizeof(IFEntry)" ma come "sizeof(IFEntry) + MAX_ADAPTER_DESCRIPTION_LENGTH + 1".

  1. Ottenere MIB-II informazioni su un'entità IP specifica.

Le informazioni MIB possono essere recuperate anche da un'entità IP (un il cui tipo è CL_NL_ENTITY) impostando il membro ID.toi_entity per identificare l'entità, il ID.toi_class su INFO_CLASS_PROTOCOL, l'ID.toi_type su INFO_TYPE_PROVIDERe l'ID.toi_id per IP_MIB_STATS_ID. In questo caso viene restituita una struttura IPSNMPInfo e il buffer di output può essere allocato a "sizeof(IPSNMPInfo)".

  1. Ottenere informazioni sull'indirizzo su un'entità IP specifica.

Se il membro ipsi_numaddr della struttura IPSNMPInfo restituita per una determinata entità IP è diverso da zero, è possibile recuperare una matrice di strutture IPAddrEntry impostando il membro ID.toi_entity per identificare l'entità, il ID.toi_class a INFO_CLASS_PROTOCOL, l'ID.toi_type a INFO_TYPE_PROVIDER, e il ID.toi_id per IP_MIB_ADDRTABLE_ENTRY_ID. In questo caso, il buffer di output deve essere allocato per contenere una matrice di dimensioni:

sizeof(IPAddrEntry) * pIpSnmpInfoReturned->ipsi_numaddr

  1. Ottenere informazioni sull'interfaccia su un indirizzo IP specifico.

È possibile recuperare altre informazioni sull'interfaccia per un determinato indirizzo IP restituito nella matrice IPAddrEntry precedente lasciando il membro ID.toi_entity impostato per identificare l'entità IP, il ID.toi_class impostato su INFO_CLASS_PROTOCOLe il ID.toi_type impostato su INFO_TYPE_PROVIDER, quindi impostando il ID.toi_id su IP_INTFC_INFO_ID e sul membro Context della struttura TCP_REQUEST_QUERY_INFORMATION_EX sull'indirizzo IPv4 o IPv6 in questione.

Allocare un buffer di output sufficientemente grande da contenere sizeof(IPINTERFACEINFO) + MAX_PHYSADDR_SIZE.

In caso di restituzione, il buffer di output contiene una struttura IPInterfaceInfo compilata .

Esempi

Nell'esempio seguente viene illustrato come ottenere un elenco delle entità presenti nella scheda TCP nel computer corrente.

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


Fabbisogno

Requisito Valore
intestazione tcpioctl.h

Vedere anche

DeviceIoControl

'API helper del protocollo Internet

informazioni di riferimento sulla gestione