Freigeben über


IOCTL_TCP_QUERY_INFORMATION_EX IOCTL (tcpioctl.h)

[Dieser Steuerelementcode kann in zukünftigen Versionen von Windows geändert oder nicht verfügbar sein. Verwenden Sie die Internetprotokoll-Hilfs-API anstelle dieses Steuerelementcodes.]

Ruft Informationen vom TCP/IP-Treiber ab.

Rufen Sie zum Ausführen des IOCTL_TCP_QUERY_INFORMATION_EX Vorgangs die DeviceIoControl--Funktion mit den folgenden Parametern auf.

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

Bemerkungen

Um IOCTL_TCP_QUERY_INFORMATION_EXzu verwenden, sollten Sie mit der Entwicklung von Windows-Treibern vertraut sein, wie im Windows Driver Kit (WDK)und speziell mit TDI-Treibern (Transport Driver Interface) dokumentiert.

Hinweis Um diesen Steuerelementcode zu verwenden, schließen Sie die Windows.h-Headerdatei ein. Fügen Sie außerdem tcpioctl.h, eine im Windows SDK veröffentlichte Headerdatei für die Verwendung mit IOCTL_TCP_QUERY_INFORMATION_EXund auch Tdiinfo.h und Tdistat.h, Headerdateien ein, die in der WDK für die Entwicklung von TDI-Treibern veröffentlicht wurden.
 
Hinweis Verschiedene Flags und andere Konstanten, die in der WDK-Headerdatei Tdiinfo.h für den IOCTL_TCP_QUERY_INFORMATION_EX Vorgang definiert sind, verwenden die folgende Benennungskonvention.
Buchstaben Stand für Kommentare
"AT" Adressenübersetzung Adressauflösung, z. B. die von ARP (Address Resolution Protocol) bereitgestellt wird.
"NL" Vermittlungsschicht Wie im Open Systems Interconnection (OSI)-Referenzmodell.
"TL" Transportschicht Wie im OSI-Referenzmodell.
"CL" Connection-Less Ein verbindungsloses Protokoll, das auf Übertragungspaketen basiert.
"CO" Verbunden Ein verbundenes Protokoll basierend auf weitergeleiteten Paketen.
"ER" Echoanfrage/Antwort Pakettypen, die von Ping zum Testen der TCP/IP-Konnektivität verwendet werden.
"WENN" Schnittstelle Eine Schnittstelle im Sinne von SNMP.
 
 
Der IOCTL_TCP_QUERY_INFORMATION_EX-Vorgang ruft unterschiedliche Arten von Informationen ab, je nachdem, auf welche TCP_REQUEST_QUERY_INFORMATION_EX Struktur durch den lpInBuffer Parameter verweist, wie im folgenden Absatz und Beispielcode beschrieben.
  1. Aufzählen von TDI-Entitäten.

Um ein Array von TDIEntityID Strukturen abzurufen, die alle TCP-Entitäten auf dem Computer identifiziert, legen Sie das ID.toi_entity.tei_entity Member der Eingabestruktur auf GENERIC_ENTITYfest. ID.toi_class muss dann auf INFO_CLASS_GENERICfestgelegt sein, ID.toi_type muss auf INFO_TYPE_PROVIDERfestgelegt sein, und ID.toi_id muss auf ENTITY_LIST_IDfestgelegt werden, oder der Vorgang schlägt mit einem TDI_INVALID_PARAMETER Fehlercode fehl. Das Kontextelement der Eingabestruktur wird ignoriert, wenn eine Liste angefordert wird. Die Ausgabe in diesem Fall ist ein Array TDIEntityID- Strukturen. Die GetEntityArray--Funktion im ersten Codebeispiel unten zeigt, wie ein solches Array abgerufen wird.

  1. Abrufen von Typinformationen zu einer bestimmten TDI-Entität.

Wenn das ID.toi_entity Element der Eingabestruktur eine bestimmte Entität identifiziert (wie im Fall der TDIEntityID Strukturen, die von der oben angegebenen Enumerationsanforderung zurückgegeben werden), wird die ID.toi_class auf INFO_CLASS_GENERICfestgelegt, die ID.toi_type auf INFO_TYPE_PROVIDER, und die ID.toi_id, um ENTITY_TYPE_ID bewirkt, dass mindestens ein Flagwert zu ENTITY_TYPE_ID wird in eine nicht signierte lange zurückgegeben, auf die der lpOutBuffer-Parameter verweist. Diese Flagwerte identifizieren den Typ der angegebenen Entität. Erneut wird das Context Member der Eingabestruktur ignoriert.

Die möglichen Typkennzeichnungswerte, die zurückgegeben werden können, sind in der folgenden Tabelle aufgeführt.

