次の方法で共有


IOCTL_TCP_QUERY_INFORMATION_EX IOCTL (tcpioctl.h)

[このコントロール コードは、将来のバージョンの Windows で変更されたり使用できなくなったりする可能性があります。 このコントロール コードの代わりにインターネット プロトコル ヘルパー API を使用します。

TCP/IP ドライバーから情報を取得します。

IOCTL_TCP_QUERY_INFORMATION_EX 操作を実行するには、次のパラメーターを指定して DeviceIoControl 関数を呼び出します。

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

備考

IOCTL_TCP_QUERY_INFORMATION_EXを使用するには、「Windows Driver Kit (WDK)」に記載されているように、特にトランスポート ドライバー インターフェイス (TDI) ドライバーに関するページで説明されているように、Windows ドライバー開発について理解している必要があります。

このコントロール コードを使用するには、Windows.h ヘッダー ファイルを含めます。 さらに、特に Tcpioctl.h、IOCTL_TCP_QUERY_INFORMATION_EXで使用するために Windows SDK で公開されているヘッダー ファイル、Tdiinfo.h および Tdistat.h、TDI ドライバー開発用の WDK で発行されたヘッダー ファイルも含まれます。
 
IOCTL_TCP_QUERY_INFORMATION_EX 操作の Tdiinfo.h WDK ヘッダー ファイルで定義されているさまざまなフラグとその他の定数、次の名前付け規則を使用します。
文字 表す コメント
"AT" アドレス変換 ARP によって提供されるアドレス解決 (アドレス解決プロトコル) など。
"NL" ネットワーク レイヤー Open Systems Interconnection (OSI) リファレンス モデルと同様です。
"TL" トランスポート層 OSI 参照モデルと同様です。
"CL" Connection-Less ブロードキャスト パケットに基づくコネクションレス プロトコル。
"CO" 接続 ダイレクト パケットに基づく接続されたプロトコル。
"ER" エコー要求/応答 TCP/IP 接続をテストするために Ping によって使用されるパケットの種類。
"IF" インターフェイス SNMP で使用される意味でのインターフェイス。
 
 
IOCTL_TCP_QUERY_INFORMATION_EX 操作は、次の段落とコード例で説明するように、lpInBuffer パラメーターが指す TCP_REQUEST_QUERY_INFORMATION_EX 構造に応じて、さまざまな種類の情報を取得します。
  1. TDI エンティティを列挙します。

コンピューター上のすべての TCP エンティティを識別する TDIEntityID 構造体の配列を取得するには、入力構造体の ID.toi_entity.tei_entity メンバーを GENERIC_ENTITYに設定します。 ID.toi_classINFO_CLASS_GENERICに設定する必要があります。ID.toi_typeINFO_TYPE_PROVIDERに設定し、ID.toi_idENTITY_LIST_IDに設定する必要があります。または、TDI_INVALID_PARAMETERエラー コードで操作が失敗します。 リストが要求されると、入力構造体の Context メンバーは無視されます。 この場合の出力は、TDIEntityID 構造体の配列です。 次の最初のコード例の GetEntityArray 関数は、このような配列を取得する方法を示しています。

  1. 特定の TDI エンティティに関する型情報を取得します。

入力構造体の ID.toi_entity メンバーが特定のエンティティを識別する場合 (上記の列挙要求によって返された TDIEntityID 構造体の場合と同様)、ID.toi_classINFO_CLASS_GENERICに設定し、ID.toi_typeINFO_TYPE_PROVIDERし、ID.toi_idENTITY_TYPE_ID すると、1 つ以上のフラグ値が発生しますlpOutBuffer パラメーターが指す 符号なし long に返されます。 これらのフラグ値は、指定されたエンティティの型を識別します。 もう一度、入力構造体の Context メンバーは無視されます。

返すことができる型フラグ値を次の表に示します。

意味
AT_ARP エンティティは ARP (アドレス解決プロトコル) を実装します。
AT_NULL エンティティはアドレス変換を行いません。
CL_NL_IP エンティティは、ネットワーク層に接続なしの IP (インターネット プロトコル) を実装します。
CL_NL_IPX エンティティは、ネットワーク層に接続なしの IPX (Internetwork Packet Exchange プロトコル) を実装します。
CL_TL_NBF エンティティは、トランスポート層に接続なしの NBF (NetBEUI フレーム プロトコル) を実装します。
CL_TL_UDP エンティティは、トランスポート層に UDP (ユーザー データグラム プロトコル) コネクションレスを実装します。
CO_TL_NBF エンティティは NBF (NetBEUI フレーム プロトコル) を実装し、トランスポート層にパケットを転送します。
CO_TL_SPP エンティティは、SPP (シーケンス パケット プロトコル) を実装し、トランスポート層上のパケットを転送します。
CO_TL_SPX エンティティは、SPX (シーケンスパケット交換プロトコル) を実装し、トランスポート層上のパケットを転送します。
CO_TL_TCP エンティティは TCP (伝送制御プロトコル) を実装し、トランスポート層上のパケットを転送します。
ER_ICMP エンティティは、エコー要求/応答用の ICMP (インターネット制御メッセージ プロトコル) を実装します。
IF_GENERIC エンティティはジェネリック インターフェイスを実装します。
IF_MIB エンティティは、SNMP MIB-II サポートを持つインターフェイスを実装します。
 
  1. インターフェイス エンティティに関する MIB-II 情報を取得します。

エンティティ型がIF_MIB場合は、IFEntry 構造体が返される MIB 要求を送信できます。 エンティティを識別する入力構造体の ID.toi_entity メンバー、INFO_CLASS_PROTOCOLする ID.toi_classINFO_TYPE_PROVIDERID.toi_typeID.toi_idIF_MIB_STATS_IDに設定します。

IFEntry は可変長構造体であるため、出力バッファーは "sizeof(IFEntry)" としてだけでなく、"sizeof(IFEntry) + MAX_ADAPTER_DESCRIPTION_LENGTH + 1" として割り当てる必要があります。

  1. 特定の IP エンティティに関する MIB-II 情報を取得します。

MIB 情報は、エンティティを識別するように ID.toi_entity メンバーを設定し、ID.toi_classINFO_CLASS_PROTOCOLに設定し、ID.toi_typeINFO_TYPE_PROVIDERに、ID.toi_idIP_MIB_STATS_IDに設定することで、IP エンティティ (型が CL_NL_ENTITY) から取得することもできます。 この場合、IPSNMPInfo 構造体が返され、出力バッファーを "sizeof(IPSNMPInfo)" に割り当てることができます。

  1. 特定の IP エンティティに関するアドレス情報を取得します。

特定の IP エンティティに対して返される IPSNMPInfo 構造体の ipsi_numaddr メンバーが 0 以外の場合は、ID.toi_entity メンバーを設定してエンティティを識別し、ID.toi_classINFO_CLASS_PROTOCOLに設定することで、IPAddrEntry 構造体の配列を取得できます。ID.toi_typeINFO_TYPE_PROVIDERに設定します。 と IP_MIB_ADDRTABLE_ENTRY_IDする ID.toi_id。 この場合、サイズの配列を保持するために出力バッファーを割り当てる必要があります。

sizeof(IPAddrEntry) * pIpSnmpInfoReturned->ipsi_numaddr

  1. 特定の IP アドレスに関するインターフェイス情報を取得します。

上記の IPAddrEntry 配列で返された特定の IP アドレスに関するより多くのインターフェイス情報を取得するには、ID.toi_entity メンバーを設定して IP エンティティを識別し、ID.toi_classINFO_CLASS_PROTOCOLに設定し、ID.toi_typeINFO_TYPE_PROVIDERに設定します。 次に、ID.toi_idIP_INTFC_INFO_ID に設定し、TCP_REQUEST_QUERY_INFORMATION_EX 構造体の コンテキスト メンバーを問題の IPv4 または IPv6 アドレスに設定します。

sizeof(IPINTERFACEINFO) + MAX_PHYSADDR_SIZEを格納するのに十分な大きさの出力バッファーを割り当てます。

返された出力バッファーには、IPInterfaceInfo 構造体 埋め込まれています。

次の例は、現在のコンピューター上の TCP アダプターに存在するエンティティの一覧を取得する方法を示しています。

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


必要条件

要件 価値
ヘッダー tcpioctl.h

関連項目

DeviceIoControl の

インターネット プロトコル ヘルパー API

管理情報ベース リファレンス