8866|22

75

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

过滤驱动程序中IRP_MJ_SCSI的下一层是什么? [复制链接]

最近研究U盘过滤驱动,想先读取U盘的扇区,但是一直读不到。从网上找到几个读扇区的代码,也不管用,后来发现是因为重路了。因为我将过滤驱动挂在注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{36FC9E60-C465-11CF-8056-444553540000}下, 要在SCSI的派遣函数里禁用,我想在禁用之前读取U盘扇区,所以在禁用的代码前加入读取U盘扇区的代码,在代码里有这么一段
        isl=IoGetNextIrpStackLocation(irp);
                isl->DeviceObject=dev_object;
                isl->MajorFunction=IRP_MJ_SCSI;
                isl->Parameters.Scsi.Srb=srb;
                isl->CompletionRoutine=IrpCompletionRoutine_0;
                isl->Context=srb;
                isl->Control=SL_INVOKE_ON_CANCEL|SL_INVOKE_ON_SUCCESS|SL_INVOKE_ON_ERROR;
                status=MyIoCallDriver(dev_object,irp);
所以重路了。

我想应该是在SCSI的派遣函数里写SCSI的下一层的读取扇区的代码,因为IRP_MJ_READ的下一层是IRP_MJ_SCSI,所以在SCSI里读扇区时应该写SCSI的下一层的代码,但是我不知道SCSI的下一层是什么?以及该怎么写?

谁有相关的资料?或是哪里可以看到?
或是推荐一本书也行
大家帮帮忙

最新回复

顶  详情 回复 发表于 2009-11-6 10:45
点赞 关注

回复
举报

82

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
你根本不需要写SCSI下一层的代码,只需要组织好你的SRB,发送到设备堆栈的下一个就好了
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
如何组织?
请指出具体怎么做?
 
 
 

回复

74

帖子

0

TA的资源

一粒金砂(初级)

4
 
   其实就是填充_SCSI_REQUEST_BLOCK结构(_IO_STACK_LOCATION.scsi._SCSI_REQUEST_BLOCK):
根据DDK文档很容易填写,里面有一个关键的字结构——在_SCSI_REQUEST_BLOCK结构最后是UCHAR Cdb[16];但是Cdb不一定是16个字节,长度由_SCSI_REQUEST_BLOCK.CdbLength决定。
    CDB[0]为OperationCode,28h表示SCSIOP_READ,2Ah表示SCSIOP_WRITE。_CDB[1]按位描 述了一些属性,可以参考scsi.h,这里将这个字节设为80h。_CDB[2]到_CDB[5]描述的是扇区位置,依次为dwSectorLowPos 从高字节到低字节的值。CDB[7]和CDB[8]描述了要写书的扇区数。如果小于0,则设为1。



 
 
 

回复

88

帖子

0

TA的资源

一粒金砂(初级)

5
 
LZ好厉害
 
 
 

回复

72

帖子

0

TA的资源

一粒金砂(初级)

6
 
我是才用下面的方法禁用U盘的,见下面的代码:
插入U盘时任务栏会提示U插入,但是我的电脑里没有U盘的盘符

我想知道当刚刚插入U盘但没有显示盘符时时能不能读取到磁盘的扇区?

if (_wcsnicmp(DeviceObject->AttachedDevice->DriverObject->DriverName.Buffer,L"\\Driver\\USBSTOR",15)==0)
        {
               
                PVOID buffer;
                buffer=ExAllocatePool(0,512);
                RtlZeroMemory(buffer,512);
                //读扇区
                status = AtapiReadWriteDisk(fido,IRP_MJ_READ,buffer,1,1,Irp);
                if (NT_SUCCESS(status))
                {       
                        Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
                         Irp->IoStatus.Information = 0;
                        IoCompleteRequest( Irp, IO_NO_INCREMENT );
                        ExFreePool(buffer);
                        return STATUS_ACCESS_DENIED;
                }
    }
 
 
 

回复

58

帖子

0

TA的资源

一粒金砂(初级)

7
 
我是这么写的,不知道对不对,今天电脑系统崩溃了,两个系统都不能用了,一直在装系统,大侠给看看       
srb = (PSCSI_REQUEST_BLOCK)ExAllocatePool(NonPagedPool,sizeof(SCSI_REQUEST_BLOCK));
                if(!srb)
                        break;
                sense = (PSENSE_DATA)ExAllocatePool(NonPagedPool,sizeof(SENSE_DATA));
                psense=sense;
                if(!sense)
                        break;
                memset(srb,0,sizeof(SCSI_REQUEST_BLOCK));
                memset(sense,0,sizeof(SENSE_DATA));

        //更多关于srb,请看《SCSI 总线和IDE接口:协议、应用和编程》和《SCSI程序员指南》
                srb->Length=sizeof(SCSI_REQUEST_BLOCK);
                srb->Function=0;
                srb->DataBuffer=buffer;
                srb->DataTransferLength=BlockCount<<9;    //sector size*number of sector
                srb->QueueAction=SRB_FLAGS_DISABLE_AUTOSENSE;
                srb->SrbStatus=0;
                srb->ScsiStatus=0;
                srb->NextSrb=0;
                srb->SenseInfoBuffer=sense;
                srb->SenseInfoBufferLength=sizeof(SENSE_DATA);

