上一章大概介绍了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例程需要完成以下这些功能:

  1. 注册WDF的DeviceAdd回调函数,这是WDF驱动与NT驱动最大的不同之一
  2. 创建一个驱动对象,用于向框架注册我们的驱动程序

在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;

}

此例程主要做了下面几件重要的事情:

  1. 创建初始化设备对象及其上下文
  2. 若该WDF驱动为支持PnP的,则要注册PnP相关的一系列回调函数
  3. 若该驱动需要处理IO,则需要配置一个消息队列,注册处理例程以及制定IO请求类型等等
  4. 若该驱动需要与其他程序进行交互,则可以注册一个GUID接口用于通信,当然,也可以使用符号链接的形式。

在PnP的管理例程注册部分,可以看到几个典型的回调,即PrepareHardware,ReleaseHardware,DeviceEntry以及DeviceExit。

PrepareHardware以及ReleaseHardware关系着你的硬件是否可以获得Windows分配的资源,而在PrepareHardware里面,你需要去实现内存资源,内存地址映射,IO端口映射以及CPU中断资源的分配等等。

在WDF中,给硬件分配资源的大致流程如下:

  1. 当插入一个PnP设备时,总线枚举驱动识别该设备
  2. 调用总线驱动的DeviceResourceQuery,创建资源列表
  3. 调用总线驱动的DeviceResourceRequirementQuery,创建资源需求列表
  4. 由PnP管理器来匹配驱动,随后申请必要的资源,将信息发送给驱动程序
  5. 当你的设备最终进入工作预备状态时,前面写的PrepareHardware即生效
  6. 之后进入到DeviceEntry例程,通常,DeviceEntry例程并需要额外处理事务

WDF的很多Sample之前在微软的msdn sample里面都有,包含了各种各样的硬件设备驱动,过滤驱动,枚举驱动等等,可惜不知道为什么被微软下架了。。。不过好在万能的百度上还是能找得到的,不过这里面的sample都没有去实现具体的功能,只是阐述了一个个驱动开发的模型,虽然代码量很小,但这已经是我们能看到的最好的例子了,熟悉了之后,自己去具体开发符合你需求的功能驱动就不那么困难。

后面的话,因为这几年做的很多实际的驱动,会不定期写一些笔记,当然,不在仅限于小端口驱动了~

Windows驱动开发(三)一个WDF入门实例相关推荐

  1. Windows驱动开发VXD/WDM/WDF/DDK/WDK的联系和区别

    背景介绍 首先,先从基础的东西说起,做任何程序的开发,你都需要一个配套的开发套件,专业术语叫做SDK(Software Development Kit,软件开发套件).比如:开发JAVA程序,我们可能 ...

  2. c语言windows驱动编程入门,Windows驱动开发技术详解 PDF扫描版[175MB]

    Windows驱动开发技术详解由浅入深.循序渐进地介绍了windows驱动程序的开发方法与调试技巧.本书共分23章,内容涵盖了windows操作系统的基本原理.nt驱动程序与wdm驱动程序的构造.驱动 ...

  3. windows驱动开发-WDF编程

    文章目录 前言 WDF编程前的准备工作 WDF编程 创建驱动对象 创建设备对象 设备对象的回调函数 链表操作 驱动的测试代码 其他 前言 注:本文的完整代码见仓库 18-WDF-reflect 代码参 ...

  4. Windows驱动开发学习笔记(三)—— 内核空间内核模块

    Windows驱动开发学习笔记(三)-- 内核空间&内核模块 内核空间 实验 第一步:编译如下代码 第二步:将 .sys 文件拷贝到虚拟机中 第三步:部署 .sys 文件并运行 第四步:创建一 ...

  5. Windows驱动开发入门系列教程

    从事驱动开发也有一段时间了,从最初的无头苍蝇到懵懵懂懂,到入门,直至今天,感觉一路走来,走了不少的弯路,只因为没有人引导.前几天,一个朋友问到我怎么学习Windows驱动开发,我就想到把我学习Wind ...

  6. windows 驱动开发入门——驱动中的数据结构

    最近在学习驱动编程方面的内容,在这将自己的一些心得分享出来,供大家参考,与大家共同进步,本人学习驱动主要是通过两本书--<独钓寒江 windows安全编程> 和 <windows驱动 ...

  7. windows驱动开发推荐书籍

    [作者]  猪头三  个人网站 :http://www.x86asm.com/ [序言]  很多人都对驱动开发有兴趣,但往往找不到正确的学习方式.当然这跟驱动开发的本土化资 料少有关系.大多学的驱动开 ...

  8. 《Windows驱动开发技术详解》学习笔记

    Abstract   如果推荐 Windows 驱动开发的入门书,我强烈推荐<Windows驱动开发技术详解>.但是由于成书的时间较早,该书中提到的很多工具和环境都已不可用或找不到,而本文 ...

  9. [Windows驱动开发](一)序言

    笔者学习驱动编程是从两本书入门的.它们分别是<寒江独钓--内核安全编程>和<Windows驱动开发技术详解>.两本书分别从不同的角度介绍了驱动程序的制作方法. 在我理解,驱动程 ...

  10. windows驱动开发学习

    序言]  很多人都对驱动开发有兴趣,但往往找不到正确的学习方式.当然这跟驱动开发的本土化资 料少有关系.大多学的驱动开发资料都以英文为主,这样让很多驱动初学者很头疼.本人从 事驱动开发时间不长也不短, ...

最新文章

  1. 运用C#生成docx格式的报表
  2. Django系列之启动入口源码分析
  3. 2009.11网络工程师考试案例试题学习攻略(1)
  4. lightroom 闪退_UP加速器闪退怎么办 UP加速器闪退解决方法
  5. 动态规划经典算法--最长公共子序列 LCS
  6. 【Trie】阅读理解(luogu 3879/ybtoj Trie-4)
  7. python - 基础算法题1- 使用while循环输入1 2 3 4 5 6 8 9 10
  8. 【LeetCode】【字符串】题号:*299. 猜数字游戏
  9. mapper同时添加数据只能添加一条_神器之通用mapper的使用
  10. python爬取网易云音乐歌词_python3爬取网易云音乐歌单里的歌词(含源码)
  11. 职场“奇葩说”:我的老板有多坑?
  12. SEERC 2017 J Cunning Friends
  13. wlan协议—802.11n—802.11ac 5G和2.4G
  14. PageRank 计算博客园用户排名
  15. 百度飞桨(Python+AI)入门
  16. python3爬虫(4)各种网站视频下载方法
  17. 设计一个程序,程序中有三个类,Triangle,Lader,Circle。
  18. Syntax error parameterized types are only available if sourc
  19. SQL Server 2000 安装时出现 以前的某个程序安装已经在计算机上创建挂起的文件操作
  20. [转]NFA/DFA算法

热门文章

  1. 两万常用汉字的拼音+首字母缩写+unicode编码对照表
  2. python面向对象编程指南 豆瓣_Python面向对象编程
  3. 2339: [HNOI2011]卡农
  4. vulhub学习(1) ActiveMQ反序列化漏洞(CVE-2015-5254)复现
  5. Oracle12c使用AFD(Oracle ASM Filter Driver)特性部署集群的配置方法
  6. html 给表格添加背景颜色,HTML表格标记教程(7):背景颜色属性BGCOLOR
  7. mysql临时表更新_MySql 临时表
  8. 国内有哪些不错的CV(计算机视觉)团队
  9. 奇趣携Red Bend推空中下载软件控件管理
  10. 计算机条件求和函数,在excel中怎样根据多个条件进行求和