disk.c

来自「一个类似windows」· C语言 代码 · 共 2,090 行 · 第 1/5 页

C
2,090
字号
	      ScsiClassInitializeSrbLookasideList(PartitionDeviceExtension,
						  8);

	      /* Link current partition device extension to previous disk data */
	      DiskData->NextPartition = PartitionDeviceExtension;

	      /* Initialize current disk data */
	      DiskData = (PDISK_DATA)(PartitionDeviceExtension + 1);
	      DiskData->NextPartition = NULL;
	      DiskData->PartitionType = PartitionEntry->PartitionType;
	      DiskData->PartitionNumber = PartitionNumber + 1;
	      DiskData->PartitionOrdinal = PartitionNumber + 1;
	      DiskData->HiddenSectors = PartitionEntry->HiddenSectors;
	      DiskData->BootIndicator = PartitionEntry->BootIndicator;
	      DiskData->DriveNotReady = FALSE;
	    }
	  else
	    {
	      DPRINT("ScsiClassCreateDeviceObject() failed to create partition device object (Status %x)\n", Status);

	      break;
	    }
	}
    }

  if (PartitionList != NULL)
    ExFreePool(PartitionList);

  DPRINT("DiskClassCreateDeviceObjects() done\n");

  return(STATUS_SUCCESS);
}


static NTSTATUS
DiskBuildPartitionTable(IN PDEVICE_OBJECT DiskDeviceObject,
                        IN PIRP Irp)
{
  PDRIVE_LAYOUT_INFORMATION PartitionList = NULL;
  PDEVICE_EXTENSION DiskDeviceExtension, DDE;
  PDISK_DATA DiskData, DD;
  PPARTITION_INFORMATION PartitionEntry;
  ULONG PartitionNumber;
  NTSTATUS Status;

  DPRINT("DiskBuildPartitionTable() start\n");

  DiskDeviceExtension = (PDEVICE_EXTENSION)DiskDeviceObject->DeviceExtension;
  DiskData = (PDISK_DATA)(DiskDeviceExtension + 1);

  DDE = (PDEVICE_EXTENSION) DiskDeviceExtension->PhysicalDevice->DeviceExtension;
  DD = (PDISK_DATA)(DDE +1);

  /* Clear flag for Partition0, just incase it was set. */
  DD->DriveNotReady = FALSE;

  Status = ScsiClassReadDriveCapacity(DiskDeviceObject);
  if (!NT_SUCCESS(Status))
    {
      /* Drive is not ready. */
      DPRINT("Drive not ready\n");
      DiskData->DriveNotReady = TRUE;
      return Status;
    }

  /* Read partition table */
  Status = IoReadPartitionTable(DiskDeviceExtension->PhysicalDevice,
				DiskDeviceExtension->DiskGeometry->BytesPerSector,
				TRUE,
				&PartitionList);

  DPRINT("IoReadPartitionTable(): Status: %lx\n", Status);

  if (!NT_SUCCESS(Status))
    {
      /* Drive is not ready. */
      DPRINT("Drive not ready\n");
      DiskData->DriveNotReady = TRUE;
      if (PartitionList != NULL)
	ExFreePool(PartitionList);
      return Status;
    }

  if (NT_SUCCESS(Status))
    {
      DPRINT("Read partition table!\n");
      DPRINT("  Number of partitions: %u\n", PartitionList->PartitionCount);

      /* Set disk signature */
      DiskData->Signature = PartitionList->Signature;

      DiskData->NextPartition = NULL;

      if (PartitionList->PartitionCount)
        {
	  for (PartitionNumber = 0; PartitionNumber < PartitionList->PartitionCount; PartitionNumber++)
	    {
	      PartitionEntry = &PartitionList->PartitionEntry[PartitionNumber];

	      DiskData->PartitionType = PartitionEntry->PartitionType;
	      DiskData->PartitionNumber = PartitionNumber + 1;
	      DiskData->PartitionOrdinal = PartitionNumber + 1;
	      DiskData->HiddenSectors = PartitionEntry->HiddenSectors;
	      DiskData->BootIndicator = PartitionEntry->BootIndicator;
	      DiskData->DriveNotReady = FALSE;
	      DiskDeviceExtension->StartingOffset = PartitionEntry->StartingOffset;
	      DiskDeviceExtension->PartitionLength = PartitionEntry->PartitionLength;

	      DPRINT1("Partition %02ld: nr: %d boot: %1x type: %x offset: %I64d size: %I64d\n",
		      PartitionNumber,
		      DiskData->PartitionNumber,
		      DiskData->BootIndicator,
		      DiskData->PartitionType,
		      DiskDeviceExtension->StartingOffset.QuadPart /
			DiskDeviceExtension->DiskGeometry->BytesPerSector,
		      DiskDeviceExtension->PartitionLength.QuadPart /
			DiskDeviceExtension->DiskGeometry->BytesPerSector);
	    }
	}
      else
	{
	  DiskData->PartitionType = 0;
	  DiskData->PartitionNumber = 1;
	  DiskData->PartitionOrdinal = 0;
	  DiskData->HiddenSectors = 0;
	  DiskData->BootIndicator = 0;
	  DiskData->DriveNotReady = FALSE;
	  DiskDeviceExtension->StartingOffset.QuadPart = 0;
	  DiskDeviceExtension->PartitionLength.QuadPart += DiskDeviceExtension->StartingOffset.QuadPart;
	}
    }

  DPRINT("DiskBuildPartitionTable() done\n");
  if (PartitionList != NULL)
       ExFreePool(PartitionList);
  return(STATUS_SUCCESS);
}