//                 if(MajorFunction==IRP_MJ_READ)
                        srb->SrbFlags=SRB_FLAGS_DATA_IN;
                       
//                 if(MajorFunction==IRP_MJ_READ)
                        srb->SrbFlags|=SRB_FLAGS_ADAPTER_CACHE_ENABLE;
               
                srb->SrbFlags|=SRB_FLAGS_DISABLE_AUTOSENSE;
                srb->TimeOutValue=(srb->DataTransferLength>>10)+1;
                srb->QueueSortKey=DiskPos;
                srb->CdbLength=10;
                //srb->Cdb[0] = 2*((UCHAR)MajorFunction+ 17);
        srb->Cdb[0] = SCSIOP_READ;
                srb->Cdb[1] = srb->Cdb[1] & 0x1F | 0x80;
                srb->Cdb[2] = (unsigned char)(DiskPos>>0x18)&0xFF;    //
                srb->Cdb[3] = (unsigned char)(DiskPos>>0x10)&0xFF;    //
                srb->Cdb[4] = (unsigned char)(DiskPos>>0x08)&0xFF;    //
                srb->Cdb[5] = (UCHAR)DiskPos;          //填写sector位置
                srb->Cdb[7] = (UCHAR)BlockCount>>0x08;
                srb->Cdb[8] = (UCHAR)BlockCount;
 
 
 

回复

56

帖子

0

TA的资源

一粒金砂(初级)

8
 

                KeInitializeEvent(&Event, NotificationEvent, FALSE);
                irp=IoAllocateIrp(dev_object->StackSize,0);
                mdl=IoAllocateMdl(buffer, BlockCount<<9, 0, 0, irp);
                Irp->MdlAddress=mdl;
                if(!mdl)
                {
                        ExFreePool(srb);
                        ExFreePool(psense);
                        IoFreeIrp(irp);
                        return STATUS_INSUFFICIENT_RESOURCES;
                }
                //MmProbeAndLockPages(mdl,0,(MajorFunction==IRP_MJ_READ?0:1));
                MmProbeAndLockPages(mdl,0,IoReadAccess);
                srb->OriginalRequest=irp;
                irp->UserIosb=&isb;
                irp->UserEvent=&Event;
                irp->IoStatus.Status=0;
                irp->IoStatus.Information=0;
                irp->Flags=IRP_SYNCHRONOUS_API|IRP_NOCACHE;
                irp->AssociatedIrp.SystemBuffer=0;
                irp->Cancel=0;
                irp->RequestorMode=0;
                irp->CancelRoutine=0;
                irp->Tail.Overlay.Thread=PsGetCurrentThread();

                isl=IoGetNextIrpStackLocation(Irp);
                isl->DeviceObject=dev_object;
                //isl->MajorFunction=IRP_MJ_SCSI;
                isl->Parameters.Scsi.Srb=srb;
                isl->CompletionRoutine=IrpCompletionRoutine_0;
                isl->Context=srb;
                isl->Control=SL_INVOKE_ON_CANCEL|SL_INVOKE_ON_SUCCESS|SL_INVOKE_ON_ERROR;

                status=IoCallDriver(pdx->LowerDeviceObject,irp);
                KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, 0);
 
 
 

回复

90

帖子

0

TA的资源

一粒金砂(初级)

9
 
你之所以没有被检测出盘符,是因为你的过滤驱动是挂在{36FC9E60-C465-11CF-8056-444553540000}下,而不是{4D36E967-E325-11CE-BFC1-08002BE10318}。前者是USB Controller的GUID,后者是U盘这类Disk Device的Class GUID。

你的读写扇区的代码应该没有什么问题。有问题稍微调试一下应该没有什么大碍。

//MmProbeAndLockPages(mdl,0,(MajorFunction==IRP_MJ_READ?0:1));
//isl->MajorFunction=IRP_MJ_SCSI;
这两条语句不应该注掉
 
 
 

回复

62

帖子

0

TA的资源

一粒金砂(初级)

10
 
isl->MajorFunction=IRP_MJ_SCSI;
这条语句如果不注释掉,会反复进入SCSI的派遣函数,不能读取U盘扇区
 
 
 

回复

77

帖子

0

TA的资源

一粒金砂(初级)

11
 
