Windows驱动开发(三)一个WDF入门实例
上一章大概介绍了WDM/WDF的IOControl,
链接:https://blog.csdn.net/o0xwh_93150o/article/details/104234021
鸽太久了,刚好闲下来,就把这个实例入门篇给补了吧。话不多说,先上代码。
DriverEntry例程:
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath) {
WDF_DRIVER_CONFIG config;
NTSTATUS status = STATUS_SUCCESS;
WDF_OBJECT_ATTRIBUTES attributes;
//
// Initialize WPP Tracing
//
WPP_INIT_TRACING( DriverObject, RegistryPath );
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
//
// Register a cleanup callback so that we can call WPP_CLEANUP when
// the framework driver object is deleted during driver unload.
//
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
attributes.EvtCleanupCallback = Spw_PCIeEvtDriverContextCleanup;
WDF_DRIVER_CONFIG_INIT(&config, Spw_PCIeEvtDeviceAdd);
status = WdfDriverCreate(DriverObject,
RegistryPath,
&attributes,
&config,
WDF_NO_HANDLE);
if (!NT_SUCCESS(status)) {
TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "WdfDriverCreate failed %!STATUS!", status);
WPP_CLEANUP(DriverObject);
return status;
}
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit");
return status;
}
每一个WDF驱动必须有一个DriverEntry例程,当操作系统监测到有硬件设备插入时,就会找到对应的DriverEntry例程,DriverEntry例程需要完成以下这些功能:
- 注册WDF的DeviceAdd回调函数,这是WDF驱动与NT驱动最大的不同之一
- 创建一个驱动对象,用于向框架注册我们的驱动程序
在WDF中,真正被我们当作初始化的函数,变成了DeviceAdd,所以可以把相关的初始化行为全部丢在DeviceAdd中。
DeviceAdd例程:
NTSTATUS
Spw_PCIeEvtDeviceAdd(_In_ WDFDRIVER Driver,
_Inout_ PWDFDEVICE_INIT DeviceInit) {
NTSTATUS status = STATUS_SUCCESS;
WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
WDF_OBJECT_ATTRIBUTES deviceAttributes;
WDFDEVICE device;
PDEVICE_CONTEXT deviceContext;
WDFQUEUE queue;
WDF_IO_QUEUE_CONFIG queueConfig;
UNREFERENCED_PARAMETER(Driver);
PAGED_CODE();
WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);
//When the I/O manager sends a request for buffered I/O, the IRP contains an internal copy of the caller's buffer
//rather than the caller's buffer itself. The I/O manager copies data from the caller's buffer to the internal buffer
//during a write request or from the internal buffer to the caller's buffer when the driver completes a read
//request.
//The WDF driver receives a WDF request object, which in turn contains an embedded WDF memory object.
//The memory object contains the address of the buffer on which the driver should operate.
//初始化即插即用和电源管理例程配置结构
WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
//设置即插即用基本例程
pnpPowerCallbacks.EvtDevicePrepareHardware = Spw_PCIeEvtDevicePrepareHardware;
pnpPowerCallbacks.EvtDeviceReleaseHardware = Spw_PCIeEvtDeviceReleaseHardware;
pnpPowerCallbacks.EvtDeviceD0Entry = Spw_PCIeEvtDeviceD0Entry;
pnpPowerCallbacks.EvtDeviceD0Exit = Spw_PCIeEvtDeviceD0Exit;
//注册即插即用和电源管理例程
WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);
//deviceAttributes.EvtCleanupCallback = Spw_PCIeEvtDriverContextCleanup;
//
// Set WDFDEVICE synchronization scope. By opting for device level
// synchronization scope, all the queue and timer callbacks are
// synchronized with the device-level spinlock.
//
deviceAttributes.SynchronizationScope = WdfSynchronizationScopeDevice;
status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);
if (!NT_SUCCESS(status)) {
return status;
}
deviceContext = GetDeviceContext(device);
//用default初始化default 队列,用另一个初始化非default队列
WDF_IO_QUEUE_CONFIG_INIT(&queueConfig,
WdfIoQueueDispatchSequential);
queueConfig.EvtIoDeviceControl = Spw_PCIeEvtIoDeviceControl;
status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue);
if (!NT_SUCCESS(status)) {
return status;
}
//非默认队列,必须指定要分发的I/O请求类型
//The WdfDeviceConfigureRequestDispatching method causes the framework to queue a specified type of I/O requests to a specified I/O queue.
status = WdfDeviceConfigureRequestDispatching(device,
queue,
WdfRequestTypeDeviceControl);
if (!NT_SUCCESS(status)) {
return status;
}
//创建驱动程序接口与应用程序通信
status = WdfDeviceCreateDeviceInterface(device,
(LPGUID)&GUID_DEVINTERFACE_Spw_PCIe,
NULL // ReferenceString);
if (!NT_SUCCESS(status)) {
return status;
}
return status;
}
此例程主要做了下面几件重要的事情:
- 创建初始化设备对象及其上下文
- 若该WDF驱动为支持PnP的,则要注册PnP相关的一系列回调函数
- 若该驱动需要处理IO,则需要配置一个消息队列,注册处理例程以及制定IO请求类型等等
- 若该驱动需要与其他程序进行交互,则可以注册一个GUID接口用于通信,当然,也可以使用符号链接的形式。
在PnP的管理例程注册部分,可以看到几个典型的回调,即PrepareHardware,ReleaseHardware,DeviceEntry以及DeviceExit。
PrepareHardware以及ReleaseHardware关系着你的硬件是否可以获得Windows分配的资源,而在PrepareHardware里面,你需要去实现内存资源,内存地址映射,IO端口映射以及CPU中断资源的分配等等。
在WDF中,给硬件分配资源的大致流程如下:
- 当插入一个PnP设备时,总线枚举驱动识别该设备
- 调用总线驱动的DeviceResourceQuery,创建资源列表
- 调用总线驱动的DeviceResourceRequirementQuery,创建资源需求列表
- 由PnP管理器来匹配驱动,随后申请必要的资源,将信息发送给驱动程序
- 当你的设备最终进入工作预备状态时,前面写的PrepareHardware即生效
- 之后进入到DeviceEntry例程,通常,DeviceEntry例程并需要额外处理事务
WDF的很多Sample之前在微软的msdn sample里面都有,包含了各种各样的硬件设备驱动,过滤驱动,枚举驱动等等,可惜不知道为什么被微软下架了。。。不过好在万能的百度上还是能找得到的,不过这里面的sample都没有去实现具体的功能,只是阐述了一个个驱动开发的模型,虽然代码量很小,但这已经是我们能看到的最好的例子了,熟悉了之后,自己去具体开发符合你需求的功能驱动就不那么困难。
后面的话,因为这几年做的很多实际的驱动,会不定期写一些笔记,当然,不在仅限于小端口驱动了~
Windows驱动开发(三)一个WDF入门实例相关推荐
- Windows驱动开发VXD/WDM/WDF/DDK/WDK的联系和区别
背景介绍 首先,先从基础的东西说起,做任何程序的开发,你都需要一个配套的开发套件,专业术语叫做SDK(Software Development Kit,软件开发套件).比如:开发JAVA程序,我们可能 ...
- c语言windows驱动编程入门,Windows驱动开发技术详解 PDF扫描版[175MB]
Windows驱动开发技术详解由浅入深.循序渐进地介绍了windows驱动程序的开发方法与调试技巧.本书共分23章,内容涵盖了windows操作系统的基本原理.nt驱动程序与wdm驱动程序的构造.驱动 ...
- windows驱动开发-WDF编程
文章目录 前言 WDF编程前的准备工作 WDF编程 创建驱动对象 创建设备对象 设备对象的回调函数 链表操作 驱动的测试代码 其他 前言 注:本文的完整代码见仓库 18-WDF-reflect 代码参 ...
- Windows驱动开发学习笔记(三)—— 内核空间内核模块
Windows驱动开发学习笔记(三)-- 内核空间&内核模块 内核空间 实验 第一步:编译如下代码 第二步:将 .sys 文件拷贝到虚拟机中 第三步:部署 .sys 文件并运行 第四步:创建一 ...
- Windows驱动开发入门系列教程
从事驱动开发也有一段时间了,从最初的无头苍蝇到懵懵懂懂,到入门,直至今天,感觉一路走来,走了不少的弯路,只因为没有人引导.前几天,一个朋友问到我怎么学习Windows驱动开发,我就想到把我学习Wind ...
- windows 驱动开发入门——驱动中的数据结构
最近在学习驱动编程方面的内容,在这将自己的一些心得分享出来,供大家参考,与大家共同进步,本人学习驱动主要是通过两本书--<独钓寒江 windows安全编程> 和 <windows驱动 ...
- windows驱动开发推荐书籍
[作者] 猪头三 个人网站 :http://www.x86asm.com/ [序言] 很多人都对驱动开发有兴趣,但往往找不到正确的学习方式.当然这跟驱动开发的本土化资 料少有关系.大多学的驱动开 ...
- 《Windows驱动开发技术详解》学习笔记
Abstract 如果推荐 Windows 驱动开发的入门书,我强烈推荐<Windows驱动开发技术详解>.但是由于成书的时间较早,该书中提到的很多工具和环境都已不可用或找不到,而本文 ...
- [Windows驱动开发](一)序言
笔者学习驱动编程是从两本书入门的.它们分别是<寒江独钓--内核安全编程>和<Windows驱动开发技术详解>.两本书分别从不同的角度介绍了驱动程序的制作方法. 在我理解,驱动程 ...
- windows驱动开发学习
序言] 很多人都对驱动开发有兴趣,但往往找不到正确的学习方式.当然这跟驱动开发的本土化资 料少有关系.大多学的驱动开发资料都以英文为主,这样让很多驱动初学者很头疼.本人从 事驱动开发时间不长也不短, ...
最新文章
- 运用C#生成docx格式的报表
- Django系列之启动入口源码分析
- 2009.11网络工程师考试案例试题学习攻略(1)
- lightroom 闪退_UP加速器闪退怎么办 UP加速器闪退解决方法
- 动态规划经典算法--最长公共子序列 LCS
- 【Trie】阅读理解(luogu 3879/ybtoj Trie-4)
- python - 基础算法题1- 使用while循环输入1 2 3 4 5 6 8 9 10
- 【LeetCode】【字符串】题号:*299. 猜数字游戏
- mapper同时添加数据只能添加一条_神器之通用mapper的使用
- python爬取网易云音乐歌词_python3爬取网易云音乐歌单里的歌词(含源码)
- 职场“奇葩说”:我的老板有多坑?
- SEERC 2017 J 	 Cunning Friends
- wlan协议—802.11n—802.11ac 5G和2.4G
- PageRank 计算博客园用户排名
- 百度飞桨(Python+AI)入门
- python3爬虫(4)各种网站视频下载方法
- 设计一个程序,程序中有三个类,Triangle,Lader,Circle。
- Syntax error parameterized types are only available if sourc
- SQL Server 2000 安装时出现 以前的某个程序安装已经在计算机上创建挂起的文件操作
- [转]NFA/DFA算法
热门文章
- 两万常用汉字的拼音+首字母缩写+unicode编码对照表
- python面向对象编程指南 豆瓣_Python面向对象编程
- 2339: [HNOI2011]卡农
- vulhub学习(1) ActiveMQ反序列化漏洞(CVE-2015-5254)复现
- Oracle12c使用AFD(Oracle ASM Filter Driver)特性部署集群的配置方法
- html 给表格添加背景颜色,HTML表格标记教程(7):背景颜色属性BGCOLOR
- mysql临时表更新_MySql 临时表
- 国内有哪些不错的CV(计算机视觉)团队
- 奇趣携Red Bend推空中下载软件控件管理
- 计算机条件求和函数,在excel中怎样根据多个条件进行求和