WindowsAPI| 每天了解几个winAPI接口之Iphlpapi.h网络配置相关文档详细分析一

如果有错误欢迎指正批评,在此只作为科普和参考。

简介

Iphlpapi.h 是 Windows 平台的一个头文件,它提供了网络诊断和网络配置相关的函数。这个头文件定义了 Windows IP Helper API,其中包括许多用于获取网络配置信息、管理网络连接和执行网络诊断的函数。

例如,使用 Iphlpapi.h 可以执行以下操作:

  • 获取网络适配器的列表和状态。
  • 获取网络接口的统计信息(如发送和接收的数据包数)。
  • 管理网络路由表。
  • 执行网络诊断测试,如 ping 或 traceroute。

如果你正在开发一个需要这些功能的 Windows 应用程序,你可以在你的代码中包含这个头文件,并使用它定义的函数。

这里是一个简单的例子,展示如何使用 Iphlpapi.h 来获取网络适配器的信息:

#include <windows.h>
#include <iphlpapi.h>
#include <stdio.h>

int main() {
    ULONG outBufLen = 0;
    IP_ADAPTER_INFO *pAdapterInfo;

    // 首先调用GetAdaptersInfo以确定需要的缓冲区大小
    DWORD dwRetVal = GetAdaptersInfo(NULL, &outBufLen);
    if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
        pAdapterInfo = (IP_ADAPTER_INFO *)malloc(outBufLen);
        if(pAdapterInfo == NULL) {
            printf("Memory allocation failed for IP_ADAPTER_INFO.\n");
            return 1;
        }
    }

    // 再次调用GetAdaptersInfo以获取网络适配器信息
    dwRetVal = GetAdaptersInfo(pAdapterInfo, &outBufLen);
    if (dwRetVal == NO_ERROR) {
        // 输出网络适配器信息
        for (pAdapterInfo; pAdapterInfo != NULL; pAdapterInfo = pAdapterInfo->Next) {
            printf("\tAdapter name: %s\n", pAdapterInfo->AdapterName);
            printf("\tAdapter description: %s\n", pAdapterInfo->Description);
            printf("\tAdapter address: ");
            for (int i = 0; i < pAdapterInfo->AddressLength; i++) {
                printf("%02X ", pAdapterInfo->Address[i]);
            }
            printf("\n");
        }
    } else {
        printf("Call to GetAdaptersInfo failed.\n");
    }

    // 释放内存
    free(pAdapterInfo);
    return 0;
}

这段代码首先调用 GetAdaptersInfo 函数来确定需要的缓冲区大小,然后分配内存并再次调用该函数来获取网络适配器的信息。最后,它遍历链表并打印每个适配器的名称、描述和地址。

详解

路径

iphlpapi.h 是 Windows 操作系统中用于网络诊断和配置的一组 API 的头文件。它包含在 Windows SDK 中,通常位于以下路径:

C:\Program Files (x86)\Windows Kits\10\Include\10.0.*\um\iphlpapi.h

这里的 10.0.* 可能会根据你安装的 Windows SDK 版本而有所不同。你可以通过 Windows SDK 安装目录找到相应的头文件。如果你的系统上安装了 Visual Studio 或其他开发工具,它们通常会包含这些 SDK 文件。

头文件的开头部分

/*++

Copyright (c) Microsoft Corporation. All rights reserved.

Module Name:

    iphlpapi.h

Abstract:
    Header file for functions to interact with the IP Stack for MIB-II and
    related functionality

--*/

#ifndef __IPHLPAPI_H__
#define __IPHLPAPI_H__

#if _MSC_VER > 1000
#pragma once
#endif
#include <winapifamily.h>

这段代码是 iphlpapi.h 头文件的开头部分。它包含了几个关键部分:

  1. 版权声明:声明了 Microsoft Corporation 对该文件拥有版权。
  2. 模块名称:指出了文件名 iphlpapi.h
  3. 摘要:简要描述了这个头文件的作用,即提供与 IP 堆栈交互的函数,用于 MIB-II(管理信息库版本 2)和相关功能的实现。

