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 + -
显示快捷键?