disk.c

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

C
2,016
字号
#if 0            	
              CHAR Buffer[256];
              ULONG i, j;
              UCHAR sum = 0;
              memset(Buffer, 0, sizeof(Buffer));
              for (i = 0; i < 512; i += 16)
              {
                 for (j = 0; j < 16 && i + j < 512; j++)
                   {
                     sprintf(&Buffer[3*j], "%02x ", ((PSENDCMDOUTPARAMS)(SrbIoControl + 1))->bBuffer[i + j]);
                     sum += ((PSENDCMDOUTPARAMS)(SrbIoControl + 1))->bBuffer[i + j];
                   }
                 for (j = 0; j < 16 && i + j < 512; j++)
                   {
                       sprintf(&Buffer[3*16 + j], "%c", isprint(((PSENDCMDOUTPARAMS)(SrbIoControl + 1))->bBuffer[i + j]) ? ((PSENDCMDOUTPARAMS)(SrbIoControl + 1))->bBuffer[i + j] : '.');
                   }
                 DPRINT1("%04x %s\n", i, Buffer);
              }
              DPRINT1("Sum %02x\n", sum);
#endif              
              Information = SrbIoControl->Length;
             
            }
          else
            {
              Information = sizeof(SENDCMDOUTPARAMS) -1;
            }
          memcpy(Irp->AssociatedIrp.SystemBuffer, InParams, Information);
          ExFreePool(SrbIoControl);
          break;
        }

      case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:
        {
          WCHAR NameBuffer[80];
          PMOUNTDEV_NAME pMountDevName;
          ULONG NameLength;
          DPRINT("IOCTL_MOUNTDEV_QUERY_DEVICE_NAME\n");
          if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTDEV_NAME))
            {
              Status = STATUS_BUFFER_TOO_SMALL;
              Information = 0;
            }
          else
            {
              pMountDevName = (PMOUNTDEV_NAME)Irp->AssociatedIrp.SystemBuffer;
              swprintf(NameBuffer,
                L"\\Device\\Harddisk%lu\\Partition%lu",
                DeviceExtension->DeviceNumber,
                ((PDISK_DATA)(DeviceExtension + 1))->PartitionNumber);
              NameLength = wcslen(NameBuffer) * sizeof(WCHAR);
              pMountDevName->NameLength = NameLength;
              if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < FIELD_OFFSET(MOUNTDEV_NAME, Name) + NameLength)
                {
                  Information = sizeof(MOUNTDEV_NAME);
                  Status = STATUS_BUFFER_OVERFLOW;
                }
              else
                {
                  RtlCopyMemory(pMountDevName->Name, NameBuffer, NameLength);
                  Information = FIELD_OFFSET(MOUNTDEV_NAME, Name) + NameLength;
                  Status = STATUS_SUCCESS;
                }
            }
          break;
        }

      case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID:
        {
          WCHAR NameBuffer[80];
          PMOUNTDEV_UNIQUE_ID pMountDevUniqueId;
          ULONG UniqueIdLength;
          DPRINT("IOCTL_MOUNTDEV_QUERY_UNIQUE_ID\n");
          if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(MOUNTDEV_NAME))
            {
              Status = STATUS_BUFFER_TOO_SMALL;
              Information = 0;
            }
          else
            {
              pMountDevUniqueId = (PMOUNTDEV_UNIQUE_ID)Irp->AssociatedIrp.SystemBuffer;
              swprintf(NameBuffer,
                L"\\Device\\Harddisk%lu\\Partition%lu",
                DeviceExtension->DeviceNumber,
                ((PDISK_DATA)(DeviceExtension + 1))->PartitionNumber);
              UniqueIdLength = wcslen(NameBuffer) * sizeof(WCHAR);
              pMountDevUniqueId->UniqueIdLength = UniqueIdLength;
              if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + UniqueIdLength)
                {
                  Information = sizeof(MOUNTDEV_UNIQUE_ID);
                  Status = STATUS_BUFFER_OVERFLOW;
                }
              else
                {
                  RtlCopyMemory(pMountDevUniqueId->UniqueId, NameBuffer, UniqueIdLength);
                  Information = FIELD_OFFSET(MOUNTDEV_UNIQUE_ID, UniqueId) + UniqueIdLength;
                  Status = STATUS_SUCCESS;
                }
            }
          break;
        }

      default:
	/* Call the common device control function */
	return(ScsiClassDeviceControl(DeviceObject, Irp));
    }

  /* Verify the device if the user caused the error */
  if (!NT_SUCCESS(Status) && IoIsErrorUserInduced(Status))
    {
      IoSetHardErrorOrVerifyDevice(Irp, DeviceObject);
    }

  Irp->IoStatus.Status = Status;
  Irp->IoStatus.Information = Information;
  IoCompleteRequest(Irp,
		    IO_NO_INCREMENT);

  return(Status);
}


