Поделиться через


Функция DisableMediaSense (iphlpapi.h)

Функция DisableMediaSense отключает возможность зондирования мультимедиа стека TCP/IP на локальном компьютере.

Синтаксис

IPHLPAPI_DLL_LINKAGE DWORD DisableMediaSense(
  HANDLE     *pHandle,
  OVERLAPPED *pOverLapped
);

Параметры

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 , чтобы получить строку сообщения для возвращаемой ошибки.

Комментарии

Если параметры pHandle или pOverlapped имеют значение NULL, функция DisableMediaSense выполняется синхронно.

Если параметры pHandle и pOverlapped не имеют значения NULL, функция DisableMediaSense выполняется асинхронно с использованием структуры OVERLAPPED , на которую указывает параметр pOverlapped .

Функция DisableMediaSense не будет завершена до тех пор, пока позже не будет вызвана функция RestoreMediaSense для восстановления возможности датчиков мультимедиа. До тех пор пакет запроса ввода-вывода (IRP) остается в очереди. Кроме того, когда завершается процесс с именем DisableMediaSense , IRP отменяется и вызывается подпрограмма отмены, которая снова восстановит возможность зондирования мультимедиа.

Чтобы вызвать DisableMediaSense синхронно, приложению необходимо создать отдельный поток для этого вызова. В противном случае он будет продолжать ждать завершения IRP, и функция будет заблокирована.

Чтобы асинхронно вызвать DisableMediaSense , приложению необходимо выделить структуру OVERLAPPED . За исключением элемента hEvent , все члены этой структуры должны иметь нулевое значение. Члену hEvent требуется дескриптор допустимого объекта события. Используйте функцию CreateEvent для создания этого события. При асинхронном вызове Функция DisableMediaSense всегда возвращает ERROR_IO_PENDING. IRP будет завершен только при последующем вызове RestoreMediaSense . Используйте функцию CloseHandle , чтобы закрыть дескриптор для объекта события, когда он больше не нужен. Система автоматически закрывает дескриптор при завершении процесса. Объект события уничтожается при закрытии последнего дескриптора.

В Windows Server 2003 и Windows XP стек TCP/IP реализует политику удаления всех IP-адресов в интерфейсе в ответ на событие отключения с точки зрения мультимедиа от базового сетевого интерфейса. Если сетевой коммутатор или концентратор, к которому подключен локальный компьютер, отключен или сетевой кабель отключен, сетевой интерфейс будет доставлять события отключения. Сведения об IP-конфигурации, связанные с сетевым интерфейсом, теряются. В результате стек TCP/IP реализует политику скрытия отключенных интерфейсов, чтобы эти интерфейсы и связанные с ними IP-адреса не отображались в сведениях о конфигурации, полученных через вспомогателя IP-адресов. Эта политика не позволяет некоторым приложениям легко обнаружить, что сетевой интерфейс просто отключен, а не удален из системы.

Обычно это не влияет на локальный клиентский компьютер, если он использует DHCP-запросы к DHCP-серверу для получения сведений об IP-конфигурации. Но это может серьезно повлиять на серверные компьютеры, особенно компьютеры, используемые в составе кластеров. Функцию DisableMediaSense можно использовать для временного отключения возможности определения мультимедиа для этих случаев. Через некоторое время будет вызвана функция RestoreMediaSense для восстановления возможности зондирования мультимедиа.

Следующий параметр реестра связан с функциями DisableMediaSense и RestoreMediaSense :

Системы\CurrentControlSet\Услуги\Tcpip\Параметры\DisableDHCPMediaSense

В Windows есть внутренний флаг, который устанавливается, если этот раздел реестра существует при первой загрузке компьютера. Тот же внутренний флаг также устанавливается и сбрасывается путем вызовов DisableMediaSense и RestoreMediaSense. Однако с параметром реестра необходимо перезагрузить компьютер, чтобы изменения произошли.

Стек TCP/IP в Windows Vista и более поздних версий был изменен, чтобы не скрывать отключенные интерфейсы при возникновении события отключения. Поэтому в Windows Vista и более поздних версиях функции DisableMediaSense и RestoreMediaSense не выполняют никаких действий и всегда возвращают NO_ERROR.

Примеры

В следующем примере показано, как асинхронно вызывать функции DisableMediaSense и RestoreMediaSense . Этот пример полезен только в Windows Server 2003 и Windows XP, где функции DisableMediaSense и RestoreMediaSense выполняют некоторые полезные действия.

В примере сначала вызывается функция 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
Header iphlpapi.h
Библиотека Iphlpapi.lib
DLL Iphlpapi.dll

См. также раздел

CloseHandle

CreateEvent

EnableRouter

Справочник по вспомогательной функции IP

Начальная страница вспомогательного ip-адреса

ПЕРЕКРЫВАЮЩИХСЯ

RestoreMediaSense

UnenableRouter