Description
Write a Hello World Windows Driver (KMDF) Hello World 第一步。里面涉及相关依赖下载指引。
若是想用 Rust 开发,可以参考这个:windows-kernel-rs ,里面包含了常用的驱动编程思路和流程,Windows API 封装可使用官方提供的库: microsoft/windows-rs 。
开发大致流程
最核心的是:在 Windows-Driver-Samples 里扒相关源码,想办法跑起来,并在 demo 上更改。不建议自建项目,原因是环境依赖配置一大堆,对于接触 Visual Studio 不深的人来讲,简直要命。 另外由于闭源,你也无法从根本上去梳理整个架构,只能看文档怎么说,而往往文档总是存在滞后性和编排不合理性。
开发完毕后,还需要过EV代码签名(3800+)+ 微软认证,否则客户机器上无法使用。
参考: 通过证明对 Windows 10 及更高版本的驱动程序进行签名 - Windows drivers
避坑 | Windows驱动签名经验贴
Debug 流程
- 准备虚拟机/测试机
下载 windows.ios (不要用家庭版,Admin 权限在此版本下有限制),用虚拟机安装镜像,并设定固定IP,我是使用 NAT 的方式来固定的,桥接貌似每次重启会变更IP。
将宿主机 WDK 包中的C:\Program Files (x86)\Windows Kits\10\Remote\x64
WDK Test Target Setup x64-x64_en-us.msi 复制到虚拟机,并安装。
在 Visual Studio 里的 Configure Devices 用IP添加设备,过程中会重启虚拟机,进入开发模式。
若是为了方便非驱动部分的调试,最好在虚拟机里安装完整的开发环境本地调试,目前 Windows 下的 C/Rust 的远程调试尚未找到好的方法论。 - Visual Studio Install Driver
项目->Driver Install->Deployment,选择 上一步骤配置的 Device,勾选 Hardware ID Driver Update,并输入INF文件里的 Standard.NT$ARCH$ -> hw-id 。若是通过软件安装驱动,则不需要如此。 - 拷贝文件到虚拟机
将宿主机的 DbgView.exe, TraceView.exe 拷贝过去用作调试工具,它们一般在 C:\Program Files (x86)\Windows Kits\10\Tools$VERSION\x64下。
代码中若只用了 KdPrint 打印日志,就只需要 DbgView.exe。记得用管理员权限打开,并点击 Capture > kernel 启动内核捕获。
若是使用了 WPP Trace,则更麻烦些,通过虚拟机共享宿主机驱动编译生成的 *.pdb 文件,TraceView.exe 在创建 LogSession 的时候需要用到,每次添加新的TraceEvents, 都需要重新创建LogSession, 否则会识别不了新创建的事件,最终发版后,可以通过从 *.pdb 文件抽取 TMF 文件,来协助定位问题。 - 生产日志跟踪
用 tracepdb 生成TMF文件:
cd C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x64
#生成 TMF 文件(多个),$OUT_PATH 要是空目录。
.\tracepdb.exe -f $PROJECT_PATH\x64\Debug$DRIVER_NAMME.pdb -p $OUT_PATH
将 OUT_PATH 拷贝到虚拟机,用 TraceView.exe 创建 Log Session,此步骤会用到 Trace.h 里的 TraceControlGUID 和 OUT_PATH 内的 TMF 文件。 注意 TraceView.exe 将 logSession 保存到 workspace 再打开会出问题: Flags 和 Level 会丢失掉,无法跟踪日志。这就导致每次打开 TraceView.exe 都需要重新创建 Log Session,可通过挂起虚拟机来使虚拟机保持状态。另外,每次添加或更改 Trace 代码,都需要重新生成 TMF 文件。
驱动的安装与卸载
我一般使用Visual Studio Debug 来安装,然后 用设备管理器-> 查看->显示隐藏的设备,找到对应的虚拟设备,删除设备并勾选删除驱动来解决。
# 参考:https://learn.microsoft.com/zh-cn/windows-hardware/drivers/devtest/devcon-migration
cd C:\DriverTest
# delete-driver 删除 驱动
pnputil.exe /delete-driver $PROJECT.inf /uninstall
# add-driver 创建测试设备并安装驱动程序
pnputil.exe /add-driver $PROJECT.inf /install
若有关联的 CommandLine App 用来调试驱动,需要将 App 以 Release 方式 Build,否则 Debug 模式编译出的应用在 虚拟机 上会加载动态dll,导致无法运行(最好在虚拟机内开发,方便debug)。
备注
- 用 WinObj.exe 可以查看当前设备树。Root 节点对应 GLOBAL?? 。
- 断点的使用体验很怪异,不知道是否是我使用的方法不对,目前先用日志来解决。
Driver 与 Device 通过代码安装与卸载
参考 Windows-samples setup/devcon 代码以及 将代码从 SetupApi 移植到 CfgMgr32 - Windows drivers。
完整的讲解参考:Device and Driver Installation - Windows drivers。
Driver 和 用户空间 通信方式
- COM(DLL) umdf V1 版本和老版本,umdf v2 已不再用
- File ioctl/read/write(device interface/symbolic)这个推荐使用
- share memory
遇到的坑整理
- 网上的资料老旧,其书籍大都是Windows 2000 时代的,WDF很少,若不是做兼容性开发,意义基本不大。WDF 只支持Win10+, win7/XP 需要用 WDM 开发框架来做。
- Visual Studio 的开发工具配套问题,很多项目都是用 2015/2019 版本做的开发,导致 2022 年的版本有很多无法打开。若是可以,一个 Visual Studio 版本配套一个虚拟环境。
- Visual Studio 2022 不支持 x86架构、Windows 7以下 的驱动开发,所以目前最好用 Visual Studio 2019 来做驱动开发。
- Visual Studio 不支持 Windows Driver WPP Trace, 所以不要用其 Debug Driver。
- Windows 的开发工具兼容性做的好,导致很多可被替代的 API 被大量使用,你在阅读代码/文档的时候,根本不知道是否这个API已有更好的替代品。
内存
- 内存可以写到硬盘(Paged)
- 内存对齐
Memory Management for Windows Drivers - Windows drivers
Windows 开发额外资料
DLL的生成、编写、调用总结_终不免俗的博客-CSDN博客_生成dll
lib和dll文件的区别和联系_冯相文要加油呀的博客-CSDN博客_dll和lib
INF 文件概述 - Windows drivers
不同的 IRP 处理方法 - 速查表 - Windows drivers
【Visual Studio 2019】创建 MFC 桌面程序 ( 安装 MFC 开发组件 | 创建 MFC 应用 | MFC 应用窗口编辑 | 为按钮添加点击事件 | 修改按钮文字 | 打开应用 ) 驱动开发之前,最好搞定最简单的MFC开发,好方便后续调试。
Youtube windows 开发讲解, 目前找到的最好入门资料,但也年代久远,OSR Driver Installer 等工具已不再维护。
Windows-driver-samples : windows 官方 example,写的比较完善,但注释和使用说明少,有很多 demo 最后一次更新都是几年前,需要老一些的 visual studio 搭配特定版本的 SDK 才能跑起来,README 里面关于代码编写流程可以参考。
Accessing device properties - Windows drivers