好友
阅读权限10
听众
最后登录1970-1-1
|
Robot
发表于 2013-2-21 09:47
//在删除设备的时候 蓝屏 请高手帮忙看看 到底哪里出错了
//IoDeleteDevice 穿进去的不为空 但还是蓝屏了
#include<ntddk.h>
#define DELAY_ONE_MILLISECOND (-10*1000)
/**********************************
键盘过滤驱动
***********************************/
//声明全局变量
//在Win7中 这个变量为 多重指针 而不是指针 对象
extern POBJECT_TYPE *IoDriverObjectType;
//KbdClass 驱动名字
#define KBD_DRIVER_NAME L"\\Driver\\Kbdclass"
ULONG gC2pKeyCount=0; //当有键盘按下的请求则加1请求结束则减1
//声明 ObReferenceObjectByName 函数 根据驱动名获得对象指针
//此函数需要声明 输入微软未公开的API函数
NTSTATUS ObReferenceObjectByName(
PUNICODE_STRING ObjectName,
ULONG Attributes,
PACCESS_STATE AccessState,
ACCESS_MASK DesiredAccess,
POBJECT_TYPE *ObjectType,
KPROCESSOR_MODE AccessMode,
PVOID ParseContext,
PVOID *Object //OUT
);
//设备扩展结构
typedef struct _C2P_DEV_EXT{
//结构大小
ULONG NodeSize;
//过滤设备对象
PDEVICE_OBJECT pFilterDeviceObject;
//同时调用时保护锁
KSPIN_LOCK IoRequestsSpinLock;
//进程同步处理
KEVENT IoInProgressEvent;
//绑定的设备对象
PDEVICE_OBJECT pTargetDeviceObject;
//绑定前底层设备对象
PDEVICE_OBJECT pLowerDeviceObject;
}C2P_DEV_EXT,*PC2P_DEV_EXT;
//初始化扩展
NTSTATUS c2pDevExtInit(
IN PC2P_DEV_EXT devExt,
IN PDEVICE_OBJECT pFilterDeviceObject,
IN PDEVICE_OBJECT pTargetDeviceObject,
IN PDEVICE_OBJECT pLowerDeviceObject
){
//开辟空间
memset(devExt,0,sizeof(C2P_DEV_EXT));
devExt->NodeSize = sizeof(C2P_DEV_EXT);
devExt->pFilterDeviceObject = pFilterDeviceObject;
KeInitializeSpinLock(&(devExt->IoRequestsSpinLock));
KeInitializeEvent(&(devExt->IoInProgressEvent),NotificationEvent,FALSE);
devExt->pTargetDeviceObject = pTargetDeviceObject;
devExt->pLowerDeviceObject = pLowerDeviceObject;
return STATUS_SUCCESS;
}
//绑定设备
NTSTATUS keycupAttachDevice(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath){
//初始化变量
NTSTATUS status;
UNICODE_STRING uniNtNameString;
PC2P_DEV_EXT devExt;
PDEVICE_OBJECT pFilterDeivceObject =NULL; //过滤的设备
PDEVICE_OBJECT pTargetDeivceObject =NULL; //目标设备
PDEVICE_OBJECT pLowerDeviceObject = NULL; //下一个设备
//键盘过滤驱动对象
PDRIVER_OBJECT KbdDriverObject = NULL;
DbgPrint(("MyAttach\n"));
//初始化字符串
RtlInitUnicodeString(&uniNtNameString,KBD_DRIVER_NAME);
//打开驱动对象
status = ObReferenceObjectByName(&uniNtNameString,//驱动名称
OBJ_CASE_INSENSITIVE, //不区分大小写
NULL,
0, //权限
*IoDriverObjectType,
KernelMode,
NULL,
&KbdDriverObject); //OUT
//判断是否成功
if(!NT_SUCCESS(status)){
DbgPrint("Attach error");
return status;
}else{
//调用ObReferenceObjectByName 会导致内核的引用计数 加1
//必须调用ObDereferenceObject 函数 递减
ObDereferenceObject(DriverObject);
}
//设备链 第一个设备
pTargetDeivceObject = KbdDriverObject->DeviceObject;
//遍历设备链
while(pTargetDeivceObject){
//生成一个过滤设备
status = IoCreateDevice(
DriverObject, //驱动对象
sizeof(PC2P_DEV_EXT),
NULL,
pTargetDeivceObject->DeviceType,
pTargetDeivceObject->Characteristics,
FALSE,
&pFilterDeivceObject
);
//如果失败 返回状态
if(!NT_SUCCESS(status)){
DbgPrint("Attach Could not create filter device");
return status;
}
//进行绑定
//filter 过滤的设备
//target 设备栈中的设备 函数作用 这两个设备进行绑定 返回 pLowerDeviceObject 的指针
IoAttachDeviceToDeviceStackSafe(pFilterDeivceObject,pTargetDeivceObject,&pLowerDeviceObject);
//如果绑定失败 则退出
if(pLowerDeviceObject==NULL){
DbgPrint("IoAttachDeviceToDeviceStackSafe error");
IoDeleteDevice(pFilterDeivceObject);
pFilterDeivceObject= NULL;
return status;
}
//设备扩展
devExt = (PC2P_DEV_EXT)(pFilterDeivceObject->DeviceExtension);
c2pDevExtInit(
devExt,
pFilterDeivceObject,
pTargetDeivceObject,
pLowerDeviceObject
);
//拷贝标志位
pFilterDeivceObject->DeviceType = pLowerDeviceObject->DeviceType;
pFilterDeivceObject->Characteristics = pLowerDeviceObject->Characteristics;
pFilterDeivceObject->StackSize = pLowerDeviceObject->StackSize+1; //设备栈个数
pFilterDeivceObject->Flags |= pLowerDeviceObject->Flags&(DO_BUFFERED_IO|DO_DIRECT_IO|DO_POWER_PAGABLE );
//移动到下一个设备
pTargetDeivceObject = pTargetDeivceObject->NextDevice;
}
return status;
}
PDRIVER_OBJECT gDriverObject = NULL; //暂时不知道是用作什么
VOID c2pDetach(IN PDEVICE_OBJECT pDeviceObject)
{
PC2P_DEV_EXT devExt;
//BOOLEAN NoRequestsOutstanding = FALSE;
devExt = (PC2P_DEV_EXT)pDeviceObject->DeviceExtension;
__try
{
__try
{
IoDetachDevice(devExt->pTargetDeviceObject);
devExt->pTargetDeviceObject = NULL;
IoDeleteDevice(pDeviceObject); //在删除设备的时候 出错蓝屏 这里值不为空
DbgPrint(("Detach Finished\n"));
}
__except (EXCEPTION_EXECUTE_HANDLER){}
}
__finally{}
return;
}
//卸载函数
VOID c2pUnload(IN PDRIVER_OBJECT DriverObject)
{
PDEVICE_OBJECT DeviceObject;
PDEVICE_OBJECT OldDeviceObject;
PC2P_DEV_EXT devExt;
LARGE_INTEGER lDelay; //延迟时间
PRKTHREAD CurrentThread;
#if DBG
_asm int 3
#endif
//设置延迟时间
lDelay = RtlConvertLongToLargeInteger(100*DELAY_ONE_MILLISECOND);
CurrentThread = KeGetCurrentThread(); //获取当前运行的线程指针
//把当前线程 设置为低实时模式
KeSetPriorityThread(CurrentThread,LOW_REALTIME_PRIORITY);
UNREFERENCED_PARAMETER(DriverObject); //防止编译器提示变量为引用的警告
DbgPrint("driver unloading ....");
//遍历所有对象
DeviceObject =DriverObject->DeviceObject;
while(DeviceObject)
{
//解除并删除 设备对象
c2pDetach(DeviceObject);
//next
DeviceObject=DeviceObject->NextDevice;
}
ASSERT(NULL==DriverObject->DeviceObject); //如果设备对象不为NULL 则不会向下执行
while(gC2pKeyCount)
{
KeDelayExecutionThread(KernelMode,FALSE,&lDelay); //吧线程进入等待状态 时间为lDelay
}
DbgPrint("unload driver success!");
return ;
}
//总分发函数
NTSTATUS c2pAllFunction(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp){
DbgPrint("other Diapatch");
//向下执行 Skip 吧IRP 给真实的设备进行操作
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(((PC2P_DEV_EXT)DeviceObject->DeviceExtension)->pLowerDeviceObject,Irp);
}
//电源处理
//处理类型为 IRP_MJ_POWER
NTSTATUS c2pPower(IN PDEVICE_OBJECT DeviceObject,PIRP Irp){
PC2P_DEV_EXT devExt;
devExt = (PC2P_DEV_EXT)DeviceObject->DeviceExtension; //设备扩展
PoStartNextPowerIrp(Irp); //Vista 之后估计不用写也可以
IoSkipCurrentIrpStackLocation(Irp);
return PoCallDriver(devExt->pLowerDeviceObject,Irp);
}
//PNP处理
NTSTATUS c2pPnP(IN PDEVICE_OBJECT DeviceObject ,IN PIRP Irp){
PC2P_DEV_EXT devExt;
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpStack;
//获取真实的设备
devExt = (PC2P_DEV_EXT)DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp); //获取Irp栈段
switch(irpStack->MinorFunction){
//移除操作
case IRP_MN_REMOVE_DEVICE:
DbgPrint("IRP_MN_REMOVE_DEVICE\n");
//请求下发
IoSkipCurrentIrpStackLocation(Irp);
IoCallDriver(devExt->pLowerDeviceObject,Irp);
//解除绑定
IoDetachDevice(devExt->pLowerDeviceObject);
//删除设备
IoDeleteDevice(DeviceObject);
break;
default:
//其他类型IRP直接下发
IoSkipCurrentIrpStackLocation(Irp);
IoCallDriver(devExt->pLowerDeviceObject,Irp);
break;
}
return status;
}
//回调函数
NTSTATUS irpCallBackFunction(PDEVICE_OBJECT DeviceObject,PIRP Irp,PVOID Context){
PIO_STACK_LOCATION irpStack;
ULONG bufLen = 0;
PCHAR buf = NULL;
size_t i ;
//获取Stack location
irpStack = IoGetCurrentIrpStackLocation(Irp);
//如果请求成功 获取进一步信息
if(NT_SUCCESS(Irp->IoStatus.Status)){
//获得请求后输出到缓冲区
buf = Irp->AssociatedIrp.SystemBuffer;
//获取缓冲区的长度
//一般情况下返回值都会保存在 Information 中
bufLen = Irp->IoStatus.Information;
//打印出扫描码
for(i=0;i<bufLen;i++){
DbgPrint("键盘扫描码为: %2x\r\n",buf);
}
}
//全局变量递减
gC2pKeyCount--;
//个人理解 将IRP至于等待/保留状态 如果为True 调用IoMarkIrpPending 函数使Irp调用下层驱动进行处理
if(Irp->PendingReturned){
IoMarkIrpPending(Irp);
}
return Irp->IoStatus.Status; //返回Irp Status
}
//处理Read请求
NTSTATUS c2pDispatchRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp){
PIO_STACK_LOCATION irpStack;
PC2P_DEV_EXT devExt;
NTSTATUS status = STATUS_SUCCESS;
KEVENT waitEvent;
/*
IN PRKEVENT Event, //这个参数是初始化事件对象的指针
IN EVENT_TYPE Type, //这个参数是时间的类型。事件的类型分为两类,一类是"通知事件",对应参数是NotificationEvent.另一类是"同步事件",对应参数是SynchronizationEvent
IN BOOLEAN State //这个参数如果为真,事件对象初始化状态为激发状态。如果该参数为假,则事件对象的初始化状态为未激发态
*/
KeInitializeEvent(&waitEvent,NotificationEvent,FALSE); //初始化事件对象为通知型 并且未激活
//如果是 IRP栈中的最后1个 出栈 SP = sp-2 所以当标示为1的时候 则是最后一个设备 直接返回
//IRP 下标CurrentLocation
if(Irp->CurrentLocation==1){
ULONG ReturnedInformation = 0;
DbgPrint("Dispatch encountered bogus current location\n");
status = STATUS_INVALID_DEVICE_REQUEST;
//设置IRP状态 返回IRP 固定写法
Irp->IoStatus.Status = status; //设置IRP状态
Irp->IoStatus.Information = ReturnedInformation;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return status;
}
//全局变量+1
gC2pKeyCount++;
//得到设备扩展 目的获得下一个设备的指针
devExt = (PC2P_DEV_EXT)DeviceObject->DeviceExtension;
//设置回调函数 吧IRP继续传递 读请求结束 剩下的交给回调函数
irpStack = IoGetCurrentIrpStackLocation(Irp);
IoCopyCurrentIrpStackLocationToNext(Irp); //复制当前栈空间
//设置回调
//当IRP完成之后会调用它,需要注意的是完成函数运行在DISPATCH中断级,因此此函数里面的代码尽量不要太多,还有必须使用DISPATCH中断级的函数。
IoSetCompletionRoutine(Irp,
irpCallBackFunction, //回调函数
DeviceObject, //上下文对象
TRUE,TRUE,TRUE
);
//传递到下一个设备
return IoCallDriver(devExt->pLowerDeviceObject,Irp);
}
//入口函数
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING regPath){
ULONG i;
NTSTATUS status;
DbgPrint("Driver start loading。。。。");
//填写所有的分发函数
for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++){
DriverObject->MajorFunction = c2pAllFunction; //(总分发函数)
}
//读取请求分发函数 用来读取键盘的信息
DriverObject ->MajorFunction[IRP_MJ_READ] = c2pDispatchRead;
//电源处理 函数
DriverObject ->MajorFunction[IRP_MJ_POWER] = c2pPower;
//如果键盘被拔掉 这里是一个PNP即插即用函数
DriverObject ->MajorFunction[IRP_MJ_PNP] = c2pPnP;
//卸载函数
DriverObject ->DriverUnload = c2pUnload;
gDriverObject = DriverObject;
//绑定所有键盘设备
status = keycupAttachDevice(DriverObject,regPath);
return status;
} |
|