Windows驱动开发——WDM驱动
1、WDM.h
- /************************************************************************
- * 文件名称:HelloWDM.h
- * 作 者:张帆
- * 完成日期:2007-11-1
- *************************************************************************/
- #ifdef __cplusplus
- extern "C"
- {
- #endif
- #include <wdm.h>
- #ifdef __cplusplus
- }
- #endif
- typedef struct _DEVICE_EXTENSION
- {
- PDEVICE_OBJECT fdo;
- PDEVICE_OBJECT NextStackDevice;
- UNICODE_STRING ustrDeviceName; // 设备名
- UNICODE_STRING ustrSymLinkName; // 符号链接名
- } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
- #define PAGEDCODE code_seg("PAGE")
- #define LOCKEDCODE code_seg()
- #define INITCODE code_seg("INIT")
- #define PAGEDDATA data_seg("PAGE")
- #define LOCKEDDATA data_seg()
- #define INITDATA data_seg("INIT")
- #define arraysize(p) (sizeof(p)/sizeof((p)[0]))
- NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject,
- IN PDEVICE_OBJECT PhysicalDeviceObject);
- NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo,
- IN PIRP Irp);
- NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo,
- IN PIRP Irp);
- void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject);
- extern "C"
- NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
- IN PUNICODE_STRING RegistryPath);
2、WDM.c
- /************************************************************************
- * 文件名称:HelloWDM.cpp
- * 作 者:张帆
- * 完成日期:2007-11-1
- *************************************************************************/
- #include "HelloWDM.h"
- /************************************************************************
- * 函数名称:DriverEntry
- * 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象
- * 参数列表:
- pDriverObject:从I/O管理器中传进来的驱动对象
- pRegistryPath:驱动程序在注册表的中的路径
- * 返回 值:返回初始化驱动状态
- *************************************************************************/
- #pragma INITCODE
- extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,
- IN PUNICODE_STRING pRegistryPath)
- {
- KdPrint(("Enter DriverEntry\n"));
- pDriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;
- pDriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;
- pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
- pDriverObject->MajorFunction[IRP_MJ_CREATE] =
- pDriverObject->MajorFunction[IRP_MJ_READ] =
- pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloWDMDispatchRoutine;
- pDriverObject->DriverUnload = HelloWDMUnload;
- KdPrint(("Leave DriverEntry\n"));
- return STATUS_SUCCESS;
- }
- /************************************************************************
- * 函数名称:HelloWDMAddDevice
- * 功能描述:添加新设备
- * 参数列表:
- DriverObject:从I/O管理器中传进来的驱动对象
- PhysicalDeviceObject:从I/O管理器中传进来的物理设备对象
- * 返回 值:返回添加新设备状态
- *************************************************************************/
- #pragma PAGEDCODE
- NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject,
- IN PDEVICE_OBJECT PhysicalDeviceObject)
- {
- PAGED_CODE();
- KdPrint(("Enter HelloWDMAddDevice\n"));
- NTSTATUS status;
- PDEVICE_OBJECT fdo;
- UNICODE_STRING devName;
- RtlInitUnicodeString(&devName,L"\\Device\\MyWDMDevice");
- status = IoCreateDevice(
- DriverObject,
- sizeof(DEVICE_EXTENSION),
- &(UNICODE_STRING)devName,
- FILE_DEVICE_UNKNOWN,
- 0,
- FALSE,
- &fdo);
- if( !NT_SUCCESS(status))
- return status;
- PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
- pdx->fdo = fdo;
- pdx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);
- UNICODE_STRING symLinkName;
- RtlInitUnicodeString(&symLinkName,L"\\DosDevices\\HelloWDM");
- pdx->ustrDeviceName = devName;
- pdx->ustrSymLinkName = symLinkName;
- status = IoCreateSymbolicLink(&(UNICODE_STRING)symLinkName,&(UNICODE_STRING)devName);
- if( !NT_SUCCESS(status))
- {
- IoDeleteSymbolicLink(&pdx->ustrSymLinkName);
- status = IoCreateSymbolicLink(&symLinkName,&devName);
- if( !NT_SUCCESS(status))
- {
- return status;
- }
- }
- fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE; //驱动创建的设备有三种工作方式,缓冲区方式、直接方式和其他方式。
- fdo->Flags &= ~DO_DEVICE_INITIALIZING;
- KdPrint(("Leave HelloWDMAddDevice\n"));
- return STATUS_SUCCESS;
- }
- /************************************************************************
- * 函数名称:DefaultPnpHandler
- * 功能描述:对PNP IRP进行缺省处理
- * 参数列表:
- pdx:设备对象的扩展
- Irp:从IO请求包
- * 返回 值:返回状态
- *************************************************************************/
- #pragma PAGEDCODE
- NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP Irp)
- {
- PAGED_CODE();
- KdPrint(("Enter DefaultPnpHandler\n"));
- IoSkipCurrentIrpStackLocation(Irp);
- KdPrint(("Leave DefaultPnpHandler\n"));
- return IoCallDriver(pdx->NextStackDevice, Irp);
- }
- /************************************************************************
- * 函数名称:HandleRemoveDevice
- * 功能描述:对IRP_MN_REMOVE_DEVICE IRP进行处理
- * 参数列表:
- fdo:功能设备对象
- Irp:从IO请求包
- * 返回 值:返回状态
- *************************************************************************/
- #pragma PAGEDCODE
- NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp)
- {
- PAGED_CODE();
- KdPrint(("Enter HandleRemoveDevice\n"));
- Irp->IoStatus.Status = STATUS_SUCCESS;
- NTSTATUS status = DefaultPnpHandler(pdx, Irp);
- IoDeleteSymbolicLink(&(UNICODE_STRING)pdx->ustrSymLinkName);
- //调用IoDetachDevice()把fdo从设备栈中脱开:
- if (pdx->NextStackDevice)
- IoDetachDevice(pdx->NextStackDevice);
- //删除fdo:
- IoDeleteDevice(pdx->fdo);
- KdPrint(("Leave HandleRemoveDevice\n"));
- return status;
- }
- /************************************************************************
- * 函数名称:HelloWDMPnp
- * 功能描述:对即插即用IRP进行处理
- * 参数列表:
- fdo:功能设备对象
- Irp:从IO请求包
- * 返回 值:返回状态
- *************************************************************************/
- #pragma PAGEDCODE
- NTSTATUS HelloWDMPnp(IN PDEVICE_OBJECT fdo,
- IN PIRP Irp)
- {
- PAGED_CODE();
- KdPrint(("Enter HelloWDMPnp\n"));
- NTSTATUS status = STATUS_SUCCESS;
- PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
- PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
- static NTSTATUS (*fcntab[])(PDEVICE_EXTENSION pdx, PIRP Irp) =
- {
- DefaultPnpHandler, // IRP_MN_START_DEVICE
- DefaultPnpHandler, // IRP_MN_QUERY_REMOVE_DEVICE
- HandleRemoveDevice, // IRP_MN_REMOVE_DEVICE
- DefaultPnpHandler, // IRP_MN_CANCEL_REMOVE_DEVICE
- DefaultPnpHandler, // IRP_MN_STOP_DEVICE
- DefaultPnpHandler, // IRP_MN_QUERY_STOP_DEVICE
- DefaultPnpHandler, // IRP_MN_CANCEL_STOP_DEVICE
- DefaultPnpHandler, // IRP_MN_QUERY_DEVICE_RELATIONS
- DefaultPnpHandler, // IRP_MN_QUERY_INTERFACE
- DefaultPnpHandler, // IRP_MN_QUERY_CAPABILITIES
- DefaultPnpHandler, // IRP_MN_QUERY_RESOURCES
- DefaultPnpHandler, // IRP_MN_QUERY_RESOURCE_REQUIREMENTS
- DefaultPnpHandler, // IRP_MN_QUERY_DEVICE_TEXT
- DefaultPnpHandler, // IRP_MN_FILTER_RESOURCE_REQUIREMENTS
- DefaultPnpHandler, //
- DefaultPnpHandler, // IRP_MN_READ_CONFIG
- DefaultPnpHandler, // IRP_MN_WRITE_CONFIG
- DefaultPnpHandler, // IRP_MN_EJECT
- DefaultPnpHandler, // IRP_MN_SET_LOCK
- DefaultPnpHandler, // IRP_MN_QUERY_ID
- DefaultPnpHandler, // IRP_MN_QUERY_PNP_DEVICE_STATE
- DefaultPnpHandler, // IRP_MN_QUERY_BUS_INFORMATION
- DefaultPnpHandler, // IRP_MN_DEVICE_USAGE_NOTIFICATION
- DefaultPnpHandler, // IRP_MN_SURPRISE_REMOVAL
- };
- ULONG fcn = stack->MinorFunction;
- if (fcn >= arraysize(fcntab))
- { // unknown function
- status = DefaultPnpHandler(pdx, Irp); // some function we don't know about
- return status;
- } // unknown function
- #if DBG
- static char* fcnname[] =
- {
- "IRP_MN_START_DEVICE",
- "IRP_MN_QUERY_REMOVE_DEVICE",
- "IRP_MN_REMOVE_DEVICE",
- "IRP_MN_CANCEL_REMOVE_DEVICE",
- "IRP_MN_STOP_DEVICE",
- "IRP_MN_QUERY_STOP_DEVICE",
- "IRP_MN_CANCEL_STOP_DEVICE",
- "IRP_MN_QUERY_DEVICE_RELATIONS",
- "IRP_MN_QUERY_INTERFACE",
- "IRP_MN_QUERY_CAPABILITIES",
- "IRP_MN_QUERY_RESOURCES",
- "IRP_MN_QUERY_RESOURCE_REQUIREMENTS",
- "IRP_MN_QUERY_DEVICE_TEXT",
- "IRP_MN_FILTER_RESOURCE_REQUIREMENTS",
- "",
- "IRP_MN_READ_CONFIG",
- "IRP_MN_WRITE_CONFIG",
- "IRP_MN_EJECT",
- "IRP_MN_SET_LOCK",
- "IRP_MN_QUERY_ID",
- "IRP_MN_QUERY_PNP_DEVICE_STATE",
- "IRP_MN_QUERY_BUS_INFORMATION",
- "IRP_MN_DEVICE_USAGE_NOTIFICATION",
- "IRP_MN_SURPRISE_REMOVAL",
- };
- KdPrint(("PNP Request (%s)\n", fcnname[fcn]));
- #endif // DBG
- status = (*fcntab[fcn])(pdx, Irp);
- KdPrint(("Leave HelloWDMPnp\n"));
- return status;
- }
- /************************************************************************
- * 函数名称:HelloWDMDispatchRoutine
- * 功能描述:对缺省IRP进行处理
- * 参数列表:
- fdo:功能设备对象
- Irp:从IO请求包
- * 返回 值:返回状态
- *************************************************************************/
- #pragma PAGEDCODE
- NTSTATUS HelloWDMDispatchRoutine(IN PDEVICE_OBJECT fdo,
- IN PIRP Irp)
- {
- PAGED_CODE();
- KdPrint(("Enter HelloWDMDispatchRoutine\n"));
- PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
- //打印IRP的major function code和minor function code。
- ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
- KdPrint(("DispatchRoutine, Major function code: %x, Minor function code: %x, control code: %x\n",
- stack->MajorFunction, stack->MinorFunction, code));
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = 0; // no bytes xfered
- IoCompleteRequest( Irp, IO_NO_INCREMENT );
- KdPrint(("Leave HelloWDMDispatchRoutine\n"));
- return STATUS_SUCCESS;
- }
- /************************************************************************
- * 函数名称:HelloWDMUnload
- * 功能描述:负责驱动程序的卸载操作
- * 参数列表:
- DriverObject:驱动对象
- * 返回 值:返回状态
- *************************************************************************/
- #pragma PAGEDCODE
- void HelloWDMUnload(IN PDRIVER_OBJECT DriverObject)
- {
- PAGED_CODE();
- KdPrint(("Enter HelloWDMUnload\n"));
- KdPrint(("Leave HelloWDMUnload\n"));
- }
3、INF文件见张帆WDM例子。
4、用户态应用程序
- #include "CC_Debug.h"
- #include <stdio.h>
- #include <windows.h>
- #define DEVICE_NAME L"\\\\.\\HelloWDM"
- int main()
- {
- HANDLE hDevice = CreateFile(DEVICE_NAME,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
- printf("hDevice = %x",hDevice);
- if (hDevice != INVALID_HANDLE_VALUE)
- {
- for(int i = 0; i < 10; i++)
- {
- DWORD RetBytes = 0;
- BOOL b = DeviceIoControl(hDevice, 0xAB, NULL, 0, NULL, 0, &RetBytes, NULL);
- printf("Test number %d, DeviceIoControl result: %d, byte: %d\n", i + 1, b, RetBytes);
- Sleep(1000);
- }
- CloseHandle(hDevice);
- }
- else
- printf("CreateFile failed, err: %x\n", GetLastError());
- return 0;
- }
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驱动相关推荐
- Linux驱动开发 -- touch驱动注册
Linux i2c驱动开发 – touch 驱动 文章目录 Linux i2c驱动开发 -- touch 驱动 前言 一.i2c 驱动框架 二.Linux的MODULE声明 1. MODULE相关声明 ...
- Linux驱动开发——串口设备驱动
Linux驱动开发--串口设备驱动 一.串口简介 串口全称叫做串行接口,通常也叫做 COM 接口,串行接口指的是数据一个一个的顺序传输,通信线路简单.使用两条线即可实现双向通信,一条用于发送,一条用于 ...
- Linux嵌入式驱动开发02——驱动编译到内核
文章目录 全系列传送门 make menuconfig图形化配置界面 1. 怎么进入到make menuconfig图形化界面? 2. make menuconfig图形化界面的操作 3. 退出 4. ...
- STM32MP157驱动开发——SPI驱动
STM32MP157驱动开发--SPI驱动 一.简介 1.SPI介绍 2.STM32MP1 SPI介绍 3. ICM-20608 简介 4.Linux下的SPI框架 二.驱动开发 1)IO 的 pin ...
- Windows驱动开发WDM (1) - 基本结构
陆陆续续做过一些驱动的开发,但是一直以来都没有系统的学习过.这次重新阅读<windows驱动开发技术详解>(张帆,史彩成等编著),写博客记录一下,用以加深自己对驱动的理解. 驱动对象(DR ...
- Windows驱动开发WDM (13)- 过滤驱动
之前用的驱动例子是一个功能型驱动,只不过它操作的是一个虚拟设备.这个驱动创建的FDO(功能设备对象)是附在虚拟总线驱动创建的虚拟PDO之上的.这次来介绍一下不同于功能型驱动的过滤驱动.过滤驱动可以在功 ...
- linux使用wdm设备驱动模型,驱动开发(WDM) - thomas_more的个人空间 - OSCHINA - 中文开源技术交流社区...
windows 设备对象名称(内核对象必须命名才能被用户层访问产生句柄) \Driver\ 内核模式下访问 \.\ 用户模式下访问 winObj(symbollink设备名称的别名,各个节点查看)和d ...
- windows 驱动开发入门——驱动中的数据结构
最近在学习驱动编程方面的内容,在这将自己的一些心得分享出来,供大家参考,与大家共同进步,本人学习驱动主要是通过两本书--<独钓寒江 windows安全编程> 和 <windows驱动 ...
- linux驱动开发音频设备驱动,linux驱动开发—基于Device tree机制的驱动编写
摘要:媒介 Device Tree是一种用去描绘硬件的数据布局,类似板级描绘说话,发源于OpenFirmware(OF).正在现在遍及应用的kernel 2.6.x版本中,对分歧仄台.分歧硬件,往] ...
- Linux 设备驱动开发思想 —— 驱动分层与驱动分离
前面我们学习I2C.USB.SD驱动时,有没有发现一个共性,就是在驱动开发时,每个驱动都分层三部分,由上到下分别是: 1.XXX 设备驱动 2.XXX 核心层 3.XXX 主机控制器驱动 而需要我们编 ...
最新文章
- 皮一皮:运气差,可能说的就是这个吧...
- Linux 内核开发 - Eclipse内核开发环境搭建
- Nginx Mac笔记
- Python-jieba分词学习及应用
- Net学习日记_ASP.Net_MVC_新语法笔记
- 深度学习 GPU环境 Ubuntu 16.04 + Nvidia GTX 1080 + Python 3.6 + CUDA 9.
- matplotlib绘图相关
- python组合和继承_Python基础系列讲解——继承派生和组合的概念剖析
- JavaScript 代码收集
- win10关闭电池保护模式_近年最稳的Win10更新?Win10 1909值得升级吗
- Android应用方法数查看,查看size是否超过65k
- Android__ListView控件的使用
- 大学计算机word文档试题,大学WORD文档练习题.doc
- C内存分配方式与C++内存分配方式
- 劳务派遣人员管理办法范文
- React中Mpegts播放器的使用
- 三十六计珍藏版(上)
- OUTER JOIN的应用场景
- vSphere高级功能(一)——VMotion及SVMotion的实现
- JZOJ2020年8月11日提高组T3 页