Flagge Bedeutung
AT_ARP Die Entität implementiert ARP (Address Resolution Protocol).
AT_NULL Die Entität führt keine Adressübersetzung durch.
CL_NL_IP Die Entität implementiert IP (Internet Protocol), ohne Verbindung auf der Netzwerkebene.
CL_NL_IPX Entität implementiert IPX (Internetwork Packet Exchange-Protokoll), ohne Verbindung auf der Netzwerkebene.
CL_TL_NBF Entität implementiert NBF (NetBEUI Frame-Protokoll), verbindungslos auf der Transportschicht.
CL_TL_UDP Die Entität implementiert UDP (User Datagram Protocol) ohne Verbindung auf der Transportebene.
CO_TL_NBF Entität implementiert NBF (NetBEUI Frame-Protokoll), gerichtete Pakete auf der Transportebene.
CO_TL_SPP Die Entität implementiert SPP (Sequenced Packet Protocol), gerichtete Pakete auf der Transportebene.
CO_TL_SPX Entität implementiert SPX (Sequenced Packet Exchange-Protokoll), gerichtete Pakete auf der Transportebene.
CO_TL_TCP Die Entität implementiert TCP (Transmission Control Protocol), gerichtete Pakete auf der Transportebene.
ER_ICMP Die Entität implementiert ICMP (Internet Control Message Protocol) für Echo-Anforderung/Antwort.
IF_GENERIC Die Entität implementiert eine generische Schnittstelle.
IF_MIB Die Entität implementiert eine Schnittstelle mit SNMP MIB-II Unterstützung.
 
  1. Rufen Sie MIB-II Informationen zu einer Schnittstellenentität ab.

Wenn der Entitätstyp IF_MIB ist, kann eine MIB-Anforderung an sie gesendet werden, die zur Rückgabe einer IFEntry--Struktur führt. Legen Sie das ID.toi_entity Element der Eingabestruktur fest, um die Entität zu identifizieren, die ID.toi_class auf INFO_CLASS_PROTOCOL, die ID.toi_type auf INFO_TYPE_PROVIDERund die ID.toi_id auf IF_MIB_STATS_ID.

Beachten Sie, dass IFEntry- eine Struktur mit variabler Länge ist, sollte der Ausgabepuffer nicht nur als "sizeof(IFEntry)" sondern als "sizeof(IFEntry) + MAX_ADAPTER_DESCRIPTION_LENGTH + 1" zugewiesen werden.

  1. Rufen Sie MIB-II Informationen zu einer bestimmten IP-Entität ab.

MIB-Informationen können auch aus einer IP-Entität (einer, deren Typ CL_NL_ENTITYist) abgerufen werden, indem sie das ID.toi_entity Mitglied festlegen, um die Entität, die ID.toi_class zu INFO_CLASS_PROTOCOL, die ID.toi_type zu INFO_TYPE_PROVIDERund die ID.toi_id auf IP_MIB_STATS_IDfestzulegen. In diesem Fall wird eine IPSNMPInfo- Struktur zurückgegeben, und der Ausgabepuffer kann "sizeof(IPSNMPInfo)" zugeordnet werden.

  1. Abrufen von Adressinformationen zu einer bestimmten IP-Entität.

Wenn das ipsi_numaddr Element der IPSNMPInfo- Struktur, die für eine bestimmte IP-Entität zurückgegeben wird, ungleich Null ist, kann ein Array IPAddrEntry--Strukturen abgerufen werden, indem das ID.toi_entity-Element zum Identifizieren der Entität festgelegt wird, die ID.toi_class, die INFO_CLASS_PROTOCOL, die ID.toi_type auf INFO_TYPE_PROVIDER, und die ID.toi_id, um IP_MIB_ADDRTABLE_ENTRY_ID. In diesem Fall sollte der Ausgabepuffer zugewiesen werden, um ein Array von Größe zu enthalten:

sizeof(IPAddrEntry) * pIpSnmpInfoReturned->ipsi_numaddr

  1. Abrufen von Schnittstelleninformationen zu einer bestimmten IP-Adresse.

Weitere Schnittstelleninformationen können für eine bestimmte IP-Adresse abgerufen werden, die im IPAddrEntry Array oben zurückgegeben wird, indem sie den ID.toi_entity Membersatz verlassen, um die IP-Entität zu identifizieren, die ID.toi_class auf INFO_CLASS_PROTOCOLfestgelegt und die ID.toi_type auf INFO_TYPE_PROVIDERfestgelegt ist. und legen Sie dann die ID.toi_id auf IP_INTFC_INFO_ID und das Context Member der TCP_REQUEST_QUERY_INFORMATION_EX Struktur auf die betreffende IPv4- oder IPv6-Adresse fest.

Weisen Sie einen Ausgabepuffer groß genug zu, um sizeof(IPINTERFACEINFO) + MAX_PHYSADDR_SIZEzu enthalten.

Beim Zurückgeben enthält der Ausgabepuffer eine ausgefüllte IPInterfaceInfo- Struktur.

Beispiele

Das folgende Beispiel zeigt, wie Sie eine Liste der Entitäten abrufen, die auf dem TCP-Adapter auf dem aktuellen Computer vorhanden sind.

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


Anforderungen

Anforderung Wert
Header- tcpioctl.h

Siehe auch

DeviceIoControl-

Internetprotokoll-Hilfs-API

Verwaltungsinformationsbasisreferenz