Función RestoreMediaSense (iphlpapi.h)

La función RestoreMediaSense restaura la funcionalidad de detección de medios de la pila TCP/IP en un equipo local en el que se llamó anteriormente a la función DisableMediaSense .

Sintaxis

IPHLPAPI_DLL_LINKAGE DWORD RestoreMediaSense(
             OVERLAPPED *pOverlapped,
  [optional] LPDWORD    lpdwEnableCount
);

Parámetros

pOverlapped

Puntero a una estructura OVERLAPPED. Excepto para el miembro hEvent , todos los miembros de esta estructura deben establecerse en cero. El miembro hEvent debe contener un identificador para un objeto de evento válido. Use la función CreateEvent para crear este objeto de evento.

[optional] lpdwEnableCount

Puntero opcional a una variable DWORD que recibe el número de referencias restantes si la función RestoreMediaSense se realiza correctamente. Las funciones EnableRouter y UnenableRouter también usan la variable .

Valor devuelto

Si la función se ejecuta correctamente, el valor devuelto es NO_ERROR.

Si se produce un error en la función, el valor devuelto es uno de los siguientes códigos de error.

Código devuelto Descripción
ERROR_INVALID_PARAMETER
Se pasó un parámetro no válido a la función. Este error se devuelve si un parámetro pOverlapped es un puntero incorrecto. Este error también se devuelve si no se llamó a la función DisableMediaSense antes de llamar a la función RestoreMediaSense .
ERROR_IO_PENDING
La operación está en curso. Este valor puede devolverse mediante una llamada asincrónica correcta a RestoreMediaSense.
ERROR_OPEN_FAILED
Un identificador interno para el controlador no era válido.
ERROR_NOT_SUPPORTED
No se admite la solicitud.
Otros
Use FormatMessage para obtener la cadena de mensaje para el error devuelto.

Comentarios

Si el parámetro pOverlapped es NULL, la función RestoreMediaSense se ejecuta sincrónicamente.

Si el parámetro pOverlapped no es NULL, la función RestoreMediaSense se ejecuta de forma asincrónica mediante la estructura SUPERPUESTA a la que apunta el parámetro pOverlapped .

La función DisableMediaSense no se completa hasta que se llama a la función RestoreMediaSense más adelante para restaurar la funcionalidad de detección de medios. Hasta entonces, un paquete de solicitud de E/S (IRP) permanece en cola. Como alternativa, cuando se cierra el proceso llamado DisableMediaSense , se cancela el IRP y se llama a una rutina de cancelación que restauraría de nuevo la funcionalidad de detección de medios.

Para llamar a RestoreMediaSense de forma sincrónica, una aplicación debe pasar un puntero NULL en el parámetro pOverlapped . Cuando Se llama a RestoreMediaSense de forma sincrónica, la función devuelve cuando se ha completado el paquete de solicitud de E/S (IRP) para restaurar el sentido multimedia.

Para llamar a RestoreMediaSense de forma asincrónica, una aplicación debe asignar una estructura SUPERPUESTA . Excepto para el miembro hEvent , todos los miembros de esta estructura deben establecerse en cero. El miembro hEvent requiere un identificador para un objeto de evento válido. Use la función CreateEvent para crear este evento. Cuando se llama de forma asincrónica, RestoreMediaSense puede devolver ERROR_IO_PENDING. El IRP se completa cuando se ha restaurado la funcionalidad de detección de medios. Use la función CloseHandle para cerrar el identificador del objeto de evento cuando ya no sea necesario. El sistema cierra el identificador automáticamente cuando finaliza el proceso. El objeto de evento se destruye cuando se ha cerrado su último identificador.

Si no se llamó a DisableMediaSense antes de llamar a RestoreMediaSense, RestoreMediaSense devuelve ERROR_INVALID_PARAMETER.

En Windows Server 2003 y Windows XP, la pila TCP/IP implementa una directiva de eliminación de todas las direcciones IP en una interfaz en respuesta a un evento de desconexión de sentido multimedia de una interfaz de red subyacente. Si un conmutador de red o un concentrador al que está conectado el equipo local está apagado o se desconecta un cable de red, la interfaz de red entregará eventos de desconexión. Se pierde la información de configuración de IP asociada a la interfaz de red. Como resultado, la pila TCP/IP implementa una directiva de ocultar interfaces desconectadas para que estas interfaces y sus direcciones IP asociadas no aparezcan en la información de configuración recuperada a través del asistente de IP. Esta directiva impide que algunas aplicaciones detecten fácilmente que una interfaz de red se desconecta simplemente, en lugar de quitarse del sistema.

Este comportamiento no suele afectar a un equipo cliente local si usa solicitudes DHCP a un servidor DHCP para obtener información de configuración de IP. Pero esto puede tener un impacto grave en los equipos servidor, especialmente en los equipos que se usan como parte de los clústeres. La función DisableMediaSense se puede usar para deshabilitar temporalmente la funcionalidad de sentido multimedia para estos casos. Más adelante, se llamaría a la función RestoreMediaSense para restaurar la funcionalidad de detección de medios.

La siguiente configuración del Registro está relacionada con las funciones DisableMediaSense y RestoreMediaSense :

Sistema\Currentcontrolset\Servicios\Tcpip\Parámetros\DisableDHCPMediaSense

Hay una marca interna en Windows que se establece si esta clave del Registro existe cuando la máquina arranca por primera vez. La misma marca interna también se establece y restablece llamando a DisableMediaSense y RestoreMediaSense. Sin embargo, con la configuración del Registro, debe reiniciar la máquina para que se produzcan los cambios.

La pila TCP/IP en Windows Vista y versiones posteriores se cambió para no ocultar interfaces desconectadas cuando se produce un evento de desconexión. Por lo tanto, en Windows Vista y versiones posteriores, las funciones DisableMediaSense y RestoreMediaSense no hacen nada y siempre devuelven NO_ERROR.

Ejemplos

En el ejemplo siguiente se muestra cómo llamar a las funciones DisableMediaSense y RestoreMediaSense de forma sincrónica. Este ejemplo solo es útil en Windows Server 2003 y Windows XP, donde las funciones DisableMediaSense y RestoreMediaSense hacen algo útil.

En primer lugar, el ejemplo crea un subproceso independiente que llama a la función DisableMediaSense de forma sincrónica, el subproceso principal se suspende durante 60 segundos para permitir que el usuario desconecte un cable de red, recupere la tabla de direcciones IP e imprima algunos miembros de las entradas de dirección IP de la tabla, llama a la función RestoreMediaSense de forma sincrónica, recupera de nuevo la tabla de direcciones IP, e imprime algunos miembros de las entradas de dirección IP de la tabla. El impacto de deshabilitar la funcionalidad de detección de medios puede verse en la diferencia en las entradas de la tabla de direcciones IP.

Para ver un ejemplo que muestra cómo llamar a las funciones DisableMediaSense y RestoreMediaSense de forma asincrónica, consulte la referencia de la función 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);
}


Requisitos

   
Cliente mínimo compatible Windows XP [solo aplicaciones de escritorio]
Servidor mínimo compatible Windows Server 2003 [solo aplicaciones de escritorio]
Plataforma de destino Windows
Encabezado iphlpapi.h
Library Iphlpapi.lib
Archivo DLL Iphlpapi.dll

Consulte también

CloseHandle

CreateEvent

DisableMediaSense

EnableRouter

Referencia de la función auxiliar de IP

Página de inicio del asistente de IP

OVERLAPPED

UnableRouter