接下来是一些预处理指令:

  • #ifndef IPHLPAPI_H:这是一个预处理指令,用于防止头文件被多次包含。它检查是否已经定义了 __IPHLAPI_H__,如果没有定义,则继续包含文件的内容。
  • #define IPHLPAPI_H:定义了 __IPHLAPI_H__,确保这个头文件的内容只会被包含一次。
  • #if _MSC_VER > 1000:这是一个条件编译指令,用于检查使用的编译器版本。_MSC_VER 是 Microsoft Visual C++ 编译器的版本号。如果版本号大于 1000(即 Visual Studio .NET 2002 或更高版本),则执行 #pragma once
  • #pragma once:这是一个非标准的编译器指令,告诉编译器这个文件只包含一次。它在 Visual Studio 中有效,但不是所有编译器都支持。
  • #include <winapifamily.h>:包含 Windows API 家族定义的头文件。这个文件定义了不同的 Windows 平台和 API 可用性。

这些指令和包含确保了头文件在编译时被正确处理,并且只包含一次。这对于避免编译错误和确保代码的一致性非常重要。

可移植性和兼容性

//
//                                                                          //
// Establish DLL function linkage if supported by the current build         //
// environment and not previously defined.                                  //
//                                                                          //
//

#ifndef IPHLPAPI_DLL_LINKAGE
#ifdef DECLSPEC_IMPORT
#define IPHLPAPI_DLL_LINKAGE DECLSPEC_IMPORT
#else
#define IPHLPAPI_DLL_LINKAGE
#endif
#endif

#pragma region Application Family or OneCore Family or Games Family
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES)

