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