DisableMediaSense 函数 (iphlpapi.h)
DisableMediaSense 函数禁用本地计算机上的 TCP/IP 堆栈的媒体感知功能。
语法
IPHLPAPI_DLL_LINKAGE DWORD DisableMediaSense(
HANDLE *pHandle,
OVERLAPPED *pOverLapped
);
parameters
pHandle
指向用于存储句柄的变量的指针。 如果 pOverlapped 参数不为 NULL,则此变量将在内部用于存储调用 IP 驱动程序和禁用媒体感知功能所需的句柄。
应用程序不应使用此变量指向的值。 此句柄供内部使用,不应关闭。
pOverLapped
指向 OVERLAPPED 结构的指针。 除 hEvent 成员外,此结构的所有成员都必须设置为零。 hEvent 成员需要有效事件对象的句柄。 使用 CreateEvent 函数创建此事件对象。
返回值
如果函数成功,则返回值NO_ERROR。
如果函数失败,则返回值为以下错误代码之一。
返回代码 | 说明 |
---|---|
|
向该函数传递了无效参数。 如果 pOverlapped 参数是错误的指针,则返回此错误。 |
|
操作正在进行中。 此值由对 DisableMediaSense 的成功异步调用返回。 |
|
pHandle 参数指向的句柄无效。 |
|
不支持该请求。 |
|
使用 FormatMessage 获取返回错误的消息字符串。 |
注解
如果 pHandle 或 pOverlapped 参数为 NULL,则 DisableMediaSense 函数将同步执行。
如果 pHandle 和 pOverlapped 参数都不为 NULL,则使用 pOverlapped 参数指向的 OVERLAPPED 结构异步执行 DisableMediaSense 函数。
在稍后调用 RestoreMediaSense 函数以还原媒体感知功能之前, DisableMediaSense 函数不会完成。 在此之前,I/O 请求数据包 (IRP) 仍排队。 或者,当名为 DisableMediaSense 的进程退出时,将取消 IRP,并调用取消例程,以再次还原媒体感知功能。
若要以同步方式调用 DisableMediaSense ,应用程序需要为此调用创建单独的线程。 否则,它会继续等待 IRP 完成,函数将阻止。
若要异步调用 DisableMediaSense ,应用程序需要分配 一个 OVERLAPPED 结构。 除 hEvent 成员外,此结构的所有成员都必须设置为零。 hEvent 成员需要有效事件对象的句柄。 使用 CreateEvent 函数创建此事件。 异步调用 DisableMediaSense 时,始终返回ERROR_IO_PENDING。 仅当稍后调用 RestoreMediaSense 时,才会完成 IRP。 当不再需要事件对象时,使用 CloseHandle 函数关闭该事件对象的句柄。 进程终止时,系统会自动关闭句柄。 事件对象在关闭其最后一个句柄时被销毁。
在 Windows Server 2003 和 Windows XP 上,TCP/IP 堆栈实现删除接口上所有 IP 地址的策略,以响应与基础网络接口的媒体感知断开连接事件。 如果本地计算机连接到的网络交换机或集线器已关闭电源,或者网络电缆断开连接,则网络接口将传递断开连接事件。 与网络接口关联的 IP 配置信息丢失。 因此,TCP/IP 堆栈实现隐藏断开连接的接口的策略,以便这些接口及其关联的 IP 地址不会显示在通过 IP 帮助程序检索的配置信息中。 此策略可防止某些应用程序轻松检测到网络接口只是断开连接,而不是从系统中删除。
如果本地客户端计算机使用 DHCP 请求获取 IP 配置信息的 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 |
Library | Iphlpapi.lib |
DLL | Iphlpapi.dll |