1、WDM.h

[cpp] view plain copy
  1. /************************************************************************
  2. * 文件名称:HelloWDM.h
  3. * 作    者:张帆
  4. * 完成日期:2007-11-1
  5. *************************************************************************/
  6. #ifdef __cplusplus
  7. extern "C"
  8. {
  9. #endif
  10. #include <wdm.h>
  11. #ifdef __cplusplus
  12. }
  13. #endif
  14. typedef struct _DEVICE_EXTENSION
  15. {
  16. PDEVICE_OBJECT fdo;
  17. PDEVICE_OBJECT NextStackDevice;
  18. UNICODE_STRING ustrDeviceName;  // 设备名
  19. UNICODE_STRING ustrSymLinkName; // 符号链接名
  20. } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
  21. #define PAGEDCODE code_seg("PAGE")
  22. #define LOCKEDCODE code_seg()
  23. #define INITCODE code_seg("INIT")
  24. #define PAGEDDATA data_seg("PAGE")
  25. #define LOCKEDDATA data_seg()
  26. #define INITDATA data_seg("INIT")
  27. #define arraysize(p) (sizeof(p)/sizeof((p)[0]))
  28. NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject,
  29. IN PDEVICE_OBJECT PhysicalDeviceObject);
  30. NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo,
  31. IN PIRP Irp);
  32. NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo,
  33. IN PIRP Irp);
  34. void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject);
  35. extern "C"
  36. NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
  37. IN PUNICODE_STRING RegistryPath);

2、WDM.c

