通过发送SRB的方式来读写U盘的物理扇区
来源:互联网 发布:英灵召唤师 知乎 编辑:程序博客网 时间:2024/05/17 09:38
ULONG g_ulBytesPerSector = 0x200;
NTSTATUS ReadSector(PDEVICE_OBJECT fido,PVOID buffer,ULONG SectorNum, int SectorCount)
{
NTSTATUS status;
PSCSI_REQUEST_BLOCK pSrb;
PSENSE_DATA Sense;
KEVENT Event;
PIRP pIrp;
PMDL pMdl;
IO_STATUS_BLOCK IoSb;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fido->DeviceExtension;
PCDB cdb;
pSrb = (PSCSI_REQUEST_BLOCK)ExAllocatePool(NonPagedPool,sizeof(SCSI_REQUEST_BLOCK));
Sense = (PSENSE_DATA)ExAllocatePool(NonPagedPool,sizeof(SENSE_DATA));
RtlZeroMemory(pSrb,sizeof(SCSI_REQUEST_BLOCK));
RtlZeroMemory(Sense,sizeof(SENSE_DATA));
pSrb->Length = sizeof(SCSI_REQUEST_BLOCK);
pSrb->Function = SRB_FUNCTION_EXECUTE_SCSI;
pSrb->PathId = 0 ;
pSrb->TargetId = 1 ;
pSrb->Lun = 0 ;
pSrb->SrbStatus = 0 ;
pSrb->ScsiStatus = 0 ;
pSrb->NextSrb = 0 ;
pSrb->QueueAction = SRB_FLAGS_DISABLE_AUTOSENSE;
pSrb->DataBuffer = buffer ;
pSrb->DataTransferLength = 512 ;
pSrb->QueueSortKey = SectorNum ;
pSrb->SenseInfoBufferLength = sizeof(SENSE_DATA);
pSrb->SenseInfoBuffer = Sense;
pSrb->SrbFlags = SRB_FLAGS_DATA_IN ;
pSrb->SrbFlags |= SRB_FLAGS_ADAPTER_CACHE_ENABLE;
pSrb->SrbFlags |= SRB_FLAGS_DISABLE_AUTOSENSE;
pSrb->CdbLength = 10;
cdb = (PCDB)pSrb->Cdb;
cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&SectorNum)->Byte3;
cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&SectorNum)->Byte2;
cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&SectorNum)->Byte1;
cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&SectorNum)->Byte0;
cdb->CDB10.TransferBlocksMsb = 0;
cdb->CDB10.TransferBlocksLsb = 1;
cdb->CDB10.OperationCode = SCSIOP_READ;
cdb->CDB10.ForceUnitAccess = TRUE;
KeInitializeEvent(&Event,NotificationEvent,FALSE);
pIrp = IoAllocateIrp(fido->StackSize,0);
pMdl = IoAllocateMdl(buffer,SectorCount*512,0,0,pIrp);
pIrp->MdlAddress = pMdl;
if(!pMdl)
{
ExFreePool(pSrb);
ExFreePool(Sense);
ExFreePool(pIrp);
return STATUS_INSUFFICIENT_RESOURCES;
}
MmProbeAndLockPages(pMdl,0,IoReadAccess);
pSrb->OriginalRequest = pIrp;
pIrp->UserIosb = &IoSb;
pIrp->UserEvent = &Event;
pIrp->IoStatus.Status = 0;
pIrp->IoStatus.Information = 0;
pIrp->Flags = IRP_NOCACHE | IRP_SYNCHRONOUS_API;
pIrp->Cancel = 0;
pIrp->RequestorMode = 0;
pIrp->CancelRoutine = 0;
pIrp->AssociatedIrp.SystemBuffer = 0;
pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
PIO_STACK_LOCATION pIrpSp = IoGetNextIrpStackLocation(pIrp);
pIrpSp->DeviceObject = fido;
pIrpSp->MajorFunction = IRP_MJ_SCSI;
pIrpSp->Parameters.Scsi.Srb = pSrb;
pIrpSp->CompletionRoutine = ReadSectorCompletionRoutine;
pIrpSp->Context = pSrb;
pIrpSp->Control = SL_INVOKE_ON_CANCEL | SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR;
IoSetCompletionRoutine(pIrp,ReadSectorCompletionRoutine,pSrb,1,1,1);
status = IoCallDriver(pdx->LowerDeviceObject,pIrp);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event,Executive,KernelMode,0,0);
status = STATUS_SUCCESS;
}
if (NT_SUCCESS(status) && pSrb->SrbStatus == SRB_STATUS_SUCCESS && pSrb->ScsiStatus == SCSISTAT_GOOD)
{
status = STATUS_SUCCESS;
}
else
{
status = STATUS_UNSUCCESSFUL;
}
__end:
if (pSrb->SenseInfoBuffer && pSrb->SenseInfoBuffer != Sense)
{
ExFreePool(pSrb->SenseInfoBuffer);
}
if (pSrb != NULL)
{
ExFreePool(pSrb);
}
if (Sense != NULL)
{
ExFreePool(Sense);
}
return status;
}
NTSTATUS ReadSectorCompletionRoutine(PDEVICE_OBJECT fido, PIRP pIrp, PVOID Context)
{
pIrp->UserIosb->Information = pIrp->IoStatus.Information;
pIrp->UserIosb->Status = pIrp->IoStatus.Status;
if (Context != NULL && pIrp->MdlAddress != NULL)
{
MmUnlockPages(pIrp->MdlAddress);
IoFreeMdl(pIrp->MdlAddress);
}
KeSetEvent(pIrp->UserEvent, 0, FALSE);
IoFreeIrp(pIrp);
return STATUS_MORE_PROCESSING_REQUIRED; //交回我们的例程处理
}
- 通过发送SRB的方式来读写U盘的物理扇区
- WinCE下的物理扇区读写
- 通过文件的方式对硬盘扇区进行直接读写操作
- 物理扇区和逻辑扇区(相对扇区)的关系
- 使用VB在U盘扇区中读写字符,经过很长时间的研究,终于实现了。
- 读写U盘(FAT32)引导扇区
- 读写U盘(FAT32)引导扇区
- 读写U盘(FAT32)引导扇区
- 通过CreateFile来读取磁盘扇区的方法
- win7的磁盘扇区读写。。。。。。。。。。。。。
- 把自己的操作系统写入U盘(FAT32)引导扇区
- 读写硬盘扇区的C语言程序
- VC、Linux、vxWorks读写物理扇区小结
- VC、Linux、vxWorks读写物理扇区小结
- Windows物理磁盘扇区读写示例总结
- U盘扇区数计算方法
- WinCE系统下应用程序直接读写存储设备(U盘)磁盘扇区
- 不同WINDOWS平台下磁盘逻辑扇区的直接读写
- BPMN术语中英文对照表
- 12/30/2010 geek日志@Android
- 利用IOCTL_STORAGE_QUERY_PROPERT获取总线类型
- Iframe框架自动适应高度示例详解
- 进度计划风险的完整列表
- 通过发送SRB的方式来读写U盘的物理扇区
- 一次C++笔试经历
- 关于sql的查询语句
- Linux的Shell编程
- Android:layout_weight的用法
- h.264视频文件封装
- 由“标准C”“纯C”引发的思考
- VS2010 Build MFC always links gdiplus.dll
- 开始ACM