class2.c
来自「一个类似windows」· C语言 代码 · 共 2,461 行 · 第 1/5 页
C
2,461 行
return(Status);
}
/*
* @implemented
*/
NTSTATUS STDCALL
ScsiClassIoCompleteAssociated(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context)
{
PDEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION IrpStack;
PSCSI_REQUEST_BLOCK Srb;
PIRP MasterIrp;
BOOLEAN Retry;
LONG RequestCount;
NTSTATUS Status;
DPRINT("ScsiClassIoCompleteAssociated(DeviceObject %p Irp %p Context %p) called\n",
DeviceObject, Irp, Context);
MasterIrp = Irp->AssociatedIrp.MasterIrp;
DeviceExtension = DeviceObject->DeviceExtension;
IrpStack = IoGetCurrentIrpStackLocation(Irp);
/*
* BUGBUG -> Srb = Srb = IrpStack->Parameters.Scsi.Srb;
* Must pass Srb as Context arg!! See comment about Completion routines in
* IofCallDriver for more info.
*/
Srb = (PSCSI_REQUEST_BLOCK)Context;
DPRINT("Srb %p\n", Srb);
if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS)
{
Status = STATUS_SUCCESS;
}
else
{
/* Release the queue if it is frozen */
if (Srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN)
{
ScsiClassReleaseQueue (DeviceObject);
}
/* Get more detailed status information */
Retry = ScsiClassInterpretSenseInfo(DeviceObject,
Srb,
IrpStack->MajorFunction,
0,
MAXIMUM_RETRIES - ((ULONG)IrpStack->Parameters.Others.Argument4),
&Status);
/* Retry the request if verify should be overridden */
if ((IrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME) &&
Status == STATUS_VERIFY_REQUIRED)
{
Status = STATUS_IO_DEVICE_ERROR;
Retry = TRUE;
}
/* Retry the request */
if ((Retry) &&
((ULONG_PTR)IrpStack->Parameters.Others.Argument4 > 0))
{
IrpStack->Parameters.Others.Argument4 = (PVOID) ((ULONG_PTR)IrpStack->Parameters.Others.Argument4 - 1);
ScsiClassRetryRequest(DeviceObject,
Irp,
Srb,
TRUE);
return(STATUS_MORE_PROCESSING_REQUIRED);
}
}
/* Free the SRB */
ExFreeToNPagedLookasideList(&DeviceExtension->SrbLookasideListHead,
Srb);
Irp->IoStatus.Status = Status;
IrpStack = IoGetNextIrpStackLocation(MasterIrp);
if (!NT_SUCCESS(Status))
{
MasterIrp->IoStatus.Status = Status;
MasterIrp->IoStatus.Information = 0;
if (IoIsErrorUserInduced(Status))
{
IoSetHardErrorOrVerifyDevice(MasterIrp,
DeviceObject);
}
}
/* Decrement the request counter in the Master IRP */
RequestCount = InterlockedDecrement((PLONG)&IrpStack->Parameters.Others.Argument1);
if (RequestCount == 0)
{
/* Complete the Master IRP */
IoCompleteRequest(MasterIrp,
IO_DISK_INCREMENT);
if (DeviceExtension->ClassStartIo)
{
KIRQL oldIrql;
oldIrql = KeGetCurrentIrql();
if (oldIrql < DISPATCH_LEVEL)
{
KeRaiseIrql (DISPATCH_LEVEL, &oldIrql);
IoStartNextPacket (DeviceObject, FALSE);
KeLowerIrql(oldIrql);
}
else
{
IoStartNextPacket (DeviceObject, FALSE);
}
}
}
/* Free the current IRP */
IoFreeIrp(Irp);
return(STATUS_MORE_PROCESSING_REQUIRED);
}
/*
* @implemented
*/
ULONG STDCALL
ScsiClassModeSense(IN PDEVICE_OBJECT DeviceObject,
IN PCHAR ModeSenseBuffer,
IN ULONG Length,
IN UCHAR PageMode)
{
PDEVICE_EXTENSION DeviceExtension;
SCSI_REQUEST_BLOCK Srb;
ULONG RetryCount;
PCDB Cdb;
NTSTATUS Status;
DPRINT("ScsiClassModeSense() called\n");
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
RetryCount = 1;
/* Initialize the SRB */
RtlZeroMemory (&Srb,
sizeof(SCSI_REQUEST_BLOCK));
Srb.CdbLength = 6;
Srb.TimeOutValue = DeviceExtension->TimeOutValue;
/* Initialize the CDB */
Cdb = (PCDB)&Srb.Cdb;
Cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
Cdb->MODE_SENSE.PageCode = PageMode;
Cdb->MODE_SENSE.AllocationLength = (UCHAR)Length;
TryAgain:
Status = ScsiClassSendSrbSynchronous (DeviceObject,
&Srb,
ModeSenseBuffer,
Length,
FALSE);
if (Status == STATUS_VERIFY_REQUIRED)
{
if (RetryCount != 0)
{
RetryCount--;
goto TryAgain;
}
}
else if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN)
{
Status = STATUS_SUCCESS;
}
if (!NT_SUCCESS(Status))
{
return 0;
}
return Srb.DataTransferLength;
}
/*
* @implemented
*/
ULONG STDCALL
ScsiClassQueryTimeOutRegistryValue(IN PUNICODE_STRING RegistryPath)
{
PRTL_QUERY_REGISTRY_TABLE Table;
ULONG TimeOutValue;
ULONG ZeroTimeOut;
ULONG Size;
PWSTR Path;
NTSTATUS Status;
if (RegistryPath == NULL)
{
return 0;
}
TimeOutValue = 0;
ZeroTimeOut = 0;
/* Allocate zero-terminated path string */
Size = RegistryPath->Length + sizeof(WCHAR);
Path = (PWSTR)ExAllocatePool (NonPagedPool,
Size);
if (Path == NULL)
{
return 0;
}
RtlZeroMemory (Path,
Size);
RtlCopyMemory (Path,
RegistryPath->Buffer,
Size - sizeof(WCHAR));
/* Allocate query table */
Size = sizeof(RTL_QUERY_REGISTRY_TABLE) * 2;
Table = (PRTL_QUERY_REGISTRY_TABLE)ExAllocatePool (NonPagedPool,
Size);
if (Table == NULL)
{
ExFreePool (Path);
return 0;
}
RtlZeroMemory (Table,
Size);
Table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
Table[0].Name = L"TimeOutValue";
Table[0].EntryContext = &TimeOutValue;
Table[0].DefaultType = REG_DWORD;
Table[0].DefaultData = &ZeroTimeOut;
Table[0].DefaultLength = sizeof(ULONG);
Status = RtlQueryRegistryValues (RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
Path,
Table,
NULL,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT("RtlQueryRegistryValue() failed (Status %lx)\n", Status);
TimeOutValue = 0;
}
ExFreePool (Table);
ExFreePool (Path);
DPRINT("TimeOut: %lu\n", TimeOutValue);
return TimeOutValue;
}
/*
* @implemented
*/
NTSTATUS STDCALL
ScsiClassReadDriveCapacity(IN PDEVICE_OBJECT DeviceObject)
{
PDEVICE_EXTENSION DeviceExtension;
PREAD_CAPACITY_DATA CapacityBuffer;
SCSI_REQUEST_BLOCK Srb;
PCDB Cdb;
NTSTATUS Status;
ULONG LastSector;
ULONG SectorSize;
ULONG RetryCount = 1;
DPRINT("ScsiClassReadDriveCapacity() called\n");
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
CapacityBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
sizeof(READ_CAPACITY_DATA));
if (CapacityBuffer == NULL)
{
return(STATUS_INSUFFICIENT_RESOURCES);
}
RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK));
Srb.CdbLength = 10;
Srb.TimeOutValue = DeviceExtension->TimeOutValue;
Cdb = (PCDB)Srb.Cdb;
Cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY;
TryAgain:
Status = ScsiClassSendSrbSynchronous(DeviceObject,
&Srb,
CapacityBuffer,
sizeof(READ_CAPACITY_DATA),
FALSE);
DPRINT("Status: %lx\n", Status);
DPRINT("Srb: %p\n", &Srb);
if (NT_SUCCESS(Status))
{
SectorSize = (((PUCHAR)&CapacityBuffer->BytesPerBlock)[0] << 24) |
(((PUCHAR)&CapacityBuffer->BytesPerBlock)[1] << 16) |
(((PUCHAR)&CapacityBuffer->BytesPerBlock)[2] << 8) |
((PUCHAR)&CapacityBuffer->BytesPerBlock)[3];
LastSector = (((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[0] << 24) |
(((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[1] << 16) |
(((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[2] << 8) |
((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[3];
DeviceExtension->DiskGeometry->BytesPerSector = SectorSize;
DeviceExtension->PartitionLength.QuadPart = (LONGLONG)(LastSector + 1);
WHICH_BIT(DeviceExtension->DiskGeometry->BytesPerSector,
DeviceExtension->SectorShift);
DeviceExtension->PartitionLength.QuadPart =
(DeviceExtension->PartitionLength.QuadPart << DeviceExtension->SectorShift);
DeviceExtension->PartitionLength.QuadPart =
(DeviceExtension->PartitionLength.QuadPart -
DeviceExtension->StartingOffset.QuadPart);
if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
{
DeviceExtension->DiskGeometry->MediaType = RemovableMedia;
}
else
{
DeviceExtension->DiskGeometry->MediaType = FixedMedia;
}
DeviceExtension->DiskGeometry->Cylinders.QuadPart = (LONGLONG)((LastSector + 1)/(32 * 64));
DeviceExtension->DiskGeometry->SectorsPerTrack = 32;
DeviceExtension->DiskGeometry->TracksPerCylinder = 64;
DPRINT("SectorSize: %lu SectorCount: %lu PartitionLenght %I64d\n", SectorSize, LastSector + 1,
DeviceExtension->PartitionLength.QuadPart / 512 );
}
/* Try again if device needs to be verified */
if (Status == STATUS_VERIFY_REQUIRED)
{
if (RetryCount > 0)
{
RetryCount--;
goto TryAgain;
}
}
if (!NT_SUCCESS(Status))
{
/* Use default values if disk geometry cannot be read */
RtlZeroMemory(DeviceExtension->DiskGeometry,
sizeof(DISK_GEOMETRY));
DeviceExtension->DiskGeometry->BytesPerSector = 512;
DeviceExtension->SectorShift = 9;
DeviceExtension->PartitionLength.QuadPart = 0;
if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
{
DeviceExtension->DiskGeometry->MediaType = RemovableMedia;
}
else
{
DeviceExtension->DiskGeometry->MediaType = FixedMedia;
}
DPRINT("SectorSize: 512 SectorCount: 0\n");
}
ExFreePool(CapacityBuffer);
DPRINT("ScsiClassReadDriveCapacity() done\n");
return(Status);
}
/*
* @implemented
*/
VOID STDCALL
ScsiClassReleaseQueue(IN PDEVICE_OBJECT DeviceObject)
{
PDEVICE_EXTENSION DeviceExtension;
PCOMPLETION_CONTEXT Context;
PIO_STACK_LOCATION Stack;
PSCSI_REQUEST_BLOCK Srb;
KIRQL Irql;
PCDB Cdb;
PIRP Irp;
DPRINT("ScsiClassReleaseQueue() called\n");
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* Allocate and initialize the completion context */
Context = ExAllocatePool (NonPagedPoolMustSucceed,
sizeof (COMPLETION_CONTEXT));
Context->DeviceObject = DeviceObject;
/* Initialize the SRB */
Srb = &Context->Srb;
RtlZeroMemory (Srb,
sizeof (SCSI_REQUEST_BLOCK));
Srb->Length = sizeof (SCSI_REQUEST_BLOCK);
Srb->PathId = DeviceExtension->PathId;
Srb->TargetId = DeviceExtension->TargetId;
Srb->Lun = DeviceExtension->Lun;
Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
Srb->TimeOutValue = START_UNIT_TIMEOUT;
Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER |
SRB_FLAGS_DISABLE_AUTOSENSE |
SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
Srb->CdbLength = 6;
/* Initialize the CDB */
Cdb = (PCDB)&Srb->Cdb;
Cdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
Cdb->START_STOP.Start = 1;
Cdb->START_STOP.LogicalUnitNumber = Srb->Lun;
/* Build the IRP */
Irp = IoAllocateIrp (DeviceObject->StackSize, FALSE);
IoSetCompletionRoutine (Irp,
(PIO_COMPLETION_ROUTINE)ScsiClassAsynchronousCompletion,
Context,
NULL,
NULL,
NULL);
/* Attach SRB to the IRP */
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
Stack = IoGetNextIrpStackLocation(Irp);
Stack->MajorFunction = IRP_MJ_SCSI;
Stack->Parameters.Scsi.Srb = Srb;
Srb->OriginalRequest = Irp;
/* Call the port driver */
Irql = KeGetCurrentIrql ();
if (Irql < DISPATCH_LEVEL)
{
KeRaiseIrql (DISPATCH_LEVEL, &Irql);
IoCallDriver (DeviceExtension->PortDeviceObject, Irp);
KeLowerIrql (Irql);
}
else
{
IoCallDriver (DeviceExtension->PortDeviceObject, Irp);
}
DPRINT("ScsiClassReleaseQueue() done\n");
}
/*
* @implemented
*/
NTSTATUS STDCALL
ScsiClassSendSrbAsynchronous(PDEVICE_OBJECT DeviceObject,
PSCSI_REQUEST_BLOCK Srb,
PIRP Irp,
PVOID BufferAddress,
ULONG BufferLength,
BOOLEAN WriteToDevice)
{
PDEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION Stack;
DPRINT("ScsiClassSendSrbAsynchronous() called\n");
DeviceExtension = DeviceObject->DeviceExtension;
/* Initialize the SRB */
Srb->Length = SCSI_REQUEST_BLOCK_SIZE;
Srb->PathId = DeviceExtension->PathId;
Srb->TargetId = DeviceExtension->TargetId;
Srb->Lun = DeviceExtension->Lun;
Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
Srb->Cdb[1] |= DeviceExtension->Lun << 5;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?