disk.c

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

C
2,090
字号
	if (DeviceExtension->PartitionLength.QuadPart == 0)
            return(STATUS_SUCCESS);
    }

  if (EndingOffset.QuadPart > DeviceExtension->PartitionLength.QuadPart)
    {
      Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
      return(STATUS_INVALID_PARAMETER);
    }

  return(STATUS_SUCCESS);
}


/**********************************************************************
 * NAME							INTERNAL
 *	DiskClassCreateDeviceObject
 *
 * DESCRIPTION
 *	Create the raw device and any partition devices on this drive
 *
 * RUN LEVEL
 *	PASSIVE_LEVEL
 *
 * ARGUMENTS
 *	DriverObject
 *		The system created driver object
 *	RegistryPath
 *	PortDeviceObject
 *	PortNumber
 *	DiskNumber
 *	Capabilities
 *	InquiryData
 *	InitialzationData
 *
 * RETURN VALUE
 *	STATUS_SUCCESS: Device objects for disk and partitions were created.
 *	Others: Failure.
 */

static NTSTATUS
DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
			    IN PUNICODE_STRING RegistryPath,
			    IN PDEVICE_OBJECT PortDeviceObject,
			    IN ULONG PortNumber,
			    IN ULONG DiskNumber,
			    IN PIO_SCSI_CAPABILITIES Capabilities,
			    IN PSCSI_INQUIRY_DATA InquiryData,
			    IN PCLASS_INIT_DATA InitializationData)
{
  OBJECT_ATTRIBUTES ObjectAttributes;
  UNICODE_STRING UnicodeDeviceDirName;
  WCHAR NameBuffer[80];
  CHAR NameBuffer2[80];
  PDEVICE_OBJECT DiskDeviceObject;
  PDEVICE_OBJECT PartitionDeviceObject;
  PDEVICE_EXTENSION DiskDeviceExtension; /* defined in class2.h */
  PDEVICE_EXTENSION PartitionDeviceExtension; /* defined in class2.h */
  PDRIVE_LAYOUT_INFORMATION PartitionList = NULL;
  HANDLE Handle;
  PPARTITION_INFORMATION PartitionEntry;
  PDISK_DATA DiskData;
  ULONG PartitionNumber;
  PVOID MbrBuffer;
  NTSTATUS Status;

  DPRINT("DiskClassCreateDeviceObject() called\n");

  /* Create the harddisk device directory */
  swprintf(NameBuffer,
	   L"\\Device\\Harddisk%lu",
	   DiskNumber);
  RtlInitUnicodeString(&UnicodeDeviceDirName,
		       NameBuffer);
  InitializeObjectAttributes(&ObjectAttributes,
			     &UnicodeDeviceDirName,
			     0,
			     NULL,
			     NULL);
  Status = ZwCreateDirectoryObject(&Handle,
				   0,
				   &ObjectAttributes);
  if (!NT_SUCCESS(Status))
    {
      DPRINT("Could not create device dir object\n");
      return(Status);
    }

  /* Claim the disk device */
  Status = ScsiClassClaimDevice(PortDeviceObject,
				InquiryData,
				FALSE,
				&PortDeviceObject);
  if (!NT_SUCCESS(Status))
    {
      DPRINT("Could not claim disk device\n");

      ZwMakeTemporaryObject(Handle);
      ZwClose(Handle);

      return(Status);
    }

  /* Create disk device (Partition 0) */
  sprintf(NameBuffer2,
	  "\\Device\\Harddisk%lu\\Partition0",
	  DiskNumber);

  Status = ScsiClassCreateDeviceObject(DriverObject,
				       NameBuffer2,
				       NULL,
				       &DiskDeviceObject,
				       InitializationData);
  if (!NT_SUCCESS(Status))
    {
      DPRINT("ScsiClassCreateDeviceObject() failed (Status %x)\n", Status);

      /* Release (unclaim) the disk */
      ScsiClassClaimDevice(PortDeviceObject,
			   InquiryData,
			   TRUE,
			   NULL);

      /* Delete the harddisk device directory */
      ZwMakeTemporaryObject(Handle);
      ZwClose(Handle);

      return(Status);
    }

  DiskDeviceObject->Flags |= DO_DIRECT_IO;
  if (((PINQUIRYDATA)InquiryData->InquiryData)->RemovableMedia)
    {
      DiskDeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;
    }
  DiskDeviceObject->StackSize = (CCHAR)PortDeviceObject->StackSize + 1;

  if (PortDeviceObject->AlignmentRequirement > DiskDeviceObject->AlignmentRequirement)
    {
      DiskDeviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement;
    }

  DiskDeviceExtension = DiskDeviceObject->DeviceExtension;
  DiskDeviceExtension->LockCount = 0;
  DiskDeviceExtension->DeviceNumber = DiskNumber;
  DiskDeviceExtension->DeviceObject = DiskDeviceObject;
  DiskDeviceExtension->PortDeviceObject = PortDeviceObject;
  DiskDeviceExtension->PhysicalDevice = DiskDeviceObject;
  DiskDeviceExtension->PortCapabilities = Capabilities;
  DiskDeviceExtension->StartingOffset.QuadPart = 0;
  DiskDeviceExtension->PortNumber = (UCHAR)PortNumber;
  DiskDeviceExtension->PathId = InquiryData->PathId;
  DiskDeviceExtension->TargetId = InquiryData->TargetId;
  DiskDeviceExtension->Lun = InquiryData->Lun;
  DiskDeviceExtension->SrbFlags = 0;

  /* Enable the command queueing, if it possible */
  if (Capabilities->TaggedQueuing &&
      ((PINQUIRYDATA)InquiryData->InquiryData)->CommandQueue)
    {
      DiskDeviceExtension->SrbFlags |= SRB_FLAGS_QUEUE_ACTION_ENABLE;
    }

  /* Get timeout value */
  DiskDeviceExtension->TimeOutValue =
    ScsiClassQueryTimeOutRegistryValue(RegistryPath);
  if (DiskDeviceExtension->TimeOutValue == 0)
    DiskDeviceExtension->TimeOutValue = SCSI_DISK_TIMEOUT;

  /* Initialize the lookaside list for SRBs */
  ScsiClassInitializeSrbLookasideList(DiskDeviceExtension,
				      4);

  /* zero-out disk data */
  DiskData = (PDISK_DATA)(DiskDeviceExtension + 1);
  RtlZeroMemory(DiskData,
		sizeof(DISK_DATA));

  /* Get disk geometry */
  DiskDeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool,
						     sizeof(DISK_GEOMETRY));
  if (DiskDeviceExtension->DiskGeometry == NULL)
    {
      DPRINT("Failed to allocate geometry buffer!\n");

      ExDeleteNPagedLookasideList(&DiskDeviceExtension->SrbLookasideListHead);

      IoDeleteDevice(DiskDeviceObject);

      /* Release (unclaim) the disk */
      ScsiClassClaimDevice(PortDeviceObject,
			   InquiryData,
			   TRUE,
			   NULL);

      /* Delete the harddisk device directory */
      ZwMakeTemporaryObject(Handle);
      ZwClose(Handle);

      return(STATUS_INSUFFICIENT_RESOURCES);
    }

  /* Allocate sense data buffer */
  DiskDeviceExtension->SenseData = ExAllocatePool(NonPagedPoolCacheAligned,
						  SENSE_BUFFER_SIZE);
  if (DiskDeviceExtension->SenseData == NULL)
    {
      DPRINT("Failed to allocate sense data buffer!\n");

      ExFreePool (DiskDeviceExtension->DiskGeometry);

      ExDeleteNPagedLookasideList(&DiskDeviceExtension->SrbLookasideListHead);

      IoDeleteDevice(DiskDeviceObject);

      /* Release (unclaim) the disk */
      ScsiClassClaimDevice(PortDeviceObject,
			   InquiryData,
			   TRUE,
			   NULL);

      /* Delete the harddisk device directory */
      ZwMakeTemporaryObject(Handle);
      ZwClose(Handle);

      return(STATUS_INSUFFICIENT_RESOURCES);
    }

  /* Read the drive's capacity */
  Status = ScsiClassReadDriveCapacity(DiskDeviceObject);
  if (!NT_SUCCESS(Status) &&
      (DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) == 0)
    {
      DPRINT("Failed to retrieve drive capacity!\n");
      return(STATUS_SUCCESS);
    }
  else
    {
      /* Clear the verify flag for removable media drives. */
      DiskDeviceObject->Flags &= ~DO_VERIFY_VOLUME;
    }

  DPRINT("SectorSize: %lu\n", DiskDeviceExtension->DiskGeometry->BytesPerSector);

  if ((DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) &&
      (DiskDeviceExtension->DiskGeometry->MediaType == RemovableMedia))
    {
      DiskClassCreateMediaChangeEvent(DiskDeviceExtension,DiskNumber);
      if (DiskDeviceExtension->MediaChangeEvent != NULL)
	{
	  DPRINT("Allocated media change event!\n");
	}
    }

  /* Check disk for presence of a disk manager */
  HalExamineMBR(DiskDeviceObject,
		DiskDeviceExtension->DiskGeometry->BytesPerSector,
		0x54,
		&MbrBuffer);
  if (MbrBuffer != NULL)
    {
      /* Start disk at sector 63 if the Ontrack Disk Manager was found */
      DPRINT("Found 'Ontrack Disk Manager'!\n");

      DiskDeviceExtension->DMSkew = 63;
      DiskDeviceExtension->DMByteSkew =
	63 * DiskDeviceExtension->DiskGeometry->BytesPerSector;
      DiskDeviceExtension->DMActive = TRUE;

      ExFreePool(MbrBuffer);
      MbrBuffer = NULL;
    }

  if ((DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) &&
      (DiskDeviceExtension->DiskGeometry->MediaType == RemovableMedia))
    {
      /* Allocate a partition list for a single entry. */
      PartitionList = ExAllocatePool(NonPagedPool,
				     sizeof(DRIVE_LAYOUT_INFORMATION));
      if (PartitionList != NULL)
	{
	  RtlZeroMemory(PartitionList,
			sizeof(DRIVE_LAYOUT_INFORMATION));
	  PartitionList->PartitionCount = 1;

	  DiskData->DriveNotReady = TRUE;
	  Status = STATUS_SUCCESS;
	}
    }
  else
    {
      /* Read partition table */
      Status = IoReadPartitionTable(DiskDeviceObject,
				    DiskDeviceExtension->DiskGeometry->BytesPerSector,
				    TRUE,
				    &PartitionList);

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

      if ((!NT_SUCCESS(Status) || PartitionList->PartitionCount == 0) &&
	  DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
	{
	  if (!NT_SUCCESS(Status))
	    {
	      /* Drive is not ready. */
	      DPRINT("Drive not ready\n");
	      DiskData->DriveNotReady = TRUE;
	    }
	  else
	    {
	      ExFreePool(PartitionList);
	    }

	  /* Allocate a partition list for a single entry. */
	  PartitionList = ExAllocatePool(NonPagedPool,
					 sizeof(DRIVE_LAYOUT_INFORMATION));
	  if (PartitionList != NULL)
	    {
	      RtlZeroMemory(PartitionList,
			    sizeof(DRIVE_LAYOUT_INFORMATION));
	      PartitionList->PartitionCount = 1;

	      Status = STATUS_SUCCESS;
	    }
	}
    }

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

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

      /* Calculate MBR checksum if disk got no signature */
      if (DiskData->Signature == 0)
	{
	  if (!ScsiDiskCalcMbrCheckSum(DiskDeviceExtension,
				       &DiskData->MbrCheckSum))
	    {
	      DPRINT("MBR checksum calculation failed for disk %lu\n",
		     DiskDeviceExtension->DeviceNumber);
	    }
	  else
	    {
	      DPRINT("MBR checksum for disk %lu is %lx\n",
		     DiskDeviceExtension->DeviceNumber,
		     DiskData->MbrCheckSum);
	    }
	}
      else
	{
	  DPRINT("Signature on disk %lu is %lx\n",
		 DiskDeviceExtension->DeviceNumber,
		 DiskData->Signature);
	}

      /* Update disk geometry if disk is visible to the BIOS */
      ScsiDiskUpdateFixedDiskGeometry(DiskDeviceExtension);

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

	  DPRINT("Partition %02ld: nr: %d boot: %1x type: %x offset: %I64d size: %I64d\n",
		 PartitionNumber,
		 PartitionEntry->PartitionNumber,
		 PartitionEntry->BootIndicator,
		 PartitionEntry->PartitionType,
		 PartitionEntry->StartingOffset.QuadPart /
		   DiskDeviceExtension->DiskGeometry->BytesPerSector,
		 PartitionEntry->PartitionLength.QuadPart /
		   DiskDeviceExtension->DiskGeometry->BytesPerSector);

	  /* Create partition device object */
	  sprintf(NameBuffer2,
		  "\\Device\\Harddisk%lu\\Partition%lu",
		  DiskNumber,
		  PartitionNumber + 1);

	  Status = ScsiClassCreateDeviceObject(DriverObject,
					       NameBuffer2,
					       DiskDeviceObject,
					       &PartitionDeviceObject ,
					       InitializationData);
	  DPRINT("ScsiClassCreateDeviceObject(): Status %x\n", Status);
	  if (NT_SUCCESS(Status))
	    {
	      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 */

⌨️ 快捷键说明

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