我想知道当刚刚插入U盘但没有显示盘符时时能不能读取到磁盘的扇区?
也就是说,当程序执行到SCSI的派遣函数里的这行语句时,if (_wcsnicmp(DeviceObject->AttachedDevice->DriverObject->DriverName.Buffer,L"\\Driver\\USBSTOR",15)==0)

在这里构造srb能否读取到U盘扇区?

#pragma LOCKEDCODE
NTSTATUS DispatchForSCSI(IN PDEVICE_OBJECT fido, IN PIRP Irp)
{
    KdPrint((DRIVERNAME " - Enter DispatchForSCSI \n"));
    //获得设备扩展
        PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
        //获得I/O堆栈
        PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
        PDEVICE_OBJECT DeviceObject = pdx->DeviceObject;
        NTSTATUS status;

        if (_wcsnicmp(DeviceObject->AttachedDevice->DriverObject->DriverName.Buffer,L"\\Driver\\USBSTOR",15)==0) //程序执行到这里,能读取到U盘扇区吗?
        {
 
 
 

回复

86

帖子

0

TA的资源

一粒金砂(初级)

12
 
读不读得到扇区,只取决于你是否向磁盘(这里是U盘)设备发送了IRP_MJ_SCSI,你的IRP没有该功能码肯定是有问题的,而且我在前面已经说了,你要把你的过滤驱动挂在Disk类驱动上面,这样你在CallDriver时比较容易直接发送该IRP给磁盘(U盘)设备。而且不存在什么IRP_MJ_SCSI重入问题。
在上述解决方案中,唯一需要考虑的是如何区别出普通磁盘还是U盘。这其实也很容易,发送IOCTL_STORAGE_QUERY_PROPERTY,就可以知道类型。
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

13
 
学习
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

14
 
不好意思,前面的说法有一点问题。IRP_MJ_SCSI重入问题还是存在,不过这个问题可以用影设备之类的方式来解决。
 
 
 

回复

68

帖子

0

TA的资源

一粒金砂(初级)

15
 
如何发送IOCTL_STORAGE_QUERY_PROPERTY?
要创建一个IRP传递下去吗?
小弟刚做这个不久,还请不吝赐教。
原来我的过滤驱动挂在Disk类驱动下面,但是重启容易蓝屏。
如果将过滤驱动挂在Disk类驱动上面,在那个派遣函数里禁用U盘?
在IRP_MJ_CREATE的派遣函数里吗?
 
 
 

回复

77

帖子

0

TA的资源

一粒金砂(初级)

16
 
如果将过滤驱动挂在Disk类驱动上面,是不是要在{4D36E967-E325-11CE-BFC1-08002BE10318}里加一个UpperFilters,是不是要和PartMgr放在一起?在PartMgr后面加一个空格然后将我的过滤驱动的名字填上?
 
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

17
 
发送IOCTL_STORAGE_QUERY_PROPERTY和发送普通的IRP的方法是一样的,自己根据DDK文档的描述填写。
你挂在Disk下面也可以,只要按照我之前说的方法处理好U盘和普通磁盘的区别,以及IRP_MJ_SCSI的重入就好了。你之前蓝屏的原因有以下可能:
(1)没有处理IRP_MJ_SCSI的重入
(2)没有正确PassThrough IRP给下层设备。因为你的驱动挂在Disk Driver下面,所有磁盘的访问都会经过你的驱动,如果你的驱动没有正确把IRP传递到下层设备,则系统启动都会有问题(会读启动分区),蓝屏自然。
至于你说要在哪个函数里禁用,这个看你自己的选择了。你可以在PNP的START DEVICE例程里就禁用:
case IRP_MN_START_DEVICE:
  //CallLowerDeviceDriver()
  //SendSRBToRead()
  break;
 
 
 

回复

63

帖子

0

TA的资源

禁止发言

18
 
我想要实现的功能是先读取U盘扇区,找到我写入的标识,如果没有这个标识,则禁用U盘。所以我想不能在START DEVICE里直接禁用吧。

明天我再试验一下区分U盘和硬盘。

谢谢jintianyishiyeai
 
 
 

回复

82

帖子

0

TA的资源

一粒金砂(初级)

19
 
我想在禁用U盘时,电脑里不会出现U盘的盘符,同时任务栏也不会出现U盘的图标,是不是将过滤驱动挂在注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{36FC9E60-C465-11CF-8056-444553540000}下,这样的效果最好。

记得前一段实验时如果挂载在disk的下面,没有盘符,但是任务栏里会有U盘的图标。
 
 
 

回复

72

帖子

0

TA的资源

一粒金砂(初级)

20
 
我决定把过滤驱动放到disk的上面,但是和PartMgr放在一起会蓝屏,这是怎么回事?过滤驱动的启动类型应该是多少?0还是3?

我只是在代码里加入了IRP_MJ_CREATE的派遣函数

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表