[cpp] view plain copy
  1. /************************************************************************
  2. * 文件名称:HelloWDM.cpp
  3. * 作    者:张帆
  4. * 完成日期:2007-11-1
  5. *************************************************************************/
  6. #include "HelloWDM.h"
  7. /************************************************************************
  8. * 函数名称:DriverEntry
  9. * 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象
  10. * 参数列表:
  11. pDriverObject:从I/O管理器中传进来的驱动对象
  12. pRegistryPath:驱动程序在注册表的中的路径
  13. * 返回 值:返回初始化驱动状态
  14. *************************************************************************/
  15. #pragma INITCODE
  16. extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,
  17. IN PUNICODE_STRING pRegistryPath)
  18. {
  19. KdPrint(("Enter DriverEntry\n"));
  20. pDriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;
  21. pDriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;
  22. pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
  23. pDriverObject->MajorFunction[IRP_MJ_CREATE] =
  24. pDriverObject->MajorFunction[IRP_MJ_READ] =
  25. pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloWDMDispatchRoutine;
  26. pDriverObject->DriverUnload = HelloWDMUnload;
  27. KdPrint(("Leave DriverEntry\n"));
  28. return STATUS_SUCCESS;
  29. }
  30. /************************************************************************
  31. * 函数名称:HelloWDMAddDevice
  32. * 功能描述:添加新设备
  33. * 参数列表:
  34. DriverObject:从I/O管理器中传进来的驱动对象
  35. PhysicalDeviceObject:从I/O管理器中传进来的物理设备对象
  36. * 返回 值:返回添加新设备状态
  37. *************************************************************************/
  38. #pragma PAGEDCODE
  39. NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject,
  40. IN PDEVICE_OBJECT PhysicalDeviceObject)
  41. {
  42. PAGED_CODE();
  43. KdPrint(("Enter HelloWDMAddDevice\n"));
  44. NTSTATUS status;
  45. PDEVICE_OBJECT fdo;
  46. UNICODE_STRING devName;
  47. RtlInitUnicodeString(&devName,L"\\Device\\MyWDMDevice");
  48. status = IoCreateDevice(
  49. DriverObject,
  50. sizeof(DEVICE_EXTENSION),
  51. &(UNICODE_STRING)devName,
  52. FILE_DEVICE_UNKNOWN,
  53. 0,
  54. FALSE,
  55. &fdo);
  56. if( !NT_SUCCESS(status))
  57. return status;
  58. PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
  59. pdx->fdo = fdo;
  60. pdx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);
  61. UNICODE_STRING symLinkName;
  62. RtlInitUnicodeString(&symLinkName,L"\\DosDevices\\HelloWDM");
  63. pdx->ustrDeviceName = devName;
  64. pdx->ustrSymLinkName = symLinkName;
  65. status = IoCreateSymbolicLink(&(UNICODE_STRING)symLinkName,&(UNICODE_STRING)devName);
  66. if( !NT_SUCCESS(status))
  67. {
  68. IoDeleteSymbolicLink(&pdx->ustrSymLinkName);
  69. status = IoCreateSymbolicLink(&symLinkName,&devName);
  70. if( !NT_SUCCESS(status))
  71. {
  72. return status;
  73. }
  74. }
  75. fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE; //驱动创建的设备有三种工作方式,缓冲区方式、直接方式和其他方式。
  76. fdo->Flags &= ~DO_DEVICE_INITIALIZING;
  77. KdPrint(("Leave HelloWDMAddDevice\n"));
  78. return STATUS_SUCCESS;
  79. }
  80. /************************************************************************
  81. * 函数名称:DefaultPnpHandler
  82. * 功能描述:对PNP IRP进行缺省处理
  83. * 参数列表:
  84. pdx:设备对象的扩展
  85. Irp:从IO请求包
  86. * 返回 值:返回状态
  87. *************************************************************************/
  88. #pragma PAGEDCODE
  89. NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP Irp)
  90. {
  91. PAGED_CODE();
  92. KdPrint(("Enter DefaultPnpHandler\n"));
  93. IoSkipCurrentIrpStackLocation(Irp);
  94. KdPrint(("Leave DefaultPnpHandler\n"));
  95. return IoCallDriver(pdx->NextStackDevice, Irp);
  96. }
  97. /************************************************************************
  98. * 函数名称:HandleRemoveDevice
  99. * 功能描述:对IRP_MN_REMOVE_DEVICE IRP进行处理
  100. * 参数列表:
  101. fdo:功能设备对象
  102. Irp:从IO请求包
  103. * 返回 值:返回状态
  104. *************************************************************************/
  105. #pragma PAGEDCODE
  106. NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp)
  107. {
  108. PAGED_CODE();
  109. KdPrint(("Enter HandleRemoveDevice\n"));
  110. Irp->IoStatus.Status = STATUS_SUCCESS;
  111. NTSTATUS status = DefaultPnpHandler(pdx, Irp);
  112. IoDeleteSymbolicLink(&(UNICODE_STRING)pdx->ustrSymLinkName);
  113. //调用IoDetachDevice()把fdo从设备栈中脱开:
  114. if (pdx->NextStackDevice)
  115. IoDetachDevice(pdx->NextStackDevice);
  116. //删除fdo:
  117. IoDeleteDevice(pdx->fdo);
  118. KdPrint(("Leave HandleRemoveDevice\n"));
  119. return status;
  120. }
  121. /************************************************************************
  122. * 函数名称:HelloWDMPnp
  123. * 功能描述:对即插即用IRP进行处理
  124. * 参数列表:
  125. fdo:功能设备对象
  126. Irp:从IO请求包
  127. * 返回 值:返回状态
  128. *************************************************************************/
  129. #pragma PAGEDCODE
  130. NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo,
  131. IN PIRP Irp)
  132. {
  133. PAGED_CODE();
  134. KdPrint(("Enter HelloWDMPnp\n"));
  135. NTSTATUS status = STATUS_SUCCESS;
  136. PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
  137. PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
  138. static NTSTATUS (*fcntab[])(PDEVICE_EXTENSION pdx, PIRP Irp) =
  139. {
  140. DefaultPnpHandler,      // IRP_MN_START_DEVICE
  141. DefaultPnpHandler,      // IRP_MN_QUERY_REMOVE_DEVICE
  142. HandleRemoveDevice,     // IRP_MN_REMOVE_DEVICE
  143. DefaultPnpHandler,      // IRP_MN_CANCEL_REMOVE_DEVICE
  144. DefaultPnpHandler,      // IRP_MN_STOP_DEVICE
  145. DefaultPnpHandler,      // IRP_MN_QUERY_STOP_DEVICE
  146. DefaultPnpHandler,      // IRP_MN_CANCEL_STOP_DEVICE
  147. DefaultPnpHandler,      // IRP_MN_QUERY_DEVICE_RELATIONS
  148. DefaultPnpHandler,      // IRP_MN_QUERY_INTERFACE
  149. DefaultPnpHandler,      // IRP_MN_QUERY_CAPABILITIES
  150. DefaultPnpHandler,      // IRP_MN_QUERY_RESOURCES
  151. DefaultPnpHandler,      // IRP_MN_QUERY_RESOURCE_REQUIREMENTS
  152. DefaultPnpHandler,      // IRP_MN_QUERY_DEVICE_TEXT
  153. DefaultPnpHandler,      // IRP_MN_FILTER_RESOURCE_REQUIREMENTS
  154. DefaultPnpHandler,      //
  155. DefaultPnpHandler,      // IRP_MN_READ_CONFIG
  156. DefaultPnpHandler,      // IRP_MN_WRITE_CONFIG
  157. DefaultPnpHandler,      // IRP_MN_EJECT
  158. DefaultPnpHandler,      // IRP_MN_SET_LOCK
  159. DefaultPnpHandler,      // IRP_MN_QUERY_ID
  160. DefaultPnpHandler,      // IRP_MN_QUERY_PNP_DEVICE_STATE
  161. DefaultPnpHandler,      // IRP_MN_QUERY_BUS_INFORMATION
  162. DefaultPnpHandler,      // IRP_MN_DEVICE_USAGE_NOTIFICATION
  163. DefaultPnpHandler,      // IRP_MN_SURPRISE_REMOVAL
  164. };
  165. ULONG fcn = stack->MinorFunction;
  166. if (fcn >= arraysize(fcntab))
  167. {                       // unknown function
  168. status = DefaultPnpHandler(pdx, Irp); // some function we don't know about
  169. return status;
  170. }                       // unknown function
  171. #if DBG
  172. static char* fcnname[] =
  173. {
  174. "IRP_MN_START_DEVICE",
  175. "IRP_MN_QUERY_REMOVE_DEVICE",
  176. "IRP_MN_REMOVE_DEVICE",
  177. "IRP_MN_CANCEL_REMOVE_DEVICE",
  178. "IRP_MN_STOP_DEVICE",
  179. "IRP_MN_QUERY_STOP_DEVICE",
  180. "IRP_MN_CANCEL_STOP_DEVICE",
  181. "IRP_MN_QUERY_DEVICE_RELATIONS",
  182. "IRP_MN_QUERY_INTERFACE",
  183. "IRP_MN_QUERY_CAPABILITIES",
  184. "IRP_MN_QUERY_RESOURCES",
  185. "IRP_MN_QUERY_RESOURCE_REQUIREMENTS",
  186. "IRP_MN_QUERY_DEVICE_TEXT",
  187. "IRP_MN_FILTER_RESOURCE_REQUIREMENTS",
  188. "",
  189. "IRP_MN_READ_CONFIG",
  190. "IRP_MN_WRITE_CONFIG",
  191. "IRP_MN_EJECT",
  192. "IRP_MN_SET_LOCK",
  193. "IRP_MN_QUERY_ID",
  194. "IRP_MN_QUERY_PNP_DEVICE_STATE",
  195. "IRP_MN_QUERY_BUS_INFORMATION",
  196. "IRP_MN_DEVICE_USAGE_NOTIFICATION",
  197. "IRP_MN_SURPRISE_REMOVAL",
  198. };
  199. KdPrint(("PNP Request (%s)\n", fcnname[fcn]));
  200. #endif // DBG
  201. status = (*fcntab[fcn])(pdx, Irp);
  202. KdPrint(("Leave HelloWDMPnp\n"));
  203. return status;
  204. }
  205. /************************************************************************
  206. * 函数名称:HelloWDMDispatchRoutine
  207. * 功能描述:对缺省IRP进行处理
  208. * 参数列表:
  209. fdo:功能设备对象
  210. Irp:从IO请求包
  211. * 返回 值:返回状态
  212. *************************************************************************/
  213. #pragma PAGEDCODE
  214. NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo,
  215. IN PIRP Irp)
  216. {
  217. PAGED_CODE();
  218. KdPrint(("Enter HelloWDMDispatchRoutine\n"));
  219. PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
  220. //打印IRP的major function code和minor function code。
  221. ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
  222. KdPrint(("DispatchRoutine, Major function code: %x, Minor function code: %x, control code: %x\n",
  223. stack->MajorFunction, stack->MinorFunction, code));
  224. Irp->IoStatus.Status = STATUS_SUCCESS;
  225. Irp->IoStatus.Information = 0;   // no bytes xfered
  226. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  227. KdPrint(("Leave HelloWDMDispatchRoutine\n"));
  228. return STATUS_SUCCESS;
  229. }
  230. /************************************************************************
  231. * 函数名称:HelloWDMUnload
  232. * 功能描述:负责驱动程序的卸载操作
  233. * 参数列表:
  234. DriverObject:驱动对象
  235. * 返回 值:返回状态
  236. *************************************************************************/
  237. #pragma PAGEDCODE
  238. void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject)
  239. {
  240. PAGED_CODE();
  241. KdPrint(("Enter HelloWDMUnload\n"));
  242. KdPrint(("Leave HelloWDMUnload\n"));
  243. }

