disk.c

来自「winNT技术操作系统,国外开放的原代码和LIUX一样」· C语言 代码 · 共 2,016 行 · 第 1/5 页

C
2,016
字号
	      PartitionDeviceObject->Flags = DiskDeviceObject->Flags;
	      PartitionDeviceObject->Characteristics = DiskDeviceObject->Characteristics;
	      PartitionDeviceObject->StackSize = DiskDeviceObject->StackSize;
	      PartitionDeviceObject->AlignmentRequirement = DiskDeviceObject->AlignmentRequirement;

	      PartitionDeviceExtension = PartitionDeviceObject->DeviceExtension;
	      PartitionDeviceExtension->SenseData = DiskDeviceExtension->SenseData;
	      PartitionDeviceExtension->LockCount = 0;
	      PartitionDeviceExtension->DeviceNumber = DiskNumber;
	      PartitionDeviceExtension->DeviceObject = PartitionDeviceObject;
	      PartitionDeviceExtension->PortDeviceObject = PortDeviceObject;
	      PartitionDeviceExtension->DiskGeometry = DiskDeviceExtension->DiskGeometry;
	      PartitionDeviceExtension->PhysicalDevice = DiskDeviceExtension->PhysicalDevice;
	      PartitionDeviceExtension->PortCapabilities = Capabilities;
	      PartitionDeviceExtension->StartingOffset.QuadPart =
		PartitionEntry->StartingOffset.QuadPart;
	      PartitionDeviceExtension->PartitionLength.QuadPart =
		PartitionEntry->PartitionLength.QuadPart;
	      PartitionDeviceExtension->DMSkew = DiskDeviceExtension->DMSkew;
	      PartitionDeviceExtension->DMByteSkew = DiskDeviceExtension->DMByteSkew;
	      PartitionDeviceExtension->DMActive = DiskDeviceExtension->DMActive;
	      PartitionDeviceExtension->PortNumber = (UCHAR)PortNumber;
	      PartitionDeviceExtension->PathId = InquiryData->PathId;
	      PartitionDeviceExtension->TargetId = InquiryData->TargetId;
	      PartitionDeviceExtension->Lun = InquiryData->Lun;
	      PartitionDeviceExtension->SectorShift = DiskDeviceExtension->SectorShift;
	      PartitionDeviceExtension->TimeOutValue = SCSI_DISK_TIMEOUT;

	      /* Initialize lookaside list for SRBs */
	      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;

	      /* Tell mount manager that we have a new partition for him. This should be replaced
	       * by the registration of MOUNTDEV_MOUNTED_DEVICE_GUID interface on partition PDO.
	       */
	      {
	        UNICODE_STRING MountManagerU = RTL_CONSTANT_STRING(MOUNTMGR_DEVICE_NAME);
	        IO_STATUS_BLOCK IoStatusBlock;
	        ULONG Length = strlen(NameBuffer2) * sizeof(WCHAR);
	        PMOUNTMGR_TARGET_NAME TargetName;
	        HANDLE hMountManager;
	        InitializeObjectAttributes(
	          &ObjectAttributes,
	          &MountManagerU,
	          0,
	          NULL,
	          NULL);
	        Status = NtOpenFile(&hMountManager, FILE_READ_ACCESS, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN);
	        if (!NT_SUCCESS(Status))
	          {
	            DPRINT("NtOpenFile(%wZ) failed with status 0x%08lx\n", &MountManagerU, Status);
	          }
	        else
	          {
	            TargetName = ExAllocatePool(PagedPool, FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) + Length + sizeof(UNICODE_NULL));
	            if (!TargetName)
	              {
	                DPRINT("ExAllocatePool() failed\n");
	              }
	            else
	              {
	                TargetName->DeviceNameLength = Length;
	                swprintf(
	                  TargetName->DeviceName,
	                  L"\\Device\\Harddisk%lu\\Partition%lu",
	                  DiskNumber,
	                  PartitionNumber + 1);
	                Status = NtDeviceIoControlFile(
	                  hMountManager,
	                  NULL,
	                  NULL,
	                  NULL,
	                  &IoStatusBlock,
	                  IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION,
	                  TargetName, FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) + Length,
	                  NULL, 0);
	                if (NT_SUCCESS(Status))
	                  Status = NtWaitForSingleObject(hMountManager, FALSE, NULL);
	                if (!NT_SUCCESS(Status))
	                  {
	                    DPRINT("NtDeviceIoControlFile() failed with status 0x%08lx\n", Status);
	                  }
	                ExFreePool(TargetName);
	              }
	            NtClose(hMountManager);
	          }
	      }
	    }
	  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,

⌨️ 快捷键说明

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