/**********************************************************************
 * NAME							EXPORTED
 *	DiskClassShutdownFlush
 *
 * DESCRIPTION
 *	Answer requests for shutdown and flush calls.
 *
 * RUN LEVEL
 *	PASSIVE_LEVEL
 *
 * ARGUMENTS
 *	DeviceObject
 *		Pointer to the device.
 *
 *	Irp
 *		Pointer to the IRP
 *
 * RETURN VALUE
 *	Status
 */

NTSTATUS STDCALL
DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
		       IN PIRP Irp)
{
  PDEVICE_EXTENSION DeviceExtension;
  PIO_STACK_LOCATION IrpStack;
  PSCSI_REQUEST_BLOCK Srb;

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

  DeviceExtension = DeviceObject->DeviceExtension;

  /* Allocate SRB */
  Srb = ExAllocatePool(NonPagedPool,
		       sizeof(SCSI_REQUEST_BLOCK));
  if (Srb == NULL)
    {
      Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
      Irp->IoStatus.Information = 0;
      IoCompleteRequest(Irp, IO_NO_INCREMENT);

      return(STATUS_INSUFFICIENT_RESOURCES);
    }

  RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));


  /* Set timeout */
  Srb->TimeOutValue = DeviceExtension->TimeOutValue * 4;

  /* Flush write cache */
  Srb->CdbLength = 10;
  Srb->Cdb[0] = SCSIOP_SYNCHRONIZE_CACHE;
  ScsiClassSendSrbSynchronous(DeviceObject,
			      Srb,
			      NULL,
			      0,
			      TRUE);

  /* Get current stack location */
  IrpStack = IoGetCurrentIrpStackLocation(Irp);

  /* FIXME: Unlock removable media upon shutdown */


  /* No retry */
  IrpStack->Parameters.Others.Argument4 = (PVOID)0;

  /* Send shutdown or flush request to the port driver */
  Srb->CdbLength = 0;
  if (IrpStack->MajorFunction == IRP_MJ_SHUTDOWN)
    Srb->Function = SRB_FUNCTION_SHUTDOWN;
  else
    Srb->Function = SRB_FUNCTION_FLUSH;

  /* Init completion routine */
  IoSetCompletionRoutine(Irp,
			 ScsiClassIoComplete,
			 Srb,
			 TRUE,
			 TRUE,
			 TRUE);

  /* Prepare next stack location for a call to the port driver */
  IrpStack = IoGetNextIrpStackLocation(Irp);
  IrpStack->MajorFunction = IRP_MJ_SCSI;
  IrpStack->Parameters.Scsi.Srb = Srb;
  Srb->OriginalRequest = Irp;

  /* Call port driver */
  return(IoCallDriver(DeviceExtension->PortDeviceObject, Irp));
}


/**********************************************************************
 * NAME							INTERNAL
 *	DiskClassUpdatePartitionDeviceObjects
 *
 * DESCRIPTION
 *	Deletes, modifies or creates partition device objects.
 *
 * RUN LEVEL
 *	PASSIVE_LEVEL
 *
 * ARGUMENTS
 *	DeviceObject
 *		Pointer to the device.
 *
 *	Irp
 *		Pointer to the IRP
 *
 * RETURN VALUE
 *	None
 */

