RestoreMediaSense 函式 (iphlpapi.h)
RestoreMediaSense 函式會在先前呼叫 DisableMediaSense 函式的本機計算機上,還原 TCP/IP 堆棧的媒體感知功能。
語法
IPHLPAPI_DLL_LINKAGE DWORD RestoreMediaSense(
OVERLAPPED *pOverlapped,
[optional] LPDWORD lpdwEnableCount
);
參數
pOverlapped
重疊結構的指標。 除了 hEvent 成員之外,此結構的所有成員都必須設定為零。 hEvent成員應該包含有效事件物件的句柄。 使用 CreateEvent 函式來建立此事件物件。
[optional] lpdwEnableCount
DWORD 變數的選擇性指標,如果 RestoreMediaSense 函式成功,則會接收剩餘的參考數目。 EnableRouter 和 UnenableRouter 函式也會使用變數。
傳回值
如果函式成功,傳回值會NO_ERROR。
如果函式失敗,傳回值就是下列其中一個錯誤碼。
傳回碼 | Description |
---|---|
|
無效的參數已傳遞至 函式。 如果 pOverlapped 參數是錯誤的指標,就會傳回此錯誤。 如果在呼叫 RestoreMediaSense 函式之前未呼叫 DisableMediaSense 函式,也會傳回此錯誤。 |
|
作業正在進行中。 這個值可由 RestoreMediaSense 的成功異步呼叫傳回。 |
|
驅動程式的內部句柄無效。 |
|
不支援此要求。 |
|
使用 FormatMessage 取得傳回錯誤的訊息字串。 |
備註
如果 pOverlapped 參數為 NULL,則會同步執行 RestoreMediaSense 函式。
如果 pOverlapped 參數不是 NULL,則 RestoreMediaSense 函式會使用 pOverlapped 參數所指向的 OVERLAPPED 結構以異步方式執行。
DisableMediaSense 函式在稍後呼叫 RestoreMediaSense 函式才能完成,以還原媒體感知功能。 在那之前,I/O 要求封包 (IRP) 仍會排入佇列。 或者,當呼叫 DisableMediaSense 的進程結束時,會取消 IRP,並呼叫取消例程,以再次還原媒體感測器功能。
若要以同步方式呼叫 RestoreMediaSense,應用程式必須在 pOverlapped 參數中傳遞 NULL 指標。 以同步方式呼叫 RestoreMediaSense 時,當 I/O 要求封包 (IRP) 完成還原媒體感知時,函式會傳回 。
若要以異步方式呼叫 RestoreMediaSense ,應用程式必須配置 重疊 結構。 除了 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組態資訊,此行為通常不會影響本機客戶端電腦。 但這可能會對伺服器計算機造成嚴重影響,特別是用來作為叢集一部分的計算機。 DisableMediaSense 函式可用來暫時停用這些案例的媒體感知功能。 稍後會呼叫 RestoreMediaSense 函式來還原媒體檢測功能。
下列登錄設定與 DisableMediaSense 和 RestoreMediaSense 函式有關:
系統\CurrentControlSet\服務\Tcpip\參數\DisableDHCPMediaSense
Windows 中有一個內部旗標,如果計算機第一次開機時存在此登錄機碼,就會設定此旗標。 相同的內部旗標也會藉由呼叫 DisableMediaSense 和 RestoreMediaSense 來設定和重設。 不過,使用登錄設定時,您必須重新啟動計算機,才能進行變更。
Windows Vista 和更新版本的 TCP/IP 堆棧在發生中斷連線事件時,已變更為不會隱藏已中斷連線的介面。 因此,在 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 函式的範例,請參閱 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 |
程式庫 | Iphlpapi.lib |
Dll | Iphlpapi.dll |