3、INF文件见张帆WDM例子。

4、用户态应用程序

[cpp] view plain copy
  1. #include "CC_Debug.h"
  2. #include <stdio.h>
  3. #include <windows.h>
  4. #define DEVICE_NAME L"\\\\.\\HelloWDM"
  5. int main()
  6. {
  7. HANDLE hDevice = CreateFile(DEVICE_NAME,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
  8. printf("hDevice = %x",hDevice);
  9. if (hDevice != INVALID_HANDLE_VALUE)
  10. {
  11. for(int i = 0; i < 10; i++)
  12. {
  13. DWORD RetBytes = 0;
  14. BOOL b = DeviceIoControl(hDevice, 0xAB, NULL, 0, NULL, 0, &RetBytes, NULL);
  15. printf("Test number %d, DeviceIoControl result: %d, byte: %d\n", i + 1, b, RetBytes);
  16. Sleep(1000);
  17. }
  18. CloseHandle(hDevice);
  19. }
  20. else
  21. printf("CreateFile failed, err: %x\n", GetLastError());
  22. return 0;
  23. }

5、这里有必要讲一下驱动的几个名字概念:

1. 首先是设备名称,就是IoCreateDevice里面用到的那个名字。这个名字只能被内核模式的程序(如其他驱动)所识别。用户模式的程序是不知道这个名字的。

2. 符号链接,驱动程序里面可以为某个设备设置符号链接,以\??\开头(或者\DosDevices\),这样用户模式的程序就可以通过这个符号链接来访问这个设备。

3. 用户模式程序里面的设备名称,以\\.\开头
比如这个例子里面内核模式的设备名称是"\Device\MyWDMDevice",符号链接是"\DosDevices\HelloWDM",然后用户模式程序通过"\\.\HelloWDM"访问这个设备。

当CreateFile成功打开这个设备后,就可以操作这个设备了。测试例子里面简单往这个设备调用了10次DeviceIoControl函数(也就是发送一个IRP_MJ_DEVICE_CONTROL类型的IRP)。

4、Major function code 是e(16进制),看一下WDM.H

确实0x0e对应的是IRP_MJ_DEVICE_CONTROL。

然后测试例子里面发送了一个0xAB的控制码给驱动,那么驱动里面通过stack->Parameters.DeviceIoControl.IoControlCode得到的控制码也是0xab,看上面的debugview信息。

http://blog.csdn.net/zj510/article/details/8208732

Windows驱动开发——WDM驱动相关推荐

  1. Linux驱动开发 -- touch驱动注册

    Linux i2c驱动开发 – touch 驱动 文章目录 Linux i2c驱动开发 -- touch 驱动 前言 一.i2c 驱动框架 二.Linux的MODULE声明 1. MODULE相关声明 ...

  2. Linux驱动开发——串口设备驱动

    Linux驱动开发--串口设备驱动 一.串口简介 串口全称叫做串行接口,通常也叫做 COM 接口,串行接口指的是数据一个一个的顺序传输,通信线路简单.使用两条线即可实现双向通信,一条用于发送,一条用于 ...

  3. Linux嵌入式驱动开发02——驱动编译到内核

    文章目录 全系列传送门 make menuconfig图形化配置界面 1. 怎么进入到make menuconfig图形化界面? 2. make menuconfig图形化界面的操作 3. 退出 4. ...

  4. STM32MP157驱动开发——SPI驱动

    STM32MP157驱动开发--SPI驱动 一.简介 1.SPI介绍 2.STM32MP1 SPI介绍 3. ICM-20608 简介 4.Linux下的SPI框架 二.驱动开发 1)IO 的 pin ...

  5. Windows驱动开发WDM (1) - 基本结构

    陆陆续续做过一些驱动的开发,但是一直以来都没有系统的学习过.这次重新阅读<windows驱动开发技术详解>(张帆,史彩成等编著),写博客记录一下,用以加深自己对驱动的理解. 驱动对象(DR ...

  6. Windows驱动开发WDM (13)- 过滤驱动

    之前用的驱动例子是一个功能型驱动,只不过它操作的是一个虚拟设备.这个驱动创建的FDO(功能设备对象)是附在虚拟总线驱动创建的虚拟PDO之上的.这次来介绍一下不同于功能型驱动的过滤驱动.过滤驱动可以在功 ...

  7. linux使用wdm设备驱动模型,驱动开发(WDM) - thomas_more的个人空间 - OSCHINA - 中文开源技术交流社区...

    windows 设备对象名称(内核对象必须命名才能被用户层访问产生句柄) \Driver\ 内核模式下访问 \.\ 用户模式下访问 winObj(symbollink设备名称的别名,各个节点查看)和d ...

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

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

  9. linux驱动开发音频设备驱动,linux驱动开发—基于Device tree机制的驱动编写

    摘要:媒介 Device Tree是一种用去描绘硬件的数据布局,类似板级描绘说话,发源于OpenFirmware(OF).正在现在遍及应用的kernel 2.6.x版本中,对分歧仄台.分歧硬件,往] ...

  10. Linux 设备驱动开发思想 —— 驱动分层与驱动分离

    前面我们学习I2C.USB.SD驱动时,有没有发现一个共性,就是在驱动开发时,每个驱动都分层三部分,由上到下分别是: 1.XXX 设备驱动 2.XXX 核心层 3.XXX 主机控制器驱动 而需要我们编 ...