/**********************************************************************
 * NAME							EXPORTED
 *	DiskClassDeviceControl
 *
 * DESCRIPTION
 *	Answer requests for device control calls
 *
 * RUN LEVEL
 *	PASSIVE_LEVEL
 *
 * ARGUMENTS
 *	Standard dispatch arguments
 *
 * RETURNS
 *	Status
 */

NTSTATUS STDCALL
DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
		       IN PIRP Irp)
{
  PDEVICE_EXTENSION DeviceExtension;
  PIO_STACK_LOCATION IrpStack;
  ULONG ControlCode, InputLength, OutputLength;
  PDISK_DATA DiskData;
  ULONG Information;
  NTSTATUS Status;
  KEVENT Event;
  IO_STATUS_BLOCK IoSB;
  PIRP LocalIrp;
  PSRB_IO_CONTROL SrbIoControl;
  PSENDCMDINPARAMS InParams;

  DPRINT("DiskClassDeviceControl() called!\n");

  Status = STATUS_INVALID_DEVICE_REQUEST;
  Information = 0;
  IrpStack = IoGetCurrentIrpStackLocation(Irp);
  ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
  InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
  DiskData = (PDISK_DATA)(DeviceExtension + 1);

  switch (ControlCode)
    {
      case IOCTL_DISK_GET_DRIVE_GEOMETRY:
	DPRINT("IOCTL_DISK_GET_DRIVE_GEOMETRY\n");
	if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY))
	  {
	    Status = STATUS_INVALID_PARAMETER;
	    break;
	  }

	if (DeviceExtension->DiskGeometry == NULL)
	  {
	    DPRINT("No disk geometry available!\n");
	    DeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool,
							   sizeof(DISK_GEOMETRY));
	  }

	if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
	  {
	    Status = ScsiClassReadDriveCapacity(DeviceObject);
	    DPRINT("ScsiClassReadDriveCapacity() returned (Status %lx)\n", Status);
	    if (!NT_SUCCESS(Status))
	      {
		/* Drive is not ready */
		DiskData->DriveNotReady = TRUE;
		break;
	      }

	    /* Drive is ready */
	    DiskData->DriveNotReady = FALSE;
	  }

	RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
		      DeviceExtension->DiskGeometry,
		      sizeof(DISK_GEOMETRY));

	Status = STATUS_SUCCESS;
	Information = sizeof(DISK_GEOMETRY);
	break;

      case IOCTL_DISK_GET_PARTITION_INFO:
	DPRINT("IOCTL_DISK_GET_PARTITION_INFO\n");

	if ((DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) &&
	(DeviceExtension->DiskGeometry->MediaType == RemovableMedia))
	{
		/* Update a partition list for a single entry. */
		Status = DiskBuildPartitionTable(DeviceObject,Irp);
	}

	if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
	    sizeof(PARTITION_INFORMATION))
	  {
	    Status = STATUS_INFO_LENGTH_MISMATCH;
	  }
	else if (DiskData->PartitionNumber == 0)
	  {
	    Status = STATUS_INVALID_DEVICE_REQUEST;
	  }
	else
	{
	    PPARTITION_INFORMATION PartitionInfo;

	    PartitionInfo = (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;

	    PartitionInfo->PartitionType = DiskData->PartitionType;
	    PartitionInfo->StartingOffset = DeviceExtension->StartingOffset;
	    PartitionInfo->PartitionLength = DeviceExtension->PartitionLength;
	    PartitionInfo->HiddenSectors = DiskData->HiddenSectors;
	    PartitionInfo->PartitionNumber = DiskData->PartitionNumber;
	    PartitionInfo->BootIndicator = DiskData->BootIndicator;
	    PartitionInfo->RewritePartition = FALSE;
	    PartitionInfo->RecognizedPartition =
	      IsRecognizedPartition(DiskData->PartitionType);

	    Status = STATUS_SUCCESS;
	    Information = sizeof(PARTITION_INFORMATION);
	  }
	break;

      case IOCTL_DISK_SET_PARTITION_INFO:
	if (IrpStack->Parameters.DeviceIoControl.InputBufferLength <
	    sizeof(SET_PARTITION_INFORMATION))
	  {
	    Status = STATUS_INFO_LENGTH_MISMATCH;
	  }
	else if (DiskData->PartitionNumber == 0)
	  {
	    Status = STATUS_INVALID_DEVICE_REQUEST;
	  }
	else
	  {
	    PSET_PARTITION_INFORMATION PartitionInfo;

	    PartitionInfo = (PSET_PARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;

	    Status = IoSetPartitionInformation(DeviceExtension->PhysicalDevice,
					       DeviceExtension->DiskGeometry->BytesPerSector,
					       DiskData->PartitionOrdinal,
					       PartitionInfo->PartitionType);
	    if (NT_SUCCESS(Status))
	      {
		DiskData->PartitionType = PartitionInfo->PartitionType;
	      }
	  }
	break;

      case IOCTL_DISK_GET_DRIVE_LAYOUT:
	if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
	    sizeof(DRIVE_LAYOUT_INFORMATION))
	  {
	    Status = STATUS_BUFFER_TOO_SMALL;
	  }
	else
	  {
	    PDRIVE_LAYOUT_INFORMATION PartitionList;

	    Status = IoReadPartitionTable(DeviceExtension->PhysicalDevice,
					  DeviceExtension->DiskGeometry->BytesPerSector,
					  FALSE,
					  &PartitionList);
	    if (NT_SUCCESS(Status))
	      {
		ULONG BufferSize;

		BufferSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION,
					  PartitionEntry[0]);
		BufferSize += PartitionList->PartitionCount * sizeof(PARTITION_INFORMATION);

		if (BufferSize > IrpStack->Parameters.DeviceIoControl.OutputBufferLength)
		  {
		    Status = STATUS_BUFFER_TOO_SMALL;
		  }
		else
		  {
		    RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
				  PartitionList,
				  BufferSize);
		    Status = STATUS_SUCCESS;
		    Information = BufferSize;
		  }
		ExFreePool(PartitionList);
	      }
	  }
	break;

      case IOCTL_DISK_SET_DRIVE_LAYOUT:
	if (IrpStack->Parameters.DeviceIoControl.InputBufferLength <
	    sizeof(DRIVE_LAYOUT_INFORMATION))
	  {
	    Status = STATUS_INFO_LENGTH_MISMATCH;
	  }
	else if (DeviceExtension->PhysicalDevice->DeviceExtension != DeviceExtension)
	  {
	    Status = STATUS_INVALID_PARAMETER;
	  }
	else
	  {
	    PDRIVE_LAYOUT_INFORMATION PartitionList;
	    ULONG TableSize;

	    PartitionList = Irp->AssociatedIrp.SystemBuffer;
	    TableSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
			((PartitionList->PartitionCount - 1) * sizeof(PARTITION_INFORMATION));

	    if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < TableSize)
	      {
		Status = STATUS_BUFFER_TOO_SMALL;
	      }
	    else
	      {
		/* Update partition device objects */
		DiskClassUpdatePartitionDeviceObjects (DeviceObject,
						       Irp);

		/* Write partition table */
		Status = IoWritePartitionTable(DeviceExtension->PhysicalDevice,
					       DeviceExtension->DiskGeometry->BytesPerSector,
					       DeviceExtension->DiskGeometry->SectorsPerTrack,
					       DeviceExtension->DiskGeometry->TracksPerCylinder,
					       PartitionList);
	      }
	  }
	break;

      case IOCTL_DISK_IS_WRITABLE:
	{
	  PMODE_PARAMETER_HEADER ModeData;
	  ULONG Length;

	  ModeData = ExAllocatePool (NonPagedPool,
				     MODE_DATA_SIZE);
	  if (ModeData == NULL)
	    {
	      Status = STATUS_INSUFFICIENT_RESOURCES;
	      break;
	    }
	  RtlZeroMemory (ModeData,
			 MODE_DATA_SIZE);

	  Length = ScsiClassModeSense (DeviceObject,
				       (PVOID)ModeData,
				       MODE_DATA_SIZE,
				       MODE_SENSE_RETURN_ALL);
	  if (Length < sizeof(MODE_PARAMETER_HEADER))
	    {
	      /* FIXME: Retry */
	      Status = STATUS_IO_DEVICE_ERROR;
	      ExFreePool (ModeData);
	      break;
	    }

	  if (ModeData->DeviceSpecificParameter & MODE_DSP_WRITE_PROTECT)
	    {
	      Status = STATUS_MEDIA_WRITE_PROTECTED;
	    }
	  else
	    {
	      Status = STATUS_SUCCESS;
	    }
	  ExFreePool (ModeData);
	}
	break;

      case IOCTL_DISK_VERIFY:
      case IOCTL_DISK_FORMAT_TRACKS:
      case IOCTL_DISK_PERFORMANCE:
      case IOCTL_DISK_LOGGING:
      case IOCTL_DISK_FORMAT_TRACKS_EX:
      case IOCTL_DISK_HISTOGRAM_STRUCTURE:
      case IOCTL_DISK_HISTOGRAM_DATA:
      case IOCTL_DISK_HISTOGRAM_RESET:
      case IOCTL_DISK_REQUEST_STRUCTURE:
      case IOCTL_DISK_REQUEST_DATA:
	/* If we get here, something went wrong. Inform the requestor */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?