windows 驱动实例分析系列: wintun驱动分析-api篇(二)
Wintun API 模块深度解析文档二适配器生命周期与驱动管理一、概述本文档深入分析api模块中的适配器管理和驱动安装逻辑主要涉及文件adapter.c/adapter.hadapter_win7.hdriver.c/driver.hregistry.c/registry.h辅助读取注册表resource.c/resource.h提取嵌入式文件适配器管理是 Wintun 最核心的功能之一涵盖了从创建、打开、关闭、删除到孤儿设备清理的全过程。驱动安装则负责在首次使用或版本更新时将 Wintun 内核驱动wintun.sys和配套 INF/CAT 文件部署到系统。二、驱动安装与版本管理driver.c2.1 驱动版本检测WintunGetRunningDriverVersion通过NtQuerySystemInformation枚举已加载的内核模块查找名为wintun.sys的驱动然后读取其文件版本通过GetFileVersionInfo。若未加载返回 0 并设置ERROR_FILE_NOT_FOUND。内部辅助函数MaybeGetRunningDriverVersion(ReturnOneIfRunningInsteadOfVersion)支持仅检测是否存在返回 1用于等待驱动卸载。2.2 驱动安装流程DriverInstall此函数在WintunCreateAdapter中被调用首次创建适配器时。流程如下获取互斥锁通过NamespaceTakeDriverInstallationMutex()确保同一时刻只有一个进程执行安装避免竞争。创建设备信息使用SetupDiCreateDeviceInfoListExW创建网络设备类的一个临时设备信息元素设置硬件 ID 为Wintun。枚举已安装的兼容驱动通过SetupDiBuildDriverInfoList获取系统中所有匹配Wintun硬件 ID 的驱动。版本比较遍历每个驱动信息与 Wintun 内置驱动版本从 INF 提取的WINTUN_INF_VERSION和WINTUN_INF_FILETIME比较。如果现有驱动更新则直接使用如果内置驱动更新则禁用所有使用当前驱动创建的 Wintun 适配器调用DisableAllOurAdapters等待驱动卸载EnsureWintunUnloaded。调用SetupUninstallOEMInfW卸载旧驱动SUOI_FORCEDELETE强制删除。继续寻找下一个驱动。若没有找到可用驱动则执行全新安装使用ResourceCreateTemporaryDirectory在%WINDIR%\Temp下创建随机临时目录。根据本机架构NativeMachine从 DLL 资源中提取对应的wintun.sys、wintun.cat、wintun.inf到临时目录。调用SetupCopyOEMInfW将 INF 复制到系统驱动存储%SystemRoot%\INF完成安装。删除临时文件并移除目录。保存上下文将之前禁用的适配器列表通过输出参数DevInfoExistingAdaptersForCleanup和ExistingAdaptersForCleanup返回由调用方在适配器创建完成后重新启用它们通过DriverInstallDeferredCleanup。2.3 驱动卸载WintunDeleteDriver首先调用AdapterCleanupOrphanedDevices清理所有孤儿适配器无所有者进程。再次枚举匹配Wintun硬件 ID 的驱动对每个驱动调用SetupUninstallOEMInfW移除。此操作需获取驱动安装互斥锁且仅在无适配器使用时成功。2.4 版本比较逻辑IsNewer函数通过比较FILETIME和 64 位版本号高 16 位为主版本其次为次版本其次为构建号低 16 位为修订决定新旧。优先比较日期再比较版本号。三、适配器创建WintunCreateAdapter这是最复杂的函数需要处理 Windows 7/8/10 的不同 API并支持 WOW64 代理。3.1 前期准备获取设备安装互斥锁NamespaceTakeDeviceInstallationMutex。调用DriverInstall确保驱动已安装。分配并初始化WINTUN_ADAPTER结构。3.2 Windows 8 的软件设备创建路径步骤生成实例 ID若调用方提供了RequestedGUID则直接使用否则调用CoCreateGuid生成随机 GUID。将 GUID 转换为字符串作为设备实例 ID。创建存根设备Stub在 Windows 10 上先通过SwDeviceCreate创建一个临时的存根设备仅设置硬件 ID 为空字符串并在其软件注册表项中写入SuggestedInstanceId用于影响 NLA GUID。然后立即关闭该存根。此步骤的目的是为系统网络位置感知NLA提供确定的 GUID避免每次创建新适配器都生成新的 NLA 条目。创建主设备再次调用SwDeviceCreate传入实际的硬件 IDWINTUN_HWID和设备属性DEVPKEY_Wintun_Name用户指定的适配器名称如 “Demo”。DEVPKEY_Device_FriendlyName隧道类型名称 Tunnel。DEVPKEY_Device_DeviceDesc同上。设置标志SWDeviceCapabilitiesSilentInstall静默安装和SWDeviceCapabilitiesDriverRequired需要驱动。等待设备创建完成通过回调DeviceCreateCallback设置事件然后等待。等待接口可用调用WaitForInterface使用DevCreateObjectQuery查询设备接口GUID_DEVINTERFACE_NET是否已启用超时 15 秒。这确保了驱动已正确加载并注册了设备接口。打开设备信息通过SetupDiOpenDeviceInfo打开该设备然后调用PopulateAdapterData从注册表读取NetCfgInstanceId、NetLuidIndex、*IfType等关键信息。设置网络连接名称调用NciSetAdapterName内部使用NciSetConnectionName将网络连接显示名设置为用户指定的名称若冲突则自动添加序号后缀。Windows 7 特殊处理若系统为 Windows 7则路径不同见下文。3.3 Windows 7 的专用创建路径Windows 7 不支持SwDeviceCreate因此 Wintun 使用传统的 Setup API 进行设备创建参考adapter_win7.h中的CreateAdapterWin7函数创建设备信息元素设置硬件 ID 为Wintun。构建兼容驱动列表选中第一个匹配的驱动。依次调用DIF_REGISTERDEVICE、DIF_REGISTER_COINSTALLERS、DIF_INSTALLINTERFACES、DIF_INSTALLDEVICE。设置自定义属性DEVPKEY_Wintun_OwningProcess包含进程 ID 和创建时间用于孤儿设备清理。等待设备接口可用通过轮询检查注册表值和设备状态。返回设备实例 ID。3.4 WOW64 代理调用在 32 位进程运行于 64 位系统上时直接调用 Setup API 会失败。因此adapter.c中的AdapterRemoveInstance、AdapterEnableInstance、AdapterDisableInstance等函数会检查全局NativeMachine和IMAGE_FILE_PROCESS若不同则通过rundll32.c中的辅助函数启动 64 位代理进程setupapihost.dll来执行操作。代理调用的实现细节已在之前《setupapihost 深度解析》中详细说明此处不再重复。3.5 适配器打开WintunOpenAdapter枚举所有网络设备过滤枚举器为SWD\WintunWin8或ROOT\WintunWin7查找DEVPKEY_Wintun_Name与给定名称匹配的设备。获取设备实例 ID打开设备信息填充WINTUN_ADAPTER结构。同样等待接口可用并填充数据。3.6 适配器关闭WintunCloseAdapter若适配器由CreateAdapter创建具有SwDevice或通过 Windows 7 路径则调用AdapterRemoveInstance删除设备。否则只释放句柄不删除打开模式。释放内存后触发异步孤儿设备清理QueueUpOrphanedDeviceCleanupRoutine。3.7 孤儿设备清理AdapterCleanupOrphanedDevices孤儿设备是指那些没有关联进程或关联进程已退出的 Wintun 适配器。这类设备可能因进程崩溃或未正确调用CloseAdapter而遗留。清理逻辑Win8枚举所有网络设备检查设备状态是否有问题CM_Get_DevNode_Status的DN_HAS_PROBLEM。对于有问题的设备尝试通过DEVPKEY_Wintun_Name获取名称并调用AdapterRemoveInstance删除。Windows 7 特殊版本AdapterCleanupOrphanedDevicesWin7检查自定义属性DEVPKEY_Wintun_OwningProcess若进程不存在或进程创建时间不匹配则判定为孤儿并删除。此外AdapterCleanupLegacyDevices用于清理早期 Wintun 版本在ROOT\NET枚举器下遗留的设备。四、辅助函数与注册表操作4.1PopulateAdapterData从设备驱动注册表项DIREG_DRV读取NetCfgInstanceId转换为 GUID 存入CfgInstanceID。NetLuidIndex用于构造NET_LUID。*IfType接口类型。4.2AdapterGetDeviceObjectFileName通过CM_Get_Device_Interface_ListW获取设备接口的符号链接名如\\.\Wintun_{GUID}用于后续CreateFile打开设备对象。4.3WaitForInterface使用 Windows 8 引入的DevCreateObjectQuery创建设备查询等待设备接口启用超时 15 秒。若超时或失败记录详细错误信息包括问题代码和 NTSTATUS。4.4 名称冲突解决NciSetAdapterName调用NciSetConnectionName尝试设置网络连接名若返回ERROR_DUP_NAME则自动在名称后添加空格加数字序号最多尝试 1000 次并尝试重命名冲突的现有连接。五、总结本文详细剖析了 Wintun 适配器的创建、打开、关闭、删除流程以及驱动安装/卸载的完整机制。关键亮点包括跨版本兼容性为 Windows 7 保留传统 Setup API 路径同时为 Windows 8 使用更现代的软件设备模型。WOW64 透明代理自动检测进程位数通过rundll32启动代理 DLL 执行需要本机架构的 Setup API 调用。驱动版本管理智能比较现有驱动与内置驱动版本必要时升级并禁用/重新启用现有适配器。孤儿设备清理确保崩溃进程留下的适配器能被自动回收保持系统整洁。下一篇文章将转向会话管理与数据路径揭示 Wintun 高效收发的核心——环形缓冲区与无锁设计。

