tendollor
驱动牛犊
驱动牛犊
  • 注册日期2010-05-22
  • 最后登录2010-12-09
  • 粉丝1
  • 关注1
  • 积分7分
  • 威望61点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:3097回复:1

替换分发函数指针的问题

楼主#
更多 发布于:2010-12-08 16:10
#define KBD_DRIVER_NAME  L"\\Driver\\Kbdclass" 
//这个数组用来保存所有有的旧指针 
PDRIVER_DISPATCH OldDispatchFunctions[IRP_MJ_MAXIMUM_FUNCTION+1]; 
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath) 
{ 
NTSTATUS status; 
//HANDLE hMyThread; //线程句柄 
PDRIVER_OBJECT kbddriverobj; //保存键盘驱动对象的变量 
UNICODE_STRING kbddrivername; //键盘驱动对象的名称 

ULONG i; //for循环变量 

RtlInitUnicodeString(&kbddrivername,KBD_DRIVER_NAME); 
//通过驱动名字获取驱动对象 这个只适合获取驱动对象,获取设备对象最好不要用这个,第七个参数会很麻烦. 
status = ObReferenceObjectByName(&kbddrivername,OBJ_CASE_INSENSITIVE,NULL,0,IoDriverObjectType,KernelMode,NULL,&kbddriverobj); 
if(!NT_SUCCESS(status)) 
{ 
//如果获取失败 输出信息 返回 
DbgPrint("%w驱动对象获取失败!",&kbddrivername); 
return STATUS_UNSUCCESSFUL; 
} 
else 
{ 
//只要调用过Reference系列的函数就都要通过ObDereferenceObject来解除引用 
ObDereferenceObject(kbddriverobj); 
} 

//转发所有分发函数 
for(i=0;i<=IRP_MJ_MAXIMUM_FUNCTION;++i) 
{ 
OldDispatchFunctions=kbddriverobj->MajorFunction;//先保存旧指针 
//使用原子交互的函数 来替换分发函数的指针 
InterlockedExchangePointer(kbddriverobj->MajorFunction,myfilterdispatch); 
} 

DriverObject->DriverUnload=UnLoad; //设置驱动卸载函数 
return STATUS_SUCCESS; //返回值 
}



在for循环第四次执行InterlockedExchangePointer(kbddriverobj->MajorFunction,myfilterdispatch);
的时候蓝屏这不是个原子操作吗?原子操作是不是特别快速基本不会因为其他程序干扰他的执行?
寒江独钓中针对这个代码的说明是 作者没有测试 理论上可行 除非正在for循环的过程中 有新的几个IRP要 处理
但是还没完全设置完...他们之间本身有关联 这样就破坏了关联性...我还是不知道执行起来最终是个什么流程..
感觉至少应该执行完FOR循环 但是跳到IRP分发函数的时候才蓝屏啊...还是说这里设置IRP 分发函数 并不影响IRP 的处理?设置过程就一边在处理? 那之前用绑定的方式也是循环设置IRP 分发函数啊....为什么那时候不出错呢?
寒江独钓说出错的概率非常小...但是我每次都是到第四次循环就蓝屏....应该是其他的问题吗?
求大牛指点...

我再给出我的分发函数吧不知道是不是函数指针的使用上出错了?
NTSTATUS myfilterdispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) 
{ 
/*此段代码是针对绑定过滤设备的情况下 分发函数下发给被绑定的设备 
// 通用的分发函数,直接skip然后用IoCallDriver把IRP发送到真实设备 
// 的设备对象。 
KdPrint(("Other Diapatch!")); 
IoSkipCurrentIrpStackLocation(Irp); 
return IoCallDriver(((PC2P_DEV_EXT) 
DeviceObject->DeviceExtension)->LowerDeviceObject, Irp); 
此段代码是针对绑定过滤设备的情况下 分发函数下发给被绑定的设备*/ 

//而我们是事先保存了指针的,而且没有绑定设备所以,直接调用原来的分发函数就行了. 
//其实我们只需要修改读操作IRP分发函数的指针,没必要多此一举,这样也就是试试行不行吧. 
PC2P_DEV_EXT devExt; 
PIO_STACK_LOCATION irpStack; 
NTSTATUS status = STATUS_SUCCESS; 
KIRQL oldIrql; 
KEVENT event; 

// 获得真实设备。 
//devExt = (PC2P_DEV_EXT)(DeviceObject->DeviceExtension); 
//从IRP栈获取当前IRP信息 
irpStack = IoGetCurrentIrpStackLocation(Irp); 
switch (irpStack->MajorFunction) 
{ 
case IRP_MJ_READ: 
#if DBG 
_asm int 3 
#endif 
KdPrint(("IRP_MJ_READ\n")); 
(*OldDispatchFunctions[irpStack->MajorFunction])(DeviceObject,Irp); 
default: 
#if DBG 
_asm int 3 
#endif 
KdPrint(("other\n")); 
(*OldDispatchFunctions[irpStack->MajorFunction]) (DeviceObject,Irp); 
} 
/* 
switch (irpStack->MinorFunction)//这里是选择小类 我们替换指针 直接选择大类 
{ 
case IRP_MN_REMOVE_DEVICE: 
KdPrint(("IRP_MN_REMOVE_DEVICE\n")); 

// 首先把请求发下去 
IoSkipCurrentIrpStackLocation(Irp); 
IoCallDriver(devExt->LowerDeviceObject, Irp); 
// 然后解除绑定。 
IoDetachDevice(devExt->LowerDeviceObject); 
// 删除我们自己生成的虚拟设备。 
IoDeleteDevice(DeviceObject); 
status = STATUS_SUCCESS; 
break; 

default: 
// 对于其他类型的IRP,全部都直接下发即可。 
IoSkipCurrentIrpStackLocation(Irp); 
status = IoCallDriver(devExt->LowerDeviceObject, Irp); 
} */ 
return status; 

}

wxj120bw
驱动小牛
驱动小牛
  • 注册日期2008-06-14
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分109分
  • 威望1014点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2010-12-13 23:29
这是个完整的驱动程序吗?
游客

返回顶部