Windows驱动开发——WDM驱动
来源:互联网 发布:windows是什么文件夹 编辑:程序博客网 时间:2024/04/29 15:46
1、WDM.h
/************************************************************************* 文件名称:HelloWDM.h * 作 者:张帆* 完成日期:2007-11-1*************************************************************************/#ifdef __cplusplusextern "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 PAGEDCODENTSTATUS 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 PAGEDCODENTSTATUS 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 PAGEDCODENTSTATUS 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 PAGEDCODENTSTATUS 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_DEVICEDefaultPnpHandler,// IRP_MN_QUERY_REMOVE_DEVICEHandleRemoveDevice,// IRP_MN_REMOVE_DEVICEDefaultPnpHandler,// IRP_MN_CANCEL_REMOVE_DEVICEDefaultPnpHandler,// IRP_MN_STOP_DEVICEDefaultPnpHandler,// IRP_MN_QUERY_STOP_DEVICEDefaultPnpHandler,// IRP_MN_CANCEL_STOP_DEVICEDefaultPnpHandler,// IRP_MN_QUERY_DEVICE_RELATIONSDefaultPnpHandler,// IRP_MN_QUERY_INTERFACEDefaultPnpHandler,// IRP_MN_QUERY_CAPABILITIESDefaultPnpHandler,// IRP_MN_QUERY_RESOURCESDefaultPnpHandler,// IRP_MN_QUERY_RESOURCE_REQUIREMENTSDefaultPnpHandler,// IRP_MN_QUERY_DEVICE_TEXTDefaultPnpHandler,// IRP_MN_FILTER_RESOURCE_REQUIREMENTSDefaultPnpHandler,// DefaultPnpHandler,// IRP_MN_READ_CONFIGDefaultPnpHandler,// IRP_MN_WRITE_CONFIGDefaultPnpHandler,// IRP_MN_EJECTDefaultPnpHandler,// IRP_MN_SET_LOCKDefaultPnpHandler,// IRP_MN_QUERY_IDDefaultPnpHandler,// IRP_MN_QUERY_PNP_DEVICE_STATEDefaultPnpHandler,// IRP_MN_QUERY_BUS_INFORMATIONDefaultPnpHandler,// IRP_MN_DEVICE_USAGE_NOTIFICATIONDefaultPnpHandler,// IRP_MN_SURPRISE_REMOVAL};ULONG fcn = stack->MinorFunction;if (fcn >= arraysize(fcntab)){// unknown functionstatus = DefaultPnpHandler(pdx, Irp); // some function we don't know aboutreturn status;}// unknown function#if DBGstatic 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 // DBGstatus = (*fcntab[fcn])(pdx, Irp);KdPrint(("Leave HelloWDMPnp\n"));return status;}/************************************************************************* 函数名称:HelloWDMDispatchRoutine* 功能描述:对缺省IRP进行处理* 参数列表: fdo:功能设备对象 Irp:从IO请求包* 返回 值:返回状态*************************************************************************/#pragma PAGEDCODENTSTATUS 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 xferedIoCompleteRequest( Irp, IO_NO_INCREMENT );KdPrint(("Leave HelloWDMDispatchRoutine\n"));return STATUS_SUCCESS;}/************************************************************************* 函数名称:HelloWDMUnload* 功能描述:负责驱动程序的卸载操作* 参数列表: DriverObject:驱动对象* 返回 值:返回状态*************************************************************************/#pragma PAGEDCODEvoid 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
0 0
- Windows驱动开发——WDM驱动
- Windows驱动开发——WDM驱动
- windows驱动开发——DDK WDM
- USB驱动开发——基于windows的WDM模型
- WINDOWS WDM驱动开发基础
- windows驱动设计——WDM
- 谈WDM与WDF (windows驱动开发)
- 谈WDM与WDF (windows驱动开发)
- Windows驱动开发WDM (13)- 过滤驱动
- Windows驱动开发WDM (13)- 过滤驱动
- Windows 7驱动开发系列(四)--WDM模型介绍
- Windows驱动开发WDM (1) - 基本结构
- Windows驱动开发WDM (3)- 设备内存读写方式
- Windows驱动开发WDM (4)- 缓冲区方式例子
- Windows驱动开发WDM (6)- 中断请求级别
- Windows驱动开发WDM (7)- 异步IRP
- Windows驱动开发WDM (8)- 内核同步对象
- Windows驱动开发WDM (10)- StartIo取消例程
- 聊聊并发-Java中的Copy-On-Write容器
- 不错的资源
- RedHat Enterprise Linux6.4 使用CentOS yum源
- ubuntu12.04 安装jdk
- Twitter Storm: Transactional Topolgoy简介
- Windows驱动开发——WDM驱动
- 【四圣龙神录的编程教室】第16章、来制作洩矢大人的弹幕吧
- hdu 1850 Being a Good Boy in Spring Festival
- NYOJ34韩信点兵
- Java学习系列(一)Java的运行机制、JDK的安装配置及常用命令详解
- 基础练习30
- JS删除字符串中重复字符
- awgn函数与高斯白噪声
- 越界