相关新闻

从按键精灵到按键猫咪:全键盘自动化脚本实战指南

从按键精灵到按键猫咪:全键盘自动化脚本实战指南

1. 项目概述:从“按键精灵”到“按键猫咪”的进化如果你曾经为了在电脑上重复执行一些简单操作而烦恼,比如在游戏里自动点击、在办公软件里批量处理数据,或者只是想写个小脚本解放双手,那你大概率听说过“按键精灵”这类工具。它几…

2026/10/13 0:16:51 阅读更多 →
Ubuntu国内镜像源配置全攻略:APT换源原理与实战优化

Ubuntu国内镜像源配置全攻略:APT换源原理与实战优化

1. 项目概述:为什么Ubuntu国内源配置是每个用户的必修课 如果你刚接触Ubuntu,或者已经用了一段时间,但总觉得系统更新、安装软件时速度慢得让人抓狂,动不动就卡在“正在连接 archive.ubuntu.com”上,那这篇文章就是为你…

2026/10/14 16:53:30 阅读更多 →
安卓USB转串口开发实战:从原理到应用,打造移动串口调试工具

安卓USB转串口开发实战:从原理到应用,打造移动串口调试工具

1. 项目概述:当安卓遇上串口作为一名在嵌入式开发和移动应用领域摸爬滚打了十多年的老手,我经常遇到一个经典场景:如何让一部安卓手机或平板,与一个只有串口的设备(比如单片机、工控板、传感器模块)直接“对…

