驱动模型区分:
WDM 必须满足n种被要求的特性(如电源管理,即插即用);如果没有这些功能,则统一称为NT式驱动;如果调用了WDF的内核API,则称为WDF驱动。
本书关注于通用的内核程序开发,不是针对某种硬件。例如,文件系统驱动,存储设备驱动,网络驱动。不是为了驱动某个硬件,而是在通用的windows上实现某种功能。
开发环境的搭建:
下载WDK,编译调试。无需VS,VS只是方便工程管理和编码。
因为不是应用程序,所以所有win32API都不能使用。部分C Runtime函数也不能使用,但文档中说明的函数则可以使用。
简单代码示例:
#include <ntddk.h>// 提供一个Unload函数只是为了 VOID DriverUnload(PDRIVER_OBJECT driver) {// 但是实际上我们什么都不做,只打印一句话:DbgPrint("first: Our driver is unloading…\r\n"); }// DriverEntry,入口函数。相当于main。 NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path) { #if DBG // _asm int 3 #endif// 这是我们的内核模块的入口,可以在这里写入我们想写的东西。// 我在这里打印一句话。因为”Hello,world” 常常被高手耻笑,所以// 我们打印一点别的。DbgPrint("first: Hello, my salary!");// 设置一个卸载函数便于这个函数能退出。driver->DriverUnload = DriverUnload;return STATUS_SUCCESS; }
DriverEntry 是每个内核模块的入口,在加载这个模块时,被系统进程System调用一次。
设置DriverUnload函数指针,这样这个模块可以被动态地卸载。如果没有设置DriverUnload指针,则一个内核模块一旦被加载就不能卸载了。
增加两个文件,以便WDK build。
makefile,直接到Sample下找个,无需修改。sources,需要编译那些文件,只需要.c,不要加入.h,以及编译.sys的名字。
TARGETNAME=first TARGETTYPE=DRIVER SOURCES=first.c TARGETPATH=obj
编译选择,Check,Free。build。
安装工具
srvinstw.exe,通过“安装服务”,指定.sys文件路径,“设备驱动”,指定为“手动”,安装驱动。
通过“net start xxx”启动驱动。“net stop xxx”停止驱动。(系统软件服务列表中,是不显示该项的)
虚拟机调试配置,以在前面的Blog中写明。
调试
windbg下载安装。设置Symbol,SourceFile,Image。Windbg把内核视为一个整体,没有必要告诉它需要调试哪个具体的模块。只要指定
Symbol和Source。
在设置断点不方便的地方,小技巧。
#if DBG
_asm int 3 //等于手动设置断点,但是只在调试状态,在非调试状态会蓝屏。
#endif