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 函数成功,该变量接收剩余的引用数。 变量也由 EnableRouterUnenableRouter 函数使用。

返回值

如果函数成功,则返回值NO_ERROR。

如果函数失败,则返回值为以下错误代码之一。

返回代码 说明
ERROR_INVALID_PARAMETER
向该函数传递了无效参数。 如果 pOverlapped 参数是错误的指针,则返回此错误。 如果在调用 RestoreMediaSense 函数之前未调用 DisableMediaSense 函数,也会返回此错误。
ERROR_IO_PENDING
操作正在进行中。 对 RestoreMediaSense 的成功异步调用可能会返回此值。
ERROR_OPEN_FAILED
驱动程序的内部句柄无效。
ERROR_NOT_SUPPORTED
不支持该请求。
其他
使用 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 函数来还原媒体感知功能。

以下注册表设置与 DisableMediaSenseRestoreMediaSense 函数相关:

系统\CurrentControlSet\服务\Tcpip\参数\DisableDHCPMediaSense

如果计算机首次启动时此注册表项存在,则 Windows 中会设置一个内部标志。 通过调用 DisableMediaSenseRestoreMediaSense,还可以设置和重置同一内部标志。 但是,使用注册表设置时,需要重新启动计算机才能发生更改。

Windows Vista 和更高版本的 TCP/IP 堆栈已更改为在发生断开连接事件时不隐藏断开连接的接口。 因此,在 Windows Vista 及更高版本中, DisableMediaSenseRestoreMediaSense 函数不会执行任何操作,并且始终返回NO_ERROR。

示例

以下示例演示如何同步调用 DisableMediaSenseRestoreMediaSense 函数。 此示例仅适用于 DisableMediaSenseRestoreMediaSense 函数执行有用操作的 Windows Server 2003 和 Windows XP。

示例首先创建一个单独的线程,该线程同步调用 DisableMediaSense 函数,main线程休眠 60 秒以允许用户断开网络电缆的连接,检索 IP 地址表并打印表中 IP 地址条目的某些成员,同步调用 RestoreMediaSense 函数,再次检索 IP 地址表, 和 打印表中 IP 地址条目的某些成员。 禁用媒体感知功能的影响可以从 IP 地址表条目的差异中看出。

有关演示如何异步调用 DisableMediaSenseRestoreMediaSense 函数的示例,请参阅 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

另请参阅

CloseHandle

CreateEvent

DisableMediaSense

EnableRouter

IP 帮助程序函数参考

IP 帮助程序起始页

OVERLAPPED

UnenableRouter