Wintun API 模块深度解析(文档一):公共接口与项目结构
一、模块定位与整体架构
api文件夹是 Wintun 用户态动态库(wintun.dll)的完整源代码,它构成了开发者与 Wintun 驱动交互的唯一官方接口。该 DLL 封装了驱动安装、适配器管理、会话控制、数据包收发等全部功能,并以一套简洁、稳定的 C API 对外暴露(定义在wintun.h中)。
整个api模块采用分层设计:
- 公开接口层(
wintun.h):定义所有导出函数、常量和类型,供应用程序调用。 - 适配器管理层(
adapter.c/.h、adapter_win7.h、driver.c/.h):负责适配器的创建、打开、关闭、删除,以及驱动程序的安装/卸载。 - 会话与数据路径层(
session.c):管理数据会话的生命周期,实现高效的环形缓冲区收发。 - 辅助基础层(
logger、namespace、registry、resource、rundll32、nci、ntdll等):提供日志、同步、注册表、资源嵌入、WOW64 代理、网络配置等通用服务。
本文作为系列第一篇,聚焦公开接口定义、内部数据结构、项目构建配置,为后续深入理解各模块奠定基础。
二、公共头文件wintun.h详解
wintun.h是 Wintun 唯一需要用户引用的头文件,它定义了全部 API 函数原型、回调类型、常量和句柄类型。该头文件采用#pragma once和extern "C"包装,兼容 C/C++。
2.1 句柄类型与基本常量
typedefstruct_WINTUN_ADAPTER*WINTUN_ADAPTER_HANDLE;typedefstruct_TUN_SESSION*WINTUN_SESSION_HANDLE;- 两种不透明句柄,分别代表适配器和会话,内部结构在实现文件中定义,外部不可访问。
- 常量
WINTUN_MIN_RING_CAPACITY(128 KiB)和WINTUN_MAX_RING_CAPACITY(64 MiB)规定了会话环形缓冲区容量的合法范围。 WINTUN_MAX_IP_PACKET_SIZE(0xFFFF)定义了最大 IP 包大小(64 KiB)。
2.2 API 函数指针类型定义
头文件为每个导出函数定义了对应的函数指针类型(如WINTUN_CREATE_ADAPTER_FUNC),便于应用程序通过GetProcAddress动态加载。所有导出函数如下:
| 函数名 | 功能 |
|---|---|
WintunCreateAdapter | 创建新适配器(指定名称、隧道类型、可选 GUID) |
WintunOpenAdapter | 打开已存在的适配器(按名称) |
WintunCloseAdapter | 关闭并释放适配器(若由创建而来则同时删除) |
WintunDeleteDriver | 卸载驱动(当无适配器使用时) |
WintunGetAdapterLUID | 获取适配器的 NET_LUID(用于路由配置) |
WintunGetRunningDriverVersion | 查询当前加载的驱动版本号 |
WintunSetLogger | 设置全局日志回调 |
WintunStartSession | 启动数据会话(指定缓冲区容量) |
WintunEndSession | 结束会话 |
WintunGetReadWaitEvent | 获取读等待事件句柄(用于非阻塞等待) |
WintunReceivePacket | 从接收环中获取一个数据包 |
WintunReleaseReceivePacket | 释放已接收的数据包缓冲区 |
WintunAllocateSendPacket | 分配发送缓冲区 |
WintunSendPacket | 提交发送数据包 |
这些函数均采用WINAPI(__stdcall)调用约定,确保跨语言兼容。
2.3 日志回调类型
typedefenum{WINTUN_LOG_INFO,WINTUN_LOG_WARN,WINTUN_LOG_ERR}WINTUN_LOGGER_LEVEL;typedefVOID(CALLBACK*WINTUN_LOGGER_CALLBACK)(WINTUN_LOGGER_LEVEL Level,DWORD64 Timestamp,LPCWSTR Message);- 时间戳为 100 ns 间隔,自 1601-01-01 UTC(与 Windows FILETIME 一致)。
- 回调可能从多线程并发调用,需由调用方自行序列化。
三、内部头文件与数据结构
3.1adapter.h—— 适配器内部描述
typedefstruct_WINTUN_ADAPTER{HSWDEVICE SwDevice;// 软件设备句柄(Win8+)HDEVINFO DevInfo;// SetupAPI 设备信息集SP_DEVINFO_DATA DevInfoData;// 设备信息数据WCHAR*InterfaceFilename;// 设备对象文件名(如 \\.\Wintun_xxx)GUID CfgInstanceID;// 网络配置实例 GUID(NetCfgInstanceId)WCHAR DevInstanceID[MAX_DEVICE_ID_LEN];// 设备实例 IDDWORD LuidIndex;// NET_LUID 中的索引DWORD IfType;// 接口类型(IF_TYPE_SOFTWARE_LOOPBACK 等)DWORD IfIndex;// 接口索引(可选)}WINTUN_ADAPTER;此结构保存了适配器所有必要元数据,被各 API 函数频繁使用。
adapter.h还声明了内部辅助函数:
AdapterOpenDeviceObject:打开设备对象句柄(用于 IOCTL 通信)。AdapterGetDeviceObjectFileName:获取设备接口的文件名。AdapterCleanupOrphanedDevices:清理孤儿设备(无所有者进程)。AdapterRemoveInstance/AdapterEnableInstance/AdapterDisableInstance:底层设备操作,内部会判断是否需要通过rundll32代理(WOW64 场景)。
3.2driver.h—— 驱动管理接口
声明了驱动安装/卸载的核心函数:
DriverInstall:安装或升级 Wintun 驱动(比较版本、提取资源、调用 Setup API)。WintunDeleteDriver:删除驱动(当无适配器时)。WintunGetRunningDriverVersion:查询当前加载的驱动版本。
此外,driver.c中定义了驱动版本比较、文件版本提取、禁用/启用现有适配器等逻辑。
3.3 全局变量与 DLL 入口
main.h定义了全局变量:
ResourceModule:DLL 模块句柄(用于资源提取)。ModuleHeap:私有堆句柄(统一内存管理)。SecurityAttributes:安全描述符(限制仅为 SYSTEM 和 Administrators 访问)。IsLocalSystem:当前进程是否以 SYSTEM 身份运行。NativeMachine:当前进程所处的本机架构(用于决定是否启用 WOW64 代理)。IsWindows7/IsWindows10:版本标志,用于条件编译。
main.c中的DllMain负责:
- 创建私有堆。
- 初始化安全对象(创建包含 SYSTEM/管理员 SID 的安全描述符)。
- 获取操作系统版本和进程位数信息(通过
IsWow64Process2或IsWow64Process)。 - 初始化命名空间(
NamespaceInit)并清理旧版适配器(AdapterCleanupLegacyDevices)。 - 在卸载时释放资源。
延迟加载钩子(__pfnDliNotifyHook2)强制从System32加载延迟加载的 DLL,避免恶意 DLL 劫持。
四、项目构建配置(api.vcxproj)
4.1 基本设置
- 配置类型:
DynamicLibrary(生成wintun.dll)。 - 平台工具集:
WindowsApplicationForDrivers10.0——允许使用部分驱动开发包中的头文件和库,并支持cfgmgr32.h、devpkey.h等。 - 输出文件名:通过
<TargetName>wintun</TargetName>指定为wintun。
4.2 预处理器定义
根据平台定义MAYBE_WOW64(x86、x64、ARM 均有,ARM64 没有),用于条件编译代理调用逻辑。资源编译时还会检查是否已构建其他平台的代理 DLL(BUILT_ARM64_WOW64、BUILT_AMD64_WOW64),以便在资源中嵌入它们。
4.3 延迟加载与附加依赖
延迟加载了大量系统 DLL:
advapi32.dll、cfgmgr32.dll、iphlpapi.dll、setupapi.dll、shlwapi.dll、version.dll等,以及api-ms-win-devices-query-l1-1-0.dll(设备查询)和api-ms-win-devices-swdevice-l1-1-0.dll(软件设备)。- 链接库包括
onecore.lib(提供 SwDevice 等 API)、ntdll.lib(NtQuerySystemInformation等)、swdevice.lib等。
4.4 自定义生成步骤
BuildInfVersion:使用cscript.exe运行extract-driverver.js,从driver/wintun.inf中提取驱动版本和日期,生成wintun-inf.h供driver.c包含。这确保了驱动版本信息与 INF 文件同步。BuildNci:将nci.h(内联存根)和nci.def编译为nci.lib,用于动态链接nci.dll(Windows 的网络连接接口)。由于nci.dll没有导入库,因此通过自定义步骤生成。
4.5 资源嵌入
resources.rc编译后嵌入 DLL 资源,包含多个平台的驱动文件(wintun.sys、wintun.cat、wintun.inf)和代理 DLL(setupapihost*.dll)。这些资源在driver.c和rundll32.c中按需提取到临时目录使用。
五、模块间依赖关系
┌─────────────────┐ │ wintun.h │ (公开API) └────────┬────────┘ │ ┌────────────────────────┼─────────────────────────┐ │ │ │ ▼ ▼ ▼ ┌─────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ adapter.c/h │ │ session.c │ │ driver.c/h │ │(适配器管理)│ │(会话与数据路径)│ │(驱动安装/卸载) │ └──────┬──────┘ └────────┬────────┘ └──────────┬──────────┘ │ │ │ │ ┌──────────────┴──────────────┐ │ │ │ │ │ ▼ ▼ ▼ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ 辅助模块:logger, namespace, registry, resource, rundll32, nci │ └─────────────────────────────────────────────────────────────────┘adapter.c调用driver.c安装驱动,调用namespace获取互斥锁,调用registry读取配置,调用rundll32进行跨位数代理。session.c通过adapter.c打开设备对象,执行 IOCTL 注册环形缓冲区。logger被所有模块使用。resource用于提取嵌入式二进制文件。nci模块负责修改网络连接名称(NciSetConnectionName)。
六、总结
本文作为 API 模块系列的首篇,全面梳理了:
- 公共接口头文件
wintun.h的函数声明与类型定义。 - 内部关键数据结构(
WINTUN_ADAPTER、TUN_SESSION)及其作用。 - 项目构建配置的细节(资源嵌入、延迟加载、自定义生成步骤)。
- 各模块间的依赖关系和调用层次。
这些内容为后续深入分析适配器生命周期、数据路径和辅助机制提供了完整的上下文。在下一篇文章中,我们将深入剖析adapter.c与driver.c,揭示 Wintun 如何创建适配器、安装驱动,并优雅地处理 Windows 7 兼容性与 WOW64 代理调用。