WDF驱动必须用WDK编译,不可用VS默认工具链;DriverEntry仅初始化驱动对象并设卸载回调,设备操作须在EvtDriverDeviceAdd中完成;调试须用WinDbg内核调试,INF文件为加载必需,对象生命周期由WDF框架自动管理。

WDF驱动必须用WDK编译,不能用普通Visual Studio默认工具链
WDF驱动不是普通C++程序,它不链接CRT,也不走Windows用户态API调用路径。你用VS新建一个空C++项目然后照着写DriverEntry,编译会直接失败——链接器找不到WdfDriverCreate等符号,或者报unresolved external symbol _imp__WdfDriverCreate@16这类错误。
真正能编译WDF驱动的只有WDK(Windows Driver Kit)配套的编译环境,它自带专用的build工具和msbuild targets,且依赖特定版本的Windows SDK和编译器(比如WDK 22H2要求VS 2022 17.4+)。Visual Studio里必须安装“Windows驱动开发”工作负载,并在项目属性中显式选中“Windows Driver”类型。
- 不要手动改
Configuration Type为Application或Static Library - 不要在项目里添加
#include <stdio.h>或调用printf——WDF驱动里没有标准输出 - WDK工程模板生成的
.vcxproj里会有<DriverType>WDF</DriverType>和<TargetName>MyFilter</TargetName>等关键节点,删掉就编译不过
DriverEntry里只做初始化,别写业务逻辑
DriverEntry函数是WDF驱动入口,但它执行时处于内核早期阶段,很多资源还没就绪。常见错误是把设备创建、注册回调、分配内存全塞进去,结果触发蓝屏(比如KMODE_EXCEPTION_NOT_HANDLED),或驱动加载后立刻被系统卸载(STATUS_INVALID_PARAMETER)。
正确做法是只做三件事:校验参数、创建WDF驱动对象、设置卸载回调。所有设备相关操作(如创建控制设备对象、注册IRP回调)必须放到EvtDriverDeviceAdd里——这是WDF框架在收到PnP请求后才调用的函数。
立即学习“C++免费学习笔记(深入)”;
-
DriverEntry中禁止调用WdfControlDeviceInitAllocate或WdfDeviceCreate -
EvtDriverDeviceAdd才是创建设备对象的地方,每个物理/功能设备对应一次调用 - 如果驱动要支持即插即用,
WdfFdoInitSetDefaultChildListConfig这类配置也得放在这里,不能提前
NTSTATUS
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
WDF_DRIVER_CONFIG config;
WDF_OBJECT_ATTRIBUTES attrs;
<pre class='brush:php;toolbar:false;'>WDF_DRIVER_CONFIG_INIT(&config, EvtDriverDeviceAdd);
config.EvtDriverUnload = EvtDriverUnload;
WDF_OBJECT_ATTRIBUTES_INIT(&attrs);
return WdfDriverCreate(DriverObject, RegistryPath, &attrs, &config, WDF_NO_HANDLE);}
调试驱动必须用WinDbg Preview + 内核调试连接,VS附加进程无效
你不能像调试用户程序那样,在VS里按F5启动WDF驱动——它没有入口点可断点,也没有console窗口。试图用VS“附加到进程”调试svchost.exe或services.exe也毫无意义,因为驱动代码运行在内核空间,完全隔离。
真实调试流程是:目标机启用内核调试(bcdedit /debug on),宿主机用WinDbg Preview通过串口/网络/USB连接,加载符号(.sympath指向你的.pdb文件),再用!drvobj MyDriver 2确认驱动已加载,最后在EvtDriverDeviceAdd或IRP处理函数下断点。
- 忘记加载符号会导致断点全部失效,WinDbg显示
*** ERROR: Module load completed but symbols could not be loaded for MyDriver.sys - 用
lm命令检查模块是否真被加载;用!wdfkd.wdflogdump查WDF内部日志 - 驱动崩溃时,WinDbg自动停在异常位置,但堆栈可能被优化打乱——编译时务必关掉
/O2,启用/Zi和/DEBUG:FULL
INF文件不是可选配件,没它系统根本不会加载你的驱动
WDF驱动不能双击安装,也不能靠注册表硬塞。Windows只认INF文件描述的硬件ID、服务配置和签名策略。哪怕MyDriver.sys放在%SystemRoot%\System32\drivers\下,没有对应INF,设备管理器里也不会出现,sc create也会失败并报1275: This driver has been blocked from loading。
INF里最关键的三块是:[Version]段指定Class=System或具体设备类;[SourceDisksFiles]声明驱动文件名;[MyDriver.NT.Services]段必须包含AddService=MyDriver,0x00000002,MyDriver_Service_Inst,其中0x00000002表示启动类型为SERVICE_DEMAND_START(手动)或SERVICE_BOOT_START(启动时)。
- INF里
DriverVer日期格式必须是MM/DD/YYYY,写成2024-05-20会导致安装失败 - 测试阶段可用
Inf2Cat生成cat文件,但最终发布必须用EV证书签名,否则Win10/11默认拒绝加载 - 用
pnputil -i -a MyDriver.inf安装,失败时看pnputil返回的具体错误码,比如0x80070002通常意味着INF路径错或文件名不匹配
WDF驱动开发里最易被忽略的点是:所有对象生命周期都由WDF框架托管,你不能用delete或ExFreePool手动释放WDFDEVICE、WDFQUEUE等句柄——它们会在父对象析构时自动清理。过早调用WdfObjectDelete或漏掉WdfObjectGetTypedContext的类型检查,问题往往延迟到卸载时才爆发。









