RestoreMediaSense 函数 (iphlpapi.h)
RestoreMediaSense 函数在以前调用 DisableMediaSense 函数的本地计算机上还原 TCP/IP 堆栈的媒体感知功能。
语法
IPHLPAPI_DLL_LINKAGE DWORD RestoreMediaSense(
OVERLAPPED *pOverlapped,
[optional] LPDWORD lpdwEnableCount
);
参数
pOverlapped
指向 OVERLAPPED 结构的指针。 除 hEvent 成员外,此结构的所有成员都必须设置为零。 hEvent 成员应包含有效事件对象的句柄。 使用 CreateEvent 函数创建此事件对象。
[optional] lpdwEnableCount
指向 DWORD 变量的可选指针,如果 RestoreMediaSense 函数成功,该变量接收剩余的引用数。 变量也由 EnableRouter 和 UnenableRouter 函数使用。
返回值
如果函数成功,则返回值NO_ERROR。
如果函数失败,则返回值为以下错误代码之一。
返回代码 | 说明 |
---|---|
|
向该函数传递了无效参数。 如果 pOverlapped 参数是错误的指针,则返回此错误。 如果在调用 RestoreMediaSense 函数之前未调用 DisableMediaSense 函数,也会返回此错误。 |
|
操作正在进行中。 对 RestoreMediaSense 的成功异步调用可能会返回此值。 |
|
驱动程序的内部句柄无效。 |
|
不支持该请求。 |
|
使用 FormatMessage 获取返回错误的消息字符串。 |
注解
如果 pOverlapped 参数为 NULL,则 RestoreMediaSense 函数将同步执行。
如果 pOverlapped 参数不为 NULL,则使用 pOverlapped 参数指向的 OVERLAPPED 结构异步执行 RestoreMediaSense 函数。
在稍后调用 RestoreMediaSense 函数以还原媒体感知功能之前, DisableMediaSense 函数不会完成。 在此之前,I/O 请求数据包 (IRP) 仍排队。 或者,当名为 DisableMediaSense 的进程退出时,将取消 IRP,并调用取消例程,以再次还原媒体感知功能。
若要以同步方式调用 RestoreMediaSense,应用程序需要在 pOverlapped 参数中传递 NULL 指针。 同步调用 RestoreMediaSense 时,当 I/O 请求数据包 (IRP) 还原媒体感知完成时,函数将返回 。
若要异步调用 RestoreMediaSense ,应用程序需要分配 OVERLAPPED 结构。 除 hEvent 成员外,此结构的所有成员都必须设置为零。 hEvent 成员需要有效事件对象的句柄。 使用 CreateEvent 函数创建此事件。 异步调用 RestoreMediaSense 时,可以返回ERROR_IO_PENDING。 当媒体感知功能已还原时,IRP 完成。 当不再需要事件对象时,使用 CloseHandle 函数关闭该事件对象的句柄。 进程终止时,系统会自动关闭句柄。 事件对象在关闭其最后一个句柄时被销毁。
如果在调用 RestoreMediaSense 之前未调用 DisableMediaSense,则 RestoreMediaSense 返回ERROR_INVALID_PARAMETER。
在 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 函数,main线程休眠 60 秒以允许用户断开网络电缆的连接,检索 IP 地址表并打印表中 IP 地址条目的某些成员,同步调用 RestoreMediaSense 函数,再次检索 IP 地址表, 和 打印表中 IP 地址条目的某些成员。 禁用媒体感知功能的影响可以从 IP 地址表条目的差异中看出。
有关演示如何异步调用 DisableMediaSense 和 RestoreMediaSense 函数的示例,请参阅 DisableMediaSense 函数参考。
#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() */
// The thread proc to call DisableMediaSense
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
if (*((DWORD *) lpParam)) {
DWORD dwRetVal;
dwRetVal = DisableMediaSense(NULL, NULL);
if (dwRetVal && dwRetVal != ERROR_IO_PENDING) {
printf("DisableMediaSense failed with error %d\n", dwRetVal);
return 0;
} else {
Sleep(1000);
printf(" === DisableMediaSense Returned now. ===\n\n");
}
}
return 0;
}
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;
/* Variable to use with RestoreMediaSense */
DWORD dwEnableCount = 0;
// Variables used to create a separate thread to call
// the DisableMediaSense function
DWORD ThreadID;
DWORD IsDisable = TRUE;
HANDLE Disable_THandle;
// Create the thread to call Disable MediaSense synchronously
Disable_THandle =
CreateThread(NULL, 0, ThreadProc, (LPVOID) & IsDisable, 0, &ThreadID);
if (!Disable_THandle) {
printf("CreateTread Failed:%d", GetLastError());
exit(1);
}
printf(" === DisableMediaSense called on separate thread ===\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 synchronously to enable mediasense
dwRetVal = RestoreMediaSense(NULL, &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 |