#ifdef __cplusplus
extern "C" {
#endif

这段代码是 C/C++ 编程中常见的宏定义和编译器指令,用于在 Windows 平台上处理 DLL(动态链接库)的函数链接,以及确保代码在不同 Windows API 家族间的兼容性。下面是对这些代码的具体解释:

  1. 条件编译:通过一系列宏定义来确定是否需要为 DLL 函数导出或导入,这取决于编译器是否支持 DECLSPEC_IMPORT(用于指定导入符号)。

    #ifndef IPHLPAPI_DLL_LINKAGE
    #ifdef DECLSPEC_IMPORT
    #define IPHLPAPI_DLL_LINKAGE DECLSPEC_IMPORT
    #else
    #define IPHLPAPI_DLL_LINKAGE
    #endif
    #endif
    
    • #ifndef IPHLPAPI_DLL_LINKAGE 检查是否已经定义了 IPHLPAPI_DLL_LINKAGE
    • #ifdef DECLSPEC_IMPORT 检查编译器是否定义了 DECLSPEC_IMPORT(通常由编译器自动定义,例如,当你在创建 DLL 时作为导出项目编译)。
    • 如果 DECLSPEC_IMPORT 可用,则 IPHLPAPI_DLL_LINKAGE 被定义为 DECLSPEC_IMPORT,这将导入 DLL 中的函数。
    • 如果 DECLSPEC_IMPORT 不可用,则 IPHLPAPI_DLL_LINKAGE 被定义为空,这意味着没有特定的链接属性。
  2. Windows API 家族分区:使用 WINAPI_PARTITION 宏来确定代码应该在哪些 Windows API 家族中可用。

    #pragma region Application Family or OneCore Family or Games Family
    #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES)
    
    • #pragma region 是一个编译器指令,用于标识一个代码区域的开始。在这个例子中,它被用来标识与特定 Windows API 家族相关的代码区域。
    • WINAPI_FAMILY_PARTITION 宏用于在编译时确定是否应该包含这段代码。这里,它检查是否应该为应用程序家族(WINAPI_PARTITION_APP)、系统家族(WINAPI_PARTITION_SYSTEM)或游戏家族(WINAPI_PARTITION_GAMES)编译这段代码。
  3. C++ 外部链接符号:当在 C++ 项目中使用 C 风格的函数时,需要使用 extern "C" 来确保链接符号的正确性。

    #ifdef __cplusplus
    extern "C" {
    #endif
    
    • #ifdef __cplusplus 检查是否在 C++ 环境中编译代码。
    • extern "C" 指示编译器接下来的函数应该使用 C 语言的链接规则,这对于 C/C++ 混编非常重要,因为它允许 C++ 编译器正确链接 C 函数。

这些代码段是构建跨平台 Windows 应用程序时常见的做法,确保了代码的可移植性和兼容性。

设置和获取网络信息的 MIB

//
//                                                                          //
// IPRTRMIB.H has the definitions of the structures used to set and get     //
// information                                                              //
//                                                                          //
//

#include <iprtrmib.h>
#include <ipexport.h>
#include <iptypes.h>
#include <tcpestats.h>

#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) */
#pragma endregion

#pragma region Desktop Family or OneCore Family or Games Family
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES)

这段代码继续说明了一些 C/C++ 编程概念,特别是在 Windows 平台开发中使用的一些技术和宏。下面是对这段代码的详细解释:

  1. 文件用途注释:注释首先指明了这个文件包含用于设置和获取网络信息的 MIB(Management Information Base)结构的定义。

  2. 包含其他头文件

    • #include <iprtrmib.h>:包含了定义 MIB-II 管理信息结构的头文件。
    • #include <ipexport.h>:包含了 IP 相关函数的导出声明。
    • #include <iptypes.h>:包含了 IP 地址相关的类型和常量定义。
    • #include <tcpestats.h>:包含了 TCP 统计信息的结构定义。
  3. 结束平台分区宏定义

    • #endif /* WINAPI_FAMILY_PARTITION(...) */:这部分代码是结束之前 #if#ifdef 语句的条件编译块,确保只有当编译环境符合指定的 Windows 平台家族时才包含这部分代码。
  4. 结束区域定义指令

    • #pragma endregion:指示编译器结束当前定义的区域。
  5. 开始新的平台分区宏定义

    • #pragma region Desktop Family or OneCore Family or Games Family:定义了一个新的代码区域,并命名它为与桌面、OneCore 或游戏相关的家族。
    • #if WINAPI_FAMILY_PARTITION(...):使用 WINAPI_FAMILY_PARTITION 宏来包含适用于桌面、系统或游戏家族的代码,这是 Windows 8 引入的用于编译特定平台代码的方法。

这段代码是典型的 Windows SDK 编程风格,使用宏和预处理指令来控制不同版本的 Windows 平台之间的代码。这种方式允许开发者编写可在多个 Windows 平台上运行的代码,同时确保了对特定平台特性的支持。

GetNumberOfInterfaces:检索系统中网络接口的数量

//
//                                                                          //
// The GetXXXTable APIs take a buffer and a size of buffer.  If the buffer  //
// is not large enough, the APIs return ERROR_INSUFFICIENT_BUFFER  and      //
// *pdwSize is the required buffer size                                     //
// The bOrder is a BOOLEAN, which if TRUE sorts the table according to      //
// MIB-II (RFC XXXX)                                                        //
//                                                                          //
//


//
//                                                                          //
// Retrieves the number of interfaces in the system. These include LAN and  //
// WAN interfaces                                                           //
//                                                                          //
//

IPHLPAPI_DLL_LINKAGE
DWORD
WINAPI
GetNumberOfInterfaces(
    _Out_ PDWORD  pdwNumIf
    );

这段注释和函数声明是Windows网络编程中的一部分,说明了如何使用API来获取系统中网络接口的数量。这里是对代码段的解释:

  1. 注释部分

    • 第一个注释块描述了 GetXXXTable 系列API的通用行为。这些API需要一个缓冲区和缓冲区大小作为参数。如果提供缓冲区不够大,API将返回 ERROR_INSUFFICIENT_BUFFER 错误,并设置 *pdwSize 为所需的缓冲区大小。
    • 第二个注释块提到了 bOrder 参数,这是一个布尔值,如果设为 TRUE,则会根据MIB-II标准(RFC XXXX,这里的 XXXX 可能是特定RFC文档的编号)对表格进行排序。
  2. 函数声明

    • 声明了 GetNumberOfInterfaces 函数,该函数是 iphlpapi.dll 库中的一个导出函数,用于检索系统中网络接口的数量,包括本地局域网(LAN)和广域网(WAN)接口。
  3. 函数细节

    • IPHLPAPI_DLL_LINKAGE 是一个链接指示符,指定了这个函数是DLL的一部分。
    • DWORD WINAPI GetNumberOfInterfaces(_Out_ PDWORD pdwNumIf); 这行声明了一个函数,其返回类型是 DWORD 类型,这是Windows API中常用的一个无符号32位整型,用于表示函数的错误代码或返回值。
    • _Out_ PDWORD pdwNumIf 是该函数的参数,_Out_ 指的是输出参数,PDWORD 是指向 DWORD 的指针,pdwNumIf 将会存储系统中网络接口的数量。

使用这个函数时,你会提供一个 DWORD 类型的指针,函数会将系统中网络接口的数量写入这个指针指向的内存地址。如果调用成功,返回值将为 ERROR_SUCCESS(通常定义为0),表示没有错误发生。如果返回值不是0,则表示调用失败,可以通过查阅相应的错误代码来确定失败的原因。

GetIfEntry:获取特定网络接口的 MIB-II ifEntry 信息

//
//                                                                          //
// Gets the MIB-II ifEntry                                                  //
// The dwIndex field of the MIB_IFROW should be set to the index of the     //
// interface being queried                                                  //
//                                                                          //
//

IPHLPAPI_DLL_LINKAGE
DWORD
WINAPI
GetIfEntry(
    _Inout_ PMIB_IFROW   pIfRow
    );

这段注释和函数声明描述了如何使用 Windows 平台的 IP Helper API 来获取特定网络接口的 MIB-II ifEntry 信息。

  1. 注释部分

    • 注释说明了 GetIfEntry 函数的用途,即获取特定网络接口的 MIB-II ifEntry 信息。MIB-II 是一个网络管理的标准,ifEntry 是其中的一个部分,代表网络接口的相关信息。
    • 指出 MIB_IFROW 结构体的 dwIndex 字段需要被设置为查询的接口的索引。这个索引通常是从1开始的,代表系统中的第一个网络接口。
  2. 函数声明

    • GetIfEntry 函数是 iphlpapi.dll 库中的一个导出函数,用于获取特定网络接口的详细信息。
    • IPHLPAPI_DLL_LINKAGE 是一个宏,用于指示该函数是 DLL 的一部分,确保正确的导出和导入。
  3. 函数参数

    • _Inout_ PMIB_IFROW pIfRowGetIfEntry 函数的参数,其中:
      • _Inout_ 是 SAL(Source Annotation Language)注解,表示这个参数既被读取也被修改。
      • PMIB_IFROW 是指向 MIB_IFROW 结构体的指针,MIB_IFROW 包含了网络接口的详细信息。
      • pIfRow 是这个指针的变量名,它指向一个已经初始化了 dwIndex 字段的结构体实例。
  4. 函数返回值

    • 函数返回一个 DWORD 类型的值,表示操作的结果。如果操作成功,返回 ERROR_SUCCESS(值通常为0)。如果操作失败,返回值将是一个错误代码,可以通过查阅 Windows API 文档来获取具体的错误信息。

使用 GetIfEntry 函数时,你需要先初始化一个 MIB_IFROW 结构体,设置其 dwIndex 字段为你想查询的网络接口的索引。然后,将这个结构体的地址传递给 GetIfEntry 函数。如果调用成功,MIB_IFROW 结构体将被填充,包含所查询接口的详细信息,如接口的索引、名称、类型、物理地址、操作状态等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奇树谦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值