次の方法で共有


DisableMediaSense 関数 (iphlpapi.h)

DisableMediaSense 関数は、ローカル コンピューター上の TCP/IP スタックのメディア 検出機能を無効にします。

構文

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

パラメーター

pHandle

ハンドルの格納に使用される変数へのポインター。 pOverlapped パラメーターが NULL でない場合は、この変数を内部的に使用して、IP ドライバーを呼び出し、メディア 検出機能を無効にするために必要なハンドルを格納します。

アプリケーションでは、この変数が指す値を使用しないでください。 このハンドルは内部使用のため、閉じてはいけません。

pOverLapped

OVERLAPPED 構造体へのポインター。 hEvent メンバーを除き、この構造体のすべてのメンバーを 0 に設定する必要があります。 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 関数は pOverlapped パラメーターが指す OVERLAPPED 構造体を使用して非同期的に実行されます。

メディア 検出機能を復元するために RestoreMediaSense 関数が後で呼び出されるまで、DisableMediaSense 関数は完了しません。 それまでは、I/O 要求パケット (IRP) はキューに登録されたままです。 または、 DisableMediaSense を呼び出したプロセスが終了すると、IRP が取り消され、メディア 検出機能を再度復元するキャンセル ルーチンが呼び出されます。

DisableMediaSense を同期的に呼び出すには、アプリケーションでこの呼び出し用に別のスレッドを作成する必要があります。 それ以外の場合は、IRP の完了を待機し続け、関数はブロックします。

DisableMediaSense を非同期的に呼び出すには、アプリケーションで OVERLAPPED 構造体を割り当てる必要があります。 hEvent メンバーを除き、この構造体のすべてのメンバーを 0 に設定する必要があります。 hEvent メンバーには、有効なイベント オブジェクトへのハンドルが必要です。 CreateEvent 関数を使用して、このイベントを作成します。 非同期で呼び出されると、 DisableMediaSense は常にERROR_IO_PENDINGを返します。 IRP は、 RestoreMediaSense が後で呼び出された場合にのみ完了します。 CloseHandle 関数を使用して、不要になったイベント オブジェクトへのハンドルを閉じます。 プロセスが終了すると、ハンドルが自動的に閉じられます。 イベント オブジェクトは、最後のハンドルが閉じられたときに破棄されます。

Windows Server 2003 および Windows XP では、TCP/IP スタックは、基になるネットワーク インターフェイスからメディア センス切断イベントに応答して、インターフェイス上のすべての IP アドレスを削除するポリシーを実装します。 ローカル コンピューターが接続されているネットワーク スイッチまたはハブの電源がオフになっている場合、またはネットワーク ケーブルが切断されている場合、ネットワーク インターフェイスは切断イベントを配信します。 ネットワーク インターフェイスに関連付けられている IP 構成情報が失われます。 その結果、TCP/IP スタックは、切断されたインターフェイスを非表示にするポリシーを実装するため、これらのインターフェイスとそれに関連付けられている IP アドレスは、IP ヘルパーを介して取得された構成情報に表示されません。 このポリシーにより、一部のアプリケーションでは、システムから削除されるのではなく、ネットワーク インターフェイスが単に切断されていることを簡単に検出できなくなります。

この動作は、通常、IP 構成情報に DHCP サーバーへの DHCP 要求を使用している場合、ローカル クライアント コンピューターには影響しません。 ただし、これはサーバー コンピューター、特にクラスターの一部として使用されるコンピューターに深刻な影響を与える可能性があります。 DisableMediaSense 関数を使用すると、このような場合にメディア 検出機能を一時的に無効にすることができます。 しばらくすると、メディア 検出機能を復元するために RestoreMediaSense 関数が呼び出されます。

次のレジストリ設定は、 DisableMediaSense 関数と RestoreMediaSense 関数に関連しています。

システム\CurrentControlSet\サービス\Tcpip\パラメーター\DisableDHCPMediaSense

Windows には、マシンが最初に起動したときにこのレジストリ キーが存在する場合に設定される内部フラグがあります。 また、 DisableMediaSenseRestoreMediaSense を呼び出すことで、同じ内部フラグが設定およびリセットされます。 ただし、レジストリ設定では、変更を行うためにマシンを再起動する必要があります。

Windows Vista 以降の TCP/IP スタックは、切断イベントが発生したときに切断されたインターフェイスを非表示にしないように変更されました。 そのため、Windows Vista 以降では、 DisableMediaSense 関数と RestoreMediaSense 関数は何もせず、常にNO_ERRORを返します。

次の例は、 DisableMediaSense 関数と RestoreMediaSense 関数を非同期的に呼び出す方法を示しています。 このサンプルは、 DisableMediaSense 関数と RestoreMediaSense 関数が役立つ機能を実行する Windows Server 2003 および Windows XP でのみ役立ちます。

このサンプルでは、最初に 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
ヘッダー iphlpapi.h
Library Iphlpapi.lib
[DLL] Iphlpapi.dll

関連項目

CloseHandle

CreateEvent

EnableRouter

IP ヘルパー関数リファレンス

IP ヘルパーの開始ページ

OVERLAPPED

RestoreMediaSense

UnenableRouter