本文示範呼叫微軟未公開文件化的 ICMP.dll 內部 API (IcmpCreateFile、IcmpSendEcho、IcmpCloseHandle) 實作 Ping 功能。此 DLL 自 Windows 95 起存在,Windows 2000 仍保留,但微軟已宣佈將以更好方案取代,不建議新專案採用。
HINSTANCE hIcmp = LoadLibrary("ICMP.DLL");
if (!hIcmp) { /* 錯誤處理 */ }
// 定義函數指標型別 (參數複雜,使用 typedef 簡化)
typedef HANDLE (WINAPI *PFN_ICMPCREATEFILE)(VOID);
typedef BOOL (WINAPI *PFN_ICMPCLOSEHANDLE)(HANDLE);
typedef DWORD (WINAPI *PFN_ICMPSENDECHO)(HANDLE, DWORD, LPVOID, WORD,
PIP_OPTION_INFORMATION, LPVOID, DWORD, DWORD);
PFN_ICMPCREATEFILE pIcmpCreateFile = (PFN_ICMPCREATEFILE) GetProcAddress(hIcmp, "IcmpCreateFile");
PFN_ICMPCLOSEHANDLE pIcmpCloseHandle = (PFN_ICMPCLOSEHANDLE) GetProcAddress(hIcmp, "IcmpCloseHandle");
PFN_ICMPSENDECHO pIcmpSendEcho = (PFN_ICMPSENDECHO) GetProcAddress(hIcmp, "IcmpSendEcho");
typedef struct {
UCHAR Ttl; // Time To Live
UCHAR Tos; // Type Of Service
UCHAR Flags; // IP 標頭旗標
UCHAR OptionsSize; // 選項資料大小
UCHAR *OptionsData; // 選項資料指標
} IP_OPTION_INFORMATION, *PIP_OPTION_INFORMATION;
typedef struct {
DWORD Address; // 回應位址
ULONG Status; // 回應狀態
ULONG RoundTripTime; // RTT (毫秒)
USHORT DataSize; // 回應資料大小
USHORT Reserved; // 保留
void *Data; // 回應資料指標
IP_OPTION_INFORMATION Options; // 回應選項
} IP_ECHO_REPLY, *PIP_ECHO_REPLY;
WSAStartup(MAKEWORD(1,1)) 初始化 Winsockgethostbyname 解析目標主機名稱取得 IP 位址LoadLibrary("ICMP.DLL") + GetProcAddress 取得三個函數入口pIcmpCreateFile() 開啟 Ping 服務取得 HandleGlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT, sizeof(IP_ECHO_REPLY)+64))pIcmpSendEcho(hIP, destIP, sendBuf, 64, NULL, pReply, replyBufSize, 5000) 同步發送並等待回應 (5 秒逾時)pReply 解析 IP、RTT、TTL 輸出GlobalFree、FreeLibrary、WSACleanup 釋放資源main(),doit() 僅負責核心邏輯IP_ECHO_REPLY.Status 詳細分類 (參考 WinError.h)ICMP.dll 方式程式碼簡潔,封裝度高,適合快速原型開發。但因屬非公開 API,存在相容性風險 (Vista 後行為變更),生產環境建議改用 RAW Socket (下一篇) 或 Winsock 2 標準介面。