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。

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

返回代码 说明
ERROR_INVALID_PARAMETER
向该函数传递了无效参数。 如果 pOverlapped 参数是错误的指针,则返回此错误。
ERROR_IO_PENDING
操作正在进行中。 此值由对 DisableMediaSense 的成功异步调用返回。
ERROR_OPEN_FAILED
pHandle 参数指向的句柄无效。
ERROR_NOT_SUPPORTED
不支持该请求。
其他
使用 FormatMessage 获取返回错误的消息字符串。

注解

如果 pHandlepOverlapped 参数为 NULL,则 DisableMediaSense 函数将同步执行。

如果 pHandlepOverlapped 参数都不为 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 函数来还原媒体感知功能。

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

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

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

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

示例

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

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

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

另请参阅

CloseHandle

CreateEvent

EnableRouter

IP 帮助程序函数参考

IP 帮助程序起始页

OVERLAPPED

RestoreMediaSense

UnenableRouter