NTSTATUS ReadWriteDisk( PDEVICE_OBJECT DeviceObject, ULONG SectorOffset, ULONG IsReadOperation, // = 0 means is a write operation otherwise is read PVOID Buffer, ULONG SectorCount, PIO_STATUS_BLOCK IoStatusBlock ) { SENSE_DATA SenseData; // error info - - SCSI_REQUEST_BLOCK ScsiRequestBlock; PCDB CommandDescriptorBlock; PIRP Irp; PIO_STACK_LOCATION IrpSp; PMDL Mdl; KEVENT Event; NTSTATUS Status = STATUS_UNSUCCESSFUL; if (SectorCount > 0xFFFF) { return STATUS_INVALID_PARAMETER; } RtlZeroMemory(&SenseData, sizeof(SENSE_DATA)); RtlZeroMemory(&ScsiRequestBlock, sizeof(SCSI_REQUEST_BLOCK)); ScsiRequestBlock.Length = sizeof(SCSI_REQUEST_BLOCK); ScsiRequestBlock.Function = SRB_FUNCTION_EXECUTE_SCSI; ScsiRequestBlock.DataBuffer = Buffer; ScsiRequestBlock.SenseInfoBuffer = &SenseData; ScsiRequestBlock.SenseInfoBufferLength = sizeof(SENSE_DATA); ScsiRequestBlock.DataTransferLength = SectorCount * BytesPerSector; ScsiRequestBlock.QueueAction = SRB_FLAGS_DISABLE_AUTOSENSE; // Indicates that request-sense information should not be returned ??? ScsiRequestBlock.SrbFlags = IsReadOperation ? SRB_FLAGS_DATA_IN : SRB_FLAGS_DATA_OUT; ScsiRequestBlock.SrbFlags |= IsReadOperation ? SRB_FLAGS_ADAPTER_CACHE_ENABLE : 0; ScsiRequestBlock.SrbFlags |= SRB_FLAGS_DISABLE_AUTOSENSE; ScsiRequestBlock.TimeOutValue = -1; second ScsiRequestBlock.QueueSortKey = SectorOffset; // Specifies the offset from the start of the media or zero, depending on the type of the target device. ScsiRequestBlock.CdbLength = 10; // sizeof(CDB.CDB10); CommandDescriptorBlock = (PCDB)ScsiRequestBlock.Cdb; CommandDescriptorBlock->CDB10.OperationCode = IsReadOperation ? SCSIOP_READ : SCSIOP_WRITE; CommandDescriptorBlock->CDB10.LogicalUnitNumber = 0; // ??????????? what's this? CommandDescriptorBlock->CDB10.Reserved1 = 0; // in fact, not needed. // ForceUnitAccess, RelativeAddress, DisablePageOut remains still - in fact, remains 0. CommandDescriptorBlock->CDB10.LogicalBlockByte0 = (UCHAR)(SectorOffset >> 0x18); CommandDescriptorBlock->CDB10.LogicalBlockByte1 = (UCHAR)(SectorOffset >> 0x10); CommandDescriptorBlock->CDB10.LogicalBlockByte2 = (UCHAR)(SectorOffset >> 0x8); CommandDescriptorBlock->CDB10.LogicalBlockByte3 = (UCHAR)(SectorOffset); CommandDescriptorBlock->CDB10.Reserved2 = 0; CommandDescriptorBlock->CDB10.TransferBlocksMsb = (UCHAR)(SectorCount >> 0x8); CommandDescriptorBlock->CDB10.TransferBlocksLsb = (UCHAR)(SectorCount); CommandDescriptorBlock->CDB10.Control = 0; // how to initialize this? KeInitializeEvent(&Event, NotificationEvent, FALSE); Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); if (!Irp) { return STATUS_INSUFFICIENT_RESOURCES; } Mdl = IoAllocateMdl(Buffer, SectorCount * BytesPerSector, FALSE, FALSE, Irp); if (!Mdl) { IoFreeIrp(Irp); return STATUS_INSUFFICIENT_RESOURCES; } MmProbeAndLockPages(Mdl, KernelMode, IsReadOperation ? IoReadAccess : IoWriteAccess); ScsiRequestBlock.OriginalRequest = Irp; Irp->UserIosb = IoStatusBlock; Irp->UserEvent = &Event; RtlZeroMemory(&Irp->IoStatus, sizeof(IO_STATUS_BLOCK)); Irp->MdlAddress = Mdl; Irp->AssociatedIrp.SystemBuffer = NULL; Irp->Cancel = FALSE; Irp->CancelRoutine = NULL; Irp->Flags = IRP_NOCACHE | IRP_SYNCHRONOUS_API; Irp->RequestorMode = KernelMode; Irp->Tail.Overlay.Thread = PsGetCurrentThread(); IrpSp = IoGetNextIrpStackLocation(Irp); IrpSp->DeviceObject = DeviceObject; IrpSp->MajorFunction = IRP_MJ_SCSI; IrpSp->Parameters.Scsi.Srb = &ScsiRequestBlock; IoSetCompletionRoutine(Irp, IoCompletionRoutine, &ScsiRequestBlock, TRUE, TRUE, TRUE); Status = IoCallDriver(DeviceObject, Irp); if (Status == STATUS_PENDING) { (VOID)KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); Status = STATUS_SUCCESS; } if ((ScsiRequestBlock.SenseInfoBuffer != &SenseData) && (ScsiRequestBlock.SenseInfoBuffer)) { ExFreePool(ScsiRequestBlock.SenseInfoBuffer); // should we do this? DbgPrint("[ ??ìì?¤°Yò?′? XHR ′ó?£ ] Information: Freed ScsiRequestBlock.SenseInfoBuffer.\n"); } if (NT_SUCCESS(Status) && ((ScsiRequestBlock.SrbStatus == SRB_STATUS_SUCCESS) || (ScsiRequestBlock.SrbStatus == SRB_STATUS_PENDING)) && (ScsiRequestBlock.ScsiStatus == SCSISTAT_GOOD) ) { //DbgPrint("[ ??ìì?¤°Yò?′? XHR ′ó?£ ] Information: ReadWriteDisk operation succeeded.\n"); Status = STATUS_SUCCESS; } else { DbgPrint("[ ??ìì?¤°Yò?′? XHR ′ó?£ ] Error: ReadWriteDisk fails with NT status 0x%X, Scsi status 0x%X and Srb status 0x%X.\n", Status, ScsiRequestBlock.ScsiStatus, ScsiRequestBlock.SrbStatus); Status = STATUS_UNSUCCESSFUL; } return Status; }
转载于:https://www.cnblogs.com/fanzi2009/archive/2009/05/07/1451201.html