第一个驱动程序:Hello World 驱动编写

说实话,每个驱动开发者的起点都一样——写一个Hello World。我当年入行时,师傅丢给我一句话:“先让系统把你的代码跑起来,再说别的。”今天我们就来走完这第一步。

DriverEntry 与 DriverUnload 例程

驱动程序的入口点,不是main函数,而是DriverEntry。它就像一扇门,系统加载驱动时第一个敲的就是它。

#include <ntddk.h>

NTSTATUS DriverEntry(
    _In_ PDRIVER_OBJECT  DriverObject,
    _In_ PUNICODE_STRING RegistryPath
)
{
    DbgPrint("Hello World! 驱动已加载\n");

    // 设置卸载例程
    DriverObject->DriverUnload = DriverUnload;

    return STATUS_SUCCESS;
}

VOID DriverUnload(
    _In_ PDRIVER_OBJECT DriverObject
)
{
    DbgPrint("驱动已卸载,再见!\n");
}

这里有个细节我想强调一下:DbgPrint 的输出,你用 DebugView 才能看到。我第一次写驱动时,傻傻盯着控制台等了半天……嗯,后来才知道要看调试输出。

关键点:DriverEntry 必须返回 STATUS_SUCCESS,否则系统认为加载失败。DriverUnload 是必须注册的,不然驱动卸载时会蓝屏。

INF 文件结构解析

INF 文件是驱动的身份证。没有它,Windows 不认识你的驱动。我见过不少新手,代码写得挺好,结果 INF 写错了,安装死活不成功。

一个最简的 INF 文件长这样:

[Version]
Signature="$WINDOWS NT$"
Class=Sample
ClassGuid={78A1C341-4539-11D3-B98D-00C04F8EFB5C}
Provider=%ManufacturerName%
DriverVer=09/21/2024,1.0.0.0

[Manufacturer]
%ManufacturerName%=Standard,NTamd64

[Standard.NTamd64]
%DeviceDesc%=MyDevice_Inst,*PNP0000

[MyDevice_Inst]
CopyFiles=MyDevice.CopyFiles

[MyDevice.CopyFiles]
MyDriver.sys

[Strings]
ManufacturerName="MyCompany"
DeviceDesc="My Hello World Driver"

结构其实不复杂,我拆开给你看:

节 作用
[Version] 声明驱动版本、签名信息
[Manufacturer] 指定厂商和平台架构
[Standard.NTamd64] 硬件ID与驱动安装节的映射
[MyDevice_Inst] 安装指令,比如复制文件
[Strings] 字符串常量定义,避免硬编码

我的习惯:每次写 INF 文件,我都会先复制一个能用的模板,再改参数。从头写容易漏掉 ClassGuid 这种细节。

驱动签名与测试模式

64位 Windows 强制要求驱动签名。不签名的驱动,系统直接拒绝加载。我在项目中遇到过这种情况:调试好的驱动,换到客户机器上死活装不上,最后发现是签名问题。

开发阶段怎么办?开启测试模式:

bcdedit /set testsigning on

重启后,桌面右下角会出现“测试模式”水印。这时候你就可以加载未签名的驱动了。

注意:测试模式仅用于开发机。生产环境必须使用正式签名。我曾经见过有人把测试模式的驱动部署到服务器上,结果安全策略直接拦截,系统日志里全是错误。

签名的流程大致是:

  1. 生成证书(测试用自签名,正式用CA签发)
  2. 使用 SignTool 对 .sys 文件签名
  3. 在 INF 文件中添加签名信息
  4. 使用 Catalog 文件打包签名

说白了,签名就是给驱动盖个章,告诉系统“这东西是安全的”。

知识体系结构图

下面这张图,帮你理清本章的核心脉络:

Hello World 驱动开发核心流程 代码编写 DriverEntry + DriverUnload INF 文件 版本、厂商、安装指令 签名与测试 测试模式 / 正式签名 DbgPrint 调试输出 注册卸载回调 [Version] 签名声明 [Strings] 字符串定义 bcdedit 开启测试模式 SignTool 签名流程 最终目标:驱动成功加载,输出 Hello World

避坑指南:我曾经在 INF 文件中写错了 ClassGuid,结果设备管理器里驱动显示黄色感叹号。排查了半天才发现是 GUID 不对。建议你直接从 WDK 示例中复制 GUID,别自己编。

好了,第一个驱动就这么简单。代码不到20行,INF文件不到30行。你想想看,驱动开发其实没那么神秘,对吧?


可可精品资料库