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사용하려면 WDK(Windows 드라이버 키트), 특히 TDI(전송 드라이버 인터페이스) 드라이버에 설명된 대로 Windows 드라이버 개발에 익숙해야 합니다.
편지 | 스탠드 포 | 코멘트 |
---|---|---|
"AT" | 주소 변환 | ARP(주소 확인 프로토콜)에서 제공하는 것과 같은 주소 확인입니다. |
"NL" | 네트워크 계층 | OSI(Open Systems Interconnection) 참조 모델에서와 같이. |
"TL" | 전송 계층 | OSI 참조 모델에서와 같이. |
"CL" | Connection-Less | 브로드캐스트 패킷을 기반으로 하는 연결 없는 프로토콜입니다. |
"CO" | 연결 | 지시된 패킷을 기반으로 하는 연결된 프로토콜입니다. |
"ER" | Echo 요청/회신 | Ping에서 TCP/IP 연결을 테스트하는 데 사용하는 패킷 유형입니다. |
"IF" | 인터페이스 | SNMP에서 사용되는 의미의 인터페이스입니다. |
- 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 함수는 이러한 배열을 검색하는 방법을 보여줍니다.
- 특정 TDI 엔터티에 대한 형식 정보를 가져옵니다.
입력 구조의 ID.toi_entity 멤버가 특정 엔터티를 식별하는 경우(위의 열거형 요청에서 반환된 TDIEntityID 구조의 경우와 같이) ID.toi_classINFO_CLASS_GENERIC, ID.toi_typeINFO_TYPE_PROVIDER, ENTITY_TYPE_IDID.toi_id 하나 이상의 플래그 값이 발생합니다. 는 lpOutBuffer 매개 변수가 가리키는 서명되지 않은 긴 반환됩니다. 이러한 플래그 값은 지정된 엔터티의 형식을 식별합니다. 다시 한 번 입력 구조의 Context 멤버는 무시됩니다.
반환할 수 있는 가능한 형식 플래그 값은 다음 표에 나와 있습니다.
기 | 중요성 |
---|---|
AT_ARP | 엔터티는 ARP(주소 확인 프로토콜)를 구현합니다. |
AT_NULL | 엔터티는 주소 변환을 수행하지 않습니다. |
CL_NL_IP | 엔터티는 네트워크 계층에서 연결이 없는 IP(인터넷 프로토콜)를 구현합니다. |
CL_NL_IPX | 엔터티는 네트워크 계층에서 연결 없이 IPX(Internetwork Packet Exchange 프로토콜)를 구현합니다. |
CL_TL_NBF | 엔터티는 전송 계층에서 연결이 없는 NBF(NetBEUI Frame 프로토콜)를 구현합니다. |
CL_TL_UDP | 엔터티는 전송 계층에서 UDP(사용자 데이터그램 프로토콜) 연결을 구현합니다. |
CO_TL_NBF | 엔터티는 전송 계층에서 NBF(NetBEUI Frame 프로토콜) 지시 패킷을 구현합니다. |
CO_TL_SPP | 엔터티는 전송 계층에서 SPP(시퀀스 패킷 프로토콜) 지시 패킷을 구현합니다. |
CO_TL_SPX | 엔터티는 전송 계층에서 SPX(시퀀스 패킷 교환 프로토콜) 지시 패킷을 구현합니다. |
CO_TL_TCP | 엔터티는 전송 계층에서 TCP(전송 제어 프로토콜) 지시 패킷을 구현합니다. |
ER_ICMP | 엔터티는 Echo Request/Reply에 대한 ICMP(인터넷 제어 메시지 프로토콜)를 구현합니다. |
IF_GENERIC | 엔터티는 제네릭 인터페이스를 구현합니다. |
IF_MIB | 엔터티는 SNMP MIB-II 지원을 사용하여 인터페이스를 구현합니다. |
- 인터페이스 엔터티에 대한 MIB-II 정보를 가져옵니다.
엔터티 형식이 IF_MIB 경우 MIB 요청을 전송하여 IFEntry 구조가 반환될 수 있습니다. 입력 구조의 ID.toi_entity 멤버를 설정하여 엔터티, INFO_CLASS_PROTOCOLID.toi_class, INFO_TYPE_PROVIDERID.toi_type 및 IF_MIB_STATS_IDID.toi_id 식별합니다.
IFEntry 가변 길이 구조이므로 출력 버퍼는 "sizeof(IFEntry)"가 아니라 "sizeof(IFEntry) + MAX_ADAPTER_DESCRIPTION_LENGTH + 1"로 할당되어야 합니다.
- 특정 IP 엔터티에 대한 MIB-II 정보를 가져옵니다.
엔터티를 식별하도록 ID.toi_entity 멤버, INFO_CLASS_PROTOCOLID.toi_class, INFO_TYPE_PROVIDERID.toi_type 및 IP_MIB_STATS_IDID.toi_id 설정하여 IP 엔터티(형식이 CL_NL_ENTITY)에서 MIB 정보를 검색할 수도 있습니다. 이 경우 IPSNMPInfo 구조가 반환되고 출력 버퍼를 "sizeof(IPSNMPInfo)"에 할당할 수 있습니다.
- 특정 IP 엔터티에 대한 주소 정보를 가져옵니다.
특정 IP 엔터티에 대해 반환된 IPSNMPInfo 구조체의 ipsi_numaddr 멤버가 0이 아니면 ID.toi_entity 멤버를 설정하여 IPAddrEntry 구조의 배열을 검색할 수 있습니다. ID.toi_classINFO_CLASS_PROTOCOLID.toi_typeINFO_TYPE_PROVIDER 및 IP_MIB_ADDRTABLE_ENTRY_IDID.toi_id . 이 경우 출력 버퍼를 할당하여 크기 배열을 보유해야 합니다.
sizeof(IPAddrEntry) * pIpSnmpInfoReturned->ipsi_numaddr
- 특정 IP 주소에 대한 인터페이스 정보를 가져옵니다.
위의 IPAddrEntry 배열에서 반환된 지정된 IP 주소에 대해 IP 엔터티를 식별하도록 ID.toi_entity 멤버 집합, INFO_CLASS_PROTOCOL설정된 ID.toi_class, ID.toi_typeINFO_TYPE_PROVIDER설정하여 추가 인터페이스 정보를 검색할 수 있습니다. 그런 다음 ID.toi_idIP_INTFC_INFO_ID 설정하고 TCP_REQUEST_QUERY_INFORMATION_EX 구조의 Context 멤버를 해당 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