2026/10/14 18:26:39 阅读更多 →

最新新闻

Transformer为什么强?解析全局建模、并行计算与多模态扩展优势

Transformer为什么强?解析全局建模、并行计算与多模态扩展优势

最近总有人问我同一个问题:Transformer 到底比其他模型强在哪。我做了几年序列建模相关的工作,文本分类、机器翻译、多模态对齐这些任务都反复折腾过,每次换架构、调参、对比实验做下来,对“强”字的理解其实和刚接触时不太一样。…

2026/10/15 16:46:53 阅读更多 →
Enriched MarkdownText组件详解:如何用一个组件呈现完整的Markdown富文本

Enriched MarkdownText组件详解:如何用一个组件呈现完整的Markdown富文本

【免费下载链接】enriched-markdown Multiplatform Markdown-Based Rich Text Solution 项目地址: https://gitcode.com/gh_mirrors/re/enriched-markdown 点击查看 免费下载 Enriched Markdown 是一个跨平台的 Markdown 富文本解决方案(Multiplatform …

2026/10/15 16:46:53 阅读更多 →
报纸杂志HTML5模板:语义结构、印刷排版与EPUB3全链路实践

报纸杂志HTML5模板:语义结构、印刷排版与EPUB3全链路实践

简介:这是一套专为新闻媒体类网站打造的HTML5响应式网页模板,面向中小型报社、杂志社及内容创作者,解决其快速搭建专业、易读、多媒体兼容的在线出版平台的需求。模板包含11个功能完备的子页面(如首页、文章详情页、分类页、作者页…

2026/10/15 16:46:53 阅读更多 →
Matlab多目标优化实战:gamultiobj与paretosearch从入门到避坑

Matlab多目标优化实战:gamultiobj与paretosearch从入门到避坑

简介:这份资源面向需要在 MATLAB 中处理多目标优化问题的学生、科研人员与工程技术人员,核心是借助遗传算法求解相互冲突目标之间的帕累托最优解集。压缩包共 15 个文件,以 8 个 m 脚本和 7 个 asv 自动备份文件为主,整体约 8KB&a…

2026/10/15 16:46:53 阅读更多 →
Pure Control 实战:从 P 到 PI 的快速整定与避坑指南

Pure Control 实战:从 P 到 PI 的快速整定与避坑指南

简介:这份资源是面向控制工程学习者与科研人员的MATLAB/Simulink实践资料包,围绕纯控制理论展开,适合已具备一定控制基础、希望借助仿真加深理解的中高级读者。压缩包共546个文件,约6.72MB,以296个mat数据文件、58个l与…

2026/10/15 16:46:53 阅读更多 →
USB-A转USB-C线缆选购指南:从电流规格到E-Marker芯片的全面解析

USB-A转USB-C线缆选购指南:从电流规格到E-Marker芯片的全面解析

1. 从抽屉里那根线说起:USB-A转USB-C到底解决了什么问题 几乎每个人的抽屉里都躺着几根线:一头是扁扁的矩形接口,另一头是椭圆形的正反插接口。前者是USB-A,后者是USB-C。很多人对这根线的认知停留在“能充电就行”,但…

2026/10/15 16:45:53 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →