DisableMediaSense 함수(iphlpapi.h)
DisableMediaSense 함수는 로컬 컴퓨터에서 TCP/IP 스택의 미디어 감지 기능을 사용하지 않도록 설정합니다.
구문
IPHLPAPI_DLL_LINKAGE DWORD DisableMediaSense(
HANDLE *pHandle,
OVERLAPPED *pOverLapped
);
매개 변수
pHandle
핸들을 저장하는 데 사용되는 변수에 대한 포인터입니다. pOverlapped 매개 변수가 NULL이 아닌 경우 이 변수는 내부적으로 IP 드라이버를 호출하고 미디어 감지 기능을 사용하지 않도록 설정하는 데 필요한 핸들을 저장하는 데 사용됩니다.
애플리케이션은 이 변수가 가리키는 값을 사용하면 안 됩니다. 이 핸들은 내부용이므로 닫아서는 안 됩니다.
pOverLapped
OVERLAPPED 구조에 대한 포인터입니다. hEvent 멤버를 제외하고 이 구조체의 모든 멤버를 0으로 설정해야 합니다. hEvent 멤버에는 유효한 이벤트 개체에 대한 핸들이 필요합니다. CreateEvent 함수를 사용하여 이 이벤트 개체를 만듭니다.
반환 값
함수가 성공하면 반환 값이 NO_ERROR.
함수가 실패하면 반환 값은 다음 오류 코드 중 하나입니다.
반환 코드 | 설명 |
---|---|
|
잘못된 매개 변수가 함수에 전달되었습니다. pOverlapped 매개 변수가 잘못된 포인터인 경우 이 오류가 반환됩니다. |
|
작업이 진행 중입니다. 이 값은 DisableMediaSense에 대한 성공적인 비동기 호출에 의해 반환됩니다. |
|
pHandle 매개 변수가 가리키는 핸들이 잘못되었습니다. |
|
요청이 지원되지 않습니다. |
|
FormatMessage를 사용하여 반환된 오류에 대한 메시지 문자열을 가져옵니다. |
설명
pHandle 또는 pOverlapped 매개 변수가 NULL이면 DisableMediaSense 함수가 동기적으로 실행됩니다.
pHandle 및 pOverlapped 매개 변수가 모두 NULL이 아닌 경우 DisableMediaSense 함수는 pOverlapped 매개 변수가 가리키는 OVERLAPPED 구조를 사용하여 비동기적으로 실행됩니다.
DisableMediaSense 함수는 나중에 미디어 감지 기능을 복원하기 위해 RestoreMediaSense 함수가 호출될 때까지 완료되지 않습니다. 그때까지 IRP(I/O 요청 패킷)는 큐에 대기 상태로 유지됩니다. 또는 DisableMediaSense 라는 프로세스가 종료되면 IRP가 취소되고 미디어 감지 기능을 다시 복원하는 취소 루틴이 호출됩니다.
DisableMediaSense를 동기적으로 호출하려면 애플리케이션이 이 호출에 대해 별도의 스레드를 만들어야 합니다. 그렇지 않으면 IRP 완료를 계속 기다리며 함수가 차단됩니다.
DisableMediaSense를 비동기적으로 호출하려면 애플리케이션에서 OVERLAPPED 구조를 할당해야 합니다. hEvent 멤버를 제외하고 이 구조체의 모든 멤버를 0으로 설정해야 합니다. hEvent 멤버에는 유효한 이벤트 개체에 대한 핸들이 필요합니다. CreateEvent 함수를 사용하여 이 이벤트를 만듭니다. 비동기적으로 호출되는 경우 DisableMediaSense는 항상 ERROR_IO_PENDING 반환합니다. IRP는 RestoreMediaSense 가 나중에 호출될 때만 완료됩니다. CloseHandle 함수를 사용하여 더 이상 필요하지 않은 경우 이벤트 개체에 대한 핸들을 닫습니다. 시스템은 프로세스가 종료되면 핸들을 자동으로 닫습니다. 이벤트 개체는 마지막 핸들이 닫혔을 때 제거됩니다.
Windows Server 2003 및 Windows XP에서 TCP/IP 스택은 기본 네트워크 인터페이스에서 미디어 센스 연결 끊기 이벤트에 대응하여 인터페이스의 모든 IP 주소를 삭제하는 정책을 구현합니다. 로컬 컴퓨터가 연결된 네트워크 스위치 또는 허브의 전원이 꺼져 있거나 네트워크 케이블의 연결이 끊어진 경우 네트워크 인터페이스는 연결 끊김 이벤트를 제공합니다. 네트워크 인터페이스와 연결된 IP 구성 정보가 손실됩니다. 따라서 TCP/IP 스택은 연결이 끊긴 인터페이스를 숨기는 정책을 구현하므로 이러한 인터페이스와 연결된 IP 주소가 IP 도우미를 통해 검색된 구성 정보에 표시되지 않습니다. 이 정책을 사용하면 일부 애플리케이션에서 네트워크 인터페이스가 시스템에서 제거되지 않고 연결이 끊어지는 것을 쉽게 감지할 수 없습니다.
IP 구성 정보를 위해 DHCP 서버에 대한 DHCP 요청을 사용하는 경우 이 동작은 일반적으로 로컬 클라이언트 컴퓨터에 영향을 주지 않습니다. 그러나 서버 컴퓨터, 특히 클러스터의 일부로 사용되는 컴퓨터에 심각한 영향을 미칠 수 있습니다. DisableMediaSense 함수를 사용하여 이러한 경우 미디어 감지 기능을 일시적으로 사용하지 않도록 설정할 수 있습니다. 나중에 미디어 감지 기능을 복원하기 위해 RestoreMediaSense 함수가 호출됩니다.
다음 레지스트리 설정은 DisableMediaSense 및 RestoreMediaSense 함수와 관련이 있습니다.
시스템\CurrentControlSet\서비스\Tcpip\매개 변수\DisableDHCPMediaSense
Windows에는 컴퓨터가 처음 부팅할 때 이 레지스트리 키가 있는 경우 설정되는 내부 플래그가 있습니다. DisableMediaSense 및 RestoreMediaSense를 호출하여 동일한 내부 플래그도 설정되고 다시 설정됩니다. 그러나 레지스트리 설정을 사용하면 변경이 수행되려면 컴퓨터를 다시 부팅해야 합니다.
연결 끊기 이벤트가 발생할 때 연결이 끊긴 인터페이스를 숨기지 않도록 Windows Vista 이상에서 TCP/IP 스택이 변경되었습니다. 따라서 Windows Vista 이상에서는 DisableMediaSense 및 RestoreMediaSense 함수가 아무 작업도 수행하지 않으며 항상 NO_ERROR 반환합니다.
예제
다음 예제에서는 DisableMediaSense 및 RestoreMediaSense 함수를 비동기적으로 호출하는 방법을 보여 줍니다. 이 샘플은 DisableMediaSense 및 RestoreMediaSense 함수가 유용한 작업을 수행하는 Windows Server 2003 및 Windows XP에서만 유용합니다.
샘플은 먼저 DisableMediaSense 함수를 호출하고, 사용자가 네트워크 케이블의 연결을 끊을 수 있도록 60초 동안 절전 모드로 이동하고, IP 주소 테이블을 검색하고, 테이블에 있는 IP 주소 항목의 일부 멤버를 출력하고, RestoreMediaSense 함수를 호출하고, IP 주소 테이블을 다시 검색하고, 표에 있는 IP 주소 항목의 일부 멤버를 출력합니다. 미디어 감지 기능을 사용하지 않도록 설정하면 IP 주소 테이블 항목의 차이에서 확인할 수 있습니다.
DisableMediaSense 및 RestoreMediaSense 함수를 동기적으로 호출하는 방법을 보여 주는 예제는 RestoreMediaSense 함수 참조를 참조하세요.
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <stdio.h>
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
/* Note: could also use malloc() and free() */
int __cdecl main()
{
int i;
/* Variables used by GetIpAddrTable */
PMIB_IPADDRTABLE pIPAddrTable;
DWORD dwSize = 0;
DWORD dwRetVal = 0;
IN_ADDR IPAddr;
/* Variables used to return error message */
LPVOID lpMsgBuf;
// Variables to call DisableMediaSense
// and RestoreMediaSense asynchronously
HANDLE IpDriverHandle = INVALID_HANDLE_VALUE;
OVERLAPPED Overlapped;
HANDLE DriverHandle;
DWORD dwEnableCount = 0;
memset(&Overlapped, 0, sizeof (Overlapped));
Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
dwRetVal = DisableMediaSense(&DriverHandle, &Overlapped);
if (dwRetVal != ERROR_IO_PENDING) {
printf("DisableMediaSense failed with error %d\n", dwRetVal);
exit(1);
} else {
printf(" === DisableMediaSense called ===\n\n");
// Sleep for 60 seconds so we can disconnect a cable
Sleep(60000);
}
// Before calling AddIPAddress we use GetIpAddrTable to get
// an adapter to which we can add the IP.
pIPAddrTable = (MIB_IPADDRTABLE *) MALLOC(sizeof (MIB_IPADDRTABLE));
if (pIPAddrTable) {
// Make an initial call to GetIpAddrTable to get the
// necessary size into the dwSize variable
if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) ==
ERROR_INSUFFICIENT_BUFFER) {
FREE(pIPAddrTable);
pIPAddrTable = (MIB_IPADDRTABLE *) MALLOC(dwSize);
}
if (pIPAddrTable == NULL) {
printf("Memory allocation failed for GetIpAddrTable\n");
exit(1);
}
}
// Make a second call to GetIpAddrTable to get the
// actual data we want
if ((dwRetVal = GetIpAddrTable(pIPAddrTable, &dwSize, 0)) != NO_ERROR) {
printf("GetIpAddrTable failed with error %d\n", dwRetVal);
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwRetVal,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) & lpMsgBuf, 0, NULL)) {
printf("\tError: %s", lpMsgBuf);
LocalFree(lpMsgBuf);
}
exit(1);
}
printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries);
for (i = 0; i < (int) pIPAddrTable->dwNumEntries; i++) {
printf("\n\tInterface Index[%d]:\t%ld\n", i,
pIPAddrTable->table[i].dwIndex);
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr;
printf("\tIP Address[%d]: \t%s\n", i, inet_ntoa(IPAddr));
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwMask;
printf("\tSubnet Mask[%d]: \t%s\n", i, inet_ntoa(IPAddr));
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwBCastAddr;
printf("\tBroadCast[%d]: \t%s (%ld%)\n", i, inet_ntoa(IPAddr),
pIPAddrTable->table[i].dwBCastAddr);
printf("\tReassembly size[%d]:\t%ld\n", i,
pIPAddrTable->table[i].dwReasmSize);
printf("\tType and State[%d]:", i);
if (pIPAddrTable->table[i].wType & MIB_IPADDR_PRIMARY)
printf("\tPrimary IP Address");
if (pIPAddrTable->table[i].wType & MIB_IPADDR_DYNAMIC)
printf("\tDynamic IP Address");
if (pIPAddrTable->table[i].wType & MIB_IPADDR_DISCONNECTED)
printf("\tAddress is on disconnected interface");
if (pIPAddrTable->table[i].wType & MIB_IPADDR_DELETED)
printf("\tAddress is being deleted");
if (pIPAddrTable->table[i].wType & MIB_IPADDR_TRANSIENT)
printf("\tTransient address");
printf("\n");
}
// Call RestoreMediaSense asynchronously to enable mediasense
dwRetVal = RestoreMediaSense(&Overlapped, &dwEnableCount);
if (dwRetVal && dwRetVal != ERROR_IO_PENDING) {
printf("RestoreMediaSense failed with error %d\n", dwRetVal);
exit(1);
} else {
printf(" === RestoreMediaSense called ===\n");
printf(" EnableCount returned was %ld\n\n", dwEnableCount);
}
if (pIPAddrTable) {
// Make an initial call to GetIpAddrTable to get the
// necessary size into the dwSize variable
if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) ==
ERROR_INSUFFICIENT_BUFFER) {
FREE(pIPAddrTable);
pIPAddrTable = (MIB_IPADDRTABLE *) MALLOC(dwSize);
}
if (pIPAddrTable == NULL) {
printf("Memory allocation failed for GetIpAddrTable\n");
exit(1);
}
}
// Make a second call to GetIpAddrTable to get the
// actual data we want
if ((dwRetVal = GetIpAddrTable(pIPAddrTable, &dwSize, 0)) != NO_ERROR) {
printf("GetIpAddrTable failed with error %d\n", dwRetVal);
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dwRetVal,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) & lpMsgBuf, 0, NULL)) {
printf("\tError: %s", lpMsgBuf);
LocalFree(lpMsgBuf);
}
exit(1);
}
printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries);
for (i = 0; i < (int) pIPAddrTable->dwNumEntries; i++) {
printf("\n\tInterface Index[%d]:\t%ld\n", i,
pIPAddrTable->table[i].dwIndex);
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr;
printf("\tIP Address[%d]: \t%s\n", i, inet_ntoa(IPAddr));
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwMask;
printf("\tSubnet Mask[%d]: \t%s\n", i, inet_ntoa(IPAddr));
IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwBCastAddr;
printf("\tBroadCast[%d]: \t%s (%ld%)\n", i, inet_ntoa(IPAddr),
pIPAddrTable->table[i].dwBCastAddr);
printf("\tReassembly size[%d]:\t%ld\n", i,
pIPAddrTable->table[i].dwReasmSize);
printf("\tType and State[%d]:", i);
if (pIPAddrTable->table[i].wType & MIB_IPADDR_PRIMARY)
printf("\tPrimary IP Address");
if (pIPAddrTable->table[i].wType & MIB_IPADDR_DYNAMIC)
printf("\tDynamic IP Address");
if (pIPAddrTable->table[i].wType & MIB_IPADDR_DISCONNECTED)
printf("\tAddress is on disconnected interface");
if (pIPAddrTable->table[i].wType & MIB_IPADDR_DELETED)
printf("\tAddress is being deleted");
if (pIPAddrTable->table[i].wType & MIB_IPADDR_TRANSIENT)
printf("\tTransient address");
printf("\n");
}
if (pIPAddrTable) {
FREE(pIPAddrTable);
pIPAddrTable = NULL;
}
exit(0);
}
요구 사항
지원되는 최소 클라이언트 | Windows XP [데스크톱 앱만 해당] |
지원되는 최소 서버 | Windows Server 2003 [데스크톱 앱만 해당] |
대상 플랫폼 | Windows |
헤더 | iphlpapi.h |
라이브러리 | Iphlpapi.lib |
DLL | Iphlpapi.dll |