NTSTATUS ReadWriteDisk(...) (转载)

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

猜你喜欢

转载自blog.csdn.net/weixin_33810006/article/details/94192486