最新文章

  1. 皮一皮:运气差,可能说的就是这个吧...
  2. Linux 内核开发 - Eclipse内核开发环境搭建
  3. Nginx Mac笔记
  4. Python-jieba分词学习及应用
  5. Net学习日记_ASP.Net_MVC_新语法笔记
  6. 深度学习 GPU环境 Ubuntu 16.04 + Nvidia GTX 1080 + Python 3.6 + CUDA 9.
  7. matplotlib绘图相关
  8. python组合和继承_Python基础系列讲解——继承派生和组合的概念剖析
  9. JavaScript 代码收集
  10. win10关闭电池保护模式_近年最稳的Win10更新?Win10 1909值得升级吗
  11. Android应用方法数查看,查看size是否超过65k
  12. Android__ListView控件的使用
  13. 大学计算机word文档试题,大学WORD文档练习题.doc
  14. C内存分配方式与C++内存分配方式
  15. 劳务派遣人员管理办法范文
  16. React中Mpegts播放器的使用
  17. 三十六计珍藏版(上)
  18. OUTER JOIN的应用场景
  19. vSphere高级功能(一)——VMotion及SVMotion的实现
  20. JZOJ2020年8月11日提高组T3 页

热门文章

  1. java动态字段排序_Java利用Stream来实现多字段排序功能
  2. Mac OS 连内外网
  3. 算法导论 斐波那契堆
  4. [设计]2019年全国电子设计竞赛A题-电动小车动态无线充电系统
  5. cad图形如何导入到奥维地图_CAD图导入奥维简易操作步骤--陈浩
  6. python中numpy下载问题
  7. C语言实现移位密码算法,仿射密码算法
  8. python安装numpy库教程_Python库之numpy库的安装教程
  9. 尽在双11:阿里巴巴技术演进与超越
  10. Uml工具StarUML破解