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; //交回我们的例程处理
}