static VOID
DiskClassUpdatePartitionDeviceObjects(IN PDEVICE_OBJECT DiskDeviceObject,
				      IN PIRP Irp)
{
  PDRIVE_LAYOUT_INFORMATION PartitionList;
  PPARTITION_INFORMATION PartitionEntry;
  PDEVICE_EXTENSION DeviceExtension;
  PDEVICE_EXTENSION DiskDeviceExtension;
  PDISK_DATA DiskData;
  ULONG PartitionCount;
  ULONG PartitionOrdinal;
  ULONG PartitionNumber;
  ULONG LastPartitionNumber;
  ULONG i;
  BOOLEAN Found;
  WCHAR NameBuffer[MAX_PATH];
  UNICODE_STRING DeviceName;
  PDEVICE_OBJECT DeviceObject;
  NTSTATUS Status;

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

  /* Get partition list */
  PartitionList = Irp->AssociatedIrp.SystemBuffer;

  /* Round partition count up by 4 */
  PartitionCount = ((PartitionList->PartitionCount + 3) / 4) * 4;

  /* Remove the partition numbers from the partition list */
  for (i = 0; i < PartitionCount; i++)
    {
      PartitionList->PartitionEntry[i].PartitionNumber = 0;
    }

  DiskDeviceExtension = DiskDeviceObject->DeviceExtension;

  /* Traverse on-disk partition list */
  LastPartitionNumber = 0;
  DeviceExtension = DiskDeviceExtension;
  DiskData = (PDISK_DATA)(DeviceExtension + 1);
  while (TRUE)
    {
      DeviceExtension = DiskData->NextPartition;
      if (DeviceExtension == NULL)
	break;

      /* Get disk data */
      DiskData = (PDISK_DATA)(DeviceExtension + 1);

      /* Update last partition number */
      if (DiskData->PartitionNumber > LastPartitionNumber)
	LastPartitionNumber = DiskData->PartitionNumber;

      /* Ignore unused on-disk partitions */
      if (DeviceExtension->PartitionLength.QuadPart == 0ULL)
	continue;

      Found = FALSE;
      PartitionOrdinal = 0;
      for (i = 0; i < PartitionCount; i++)
	{
	  /* Get current partition entry */
	  PartitionEntry = &PartitionList->PartitionEntry[i];

	  /* Ignore empty (aka unused) or extended partitions */
	  if (PartitionEntry->PartitionType == PARTITION_ENTRY_UNUSED ||
	      IsContainerPartition (PartitionEntry->PartitionType))
	    continue;

	  PartitionOrdinal++;

	  /* Check for matching partition start offset and length */
	  if ((PartitionEntry->StartingOffset.QuadPart !=
	       DeviceExtension->StartingOffset.QuadPart) ||
	      (PartitionEntry->PartitionLength.QuadPart !=
	       DeviceExtension->PartitionLength.QuadPart))
	    continue;

	  DPRINT("Found matching partition entry for partition %lu\n",
		  DiskData->PartitionNumber);

	  /* Found matching partition */
	  Found = TRUE;

	  /* Update partition number in partition list */
	  PartitionEntry->PartitionNumber = DiskData->PartitionNumber;
	  break;
	}

      if (Found == TRUE)
	{
	  /* Get disk data for current partition */
	  DiskData = (PDISK_DATA)(DeviceExtension + 1);

	  /* Update partition type if partiton will be rewritten */
	  if (PartitionEntry->RewritePartition == TRUE)
	    DiskData->PartitionType = PartitionEntry->PartitionType;

	  /* Assign new partiton ordinal */
	  DiskData->PartitionOrdinal = PartitionOrdinal;

	  DPRINT("Partition ordinal %lu was assigned to partition %lu\n",
		 DiskData->PartitionOrdinal,
		 DiskData->PartitionNumber);
	}
      else
	{
	  /* Delete this partition */
	  DeviceExtension->PartitionLength.QuadPart = 0ULL;

	  DPRINT("Deleting partition %lu\n",
		 DiskData->PartitionNumber);
	}
    }

  /* Traverse partiton list and create new partiton devices */
  PartitionOrdinal = 0;
  for (i = 0; i < PartitionCount; i++)
    {
      /* Get current partition entry */
      PartitionEntry = &PartitionList->PartitionEntry[i];

      /* Ignore empty (aka unused) or extended partitions */
      if (PartitionEntry->PartitionType == PARTITION_ENTRY_UNUSED ||
	  IsContainerPartition (PartitionEntry->PartitionType))
	continue;

      PartitionOrdinal++;

      /* Ignore unchanged partition entries */
      if (PartitionEntry->RewritePartition == FALSE)
	continue;

      /* Check for an unused device object */
      PartitionNumber = 0;
      DeviceExtension = DiskDeviceExtension;
      DiskData = (PDISK_DATA)(DeviceExtension + 1);
      while (TRUE)
	{
	  DeviceExtension = DiskData->NextPartition;
	  if (DeviceExtension == NULL)
	    break;

	  /* Get partition disk data */
	  DiskData = (PDISK_DATA)(DeviceExtension + 1);

	  /* Found a free (unused) partition (device object) */
	  if (DeviceExtension->PartitionLength.QuadPart == 0ULL)
	    {
	      PartitionNumber = DiskData->PartitionNumber;
	      break;
	    }
	}

      if (PartitionNumber == 0)
	{
	  /* Create a new partition device object */
	  DPRINT("Create new partition device object\n");

	  /* Get new partiton number */
	  LastPartitionNumber++;
	  PartitionNumber = 

⌨️ 快捷键说明

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