disk.c

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

C
2,016
字号
				  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 */
	DPRINT("Unhandled control code: %lx\n", ControlCode);
	Status = STATUS_INVALID_DEVICE_REQUEST;
	Information = 0;
	break;

      case SMART_GET_VERSION:
        {
          PGETVERSIONINPARAMS Version;
          DPRINT("SMART_GET_VERSION\n");
          if (OutputLength < sizeof(GETVERSIONINPARAMS)) 
            {
              Status = STATUS_BUFFER_TOO_SMALL;
              Information = sizeof(GETVERSIONINPARAMS);
              break;
            }

          SrbIoControl = ExAllocatePool(NonPagedPool, sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS));
          if (SrbIoControl == NULL)
            {
	      Status = STATUS_INSUFFICIENT_RESOURCES;
              break;
            }
          Version = (PGETVERSIONINPARAMS)(SrbIoControl + 1);
          memset(SrbIoControl, 0, sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS));

          SrbIoControl->HeaderLength = sizeof(SRB_IO_CONTROL);
          memcpy(SrbIoControl->Signature, "ScsiDisk", 8);
          SrbIoControl->Timeout = DeviceExtension->TimeOutValue * 4;
          SrbIoControl->Length = sizeof(GETVERSIONINPARAMS);
          SrbIoControl->ControlCode = IOCTL_SCSI_MINIPORT_SMART_VERSION;

          KeInitializeEvent(&Event, NotificationEvent, FALSE);
          LocalIrp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT,
                                                   DeviceExtension->PortDeviceObject,
                                                   SrbIoControl,
                                                   sizeof(SRB_IO_CONTROL),
                                                   SrbIoControl,
                                                   sizeof(SRB_IO_CONTROL) + sizeof(GETVERSIONINPARAMS),
                                                   FALSE,
                                                   &Event,
                                                   &IoSB);
          if (LocalIrp == NULL)
            {
              ExFreePool(SrbIoControl);
	      Status = STATUS_INSUFFICIENT_RESOURCES;
              break;
            }

          Status = IoCallDriver(DeviceExtension->PortDeviceObject, LocalIrp);
          if (Status == STATUS_PENDING)
            {
              KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
              Status = IoSB.Status;
            }
          if (NT_SUCCESS(Status))
            {
              memcpy(Irp->AssociatedIrp.SystemBuffer, Version, sizeof(GETVERSIONINPARAMS));
              Information = sizeof(GETVERSIONINPARAMS);
            }
          ExFreePool(SrbIoControl);
          break;
        }

      case SMART_SEND_DRIVE_COMMAND: 
        {
          DPRINT("SMART_SEND_DRIVE_COMMAND\n");

          if (InputLength < sizeof(SENDCMDINPARAMS) - 1)
            {
	      Status = STATUS_INFO_LENGTH_MISMATCH;
              break;
            }

          InParams = (PSENDCMDINPARAMS)Irp->AssociatedIrp.SystemBuffer;
          if (InParams->irDriveRegs.bCommandReg == SMART_CMD)
            {
              if (InParams->irDriveRegs.bFeaturesReg == ENABLE_DISABLE_AUTOSAVE)
                {
                  DPRINT("IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE\n");
                  ControlCode = IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE;
                  Information = sizeof(SENDCMDOUTPARAMS) - 1;
                }
              else if (InParams->irDriveRegs.bFeaturesReg == SAVE_ATTRIBUTE_VALUES)
                {
                  DPRINT("IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES\n");
                  ControlCode = IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES;
                  Information = sizeof(SENDCMDOUTPARAMS) - 1;
                }
              else if (InParams->irDriveRegs.bFeaturesReg == EXECUTE_OFFLINE_DIAGS)
                {
                  DPRINT("IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS\n");
                  ControlCode = IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS;
                  Information = sizeof(SENDCMDOUTPARAMS) - 1;
                }
              else if (InParams->irDriveRegs.bFeaturesReg == SMART_WRITE_LOG)
                {
                  DPRINT("IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG\n");
                  ControlCode = IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG;
                  if (InputLength < sizeof(SENDCMDINPARAMS) - 1 + 512 * max(1, InParams->irDriveRegs.bSectorCountReg))
                    {
	              Status = STATUS_INFO_LENGTH_MISMATCH;
                      break;
                    }
                  Information = sizeof(SENDCMDOUTPARAMS) - 1;
                }
              else if (InParams->irDriveRegs.bFeaturesReg == ENABLE_SMART)
                {
                  DPRINT("IOCTL_SCSI_MINIPORT_ENABLE_SMART\n");
                  ControlCode = IOCTL_SCSI_MINIPORT_ENABLE_SMART;
                  Information = sizeof(SENDCMDOUTPARAMS) - 1;
                }
              else if (InParams->irDriveRegs.bFeaturesReg == DISABLE_SMART)
                {
                  DPRINT("IOCTL_SCSI_MINIPORT_DISABLE_SMART\n");
                  ControlCode = IOCTL_SCSI_MINIPORT_DISABLE_SMART;
                  Information = sizeof(SENDCMDOUTPARAMS) - 1;
                }
              else if (InParams->irDriveRegs.bFeaturesReg == RETURN_SMART_STATUS)
                {
                  DPRINT("IOCTL_SCSI_MINIPORT_RETURN_STATUS\n");
                  ControlCode = IOCTL_SCSI_MINIPORT_RETURN_STATUS;
                  Information = sizeof(SENDCMDOUTPARAMS) - 1 + sizeof(IDEREGS);
                }
              else if (InParams->irDriveRegs.bFeaturesReg == ENABLE_DISABLE_AUTO_OFFLINE)
                {
                  DPRINT("IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS\n");
                  ControlCode = IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS;
                  Information = sizeof(SENDCMDOUTPARAMS) - 1;
                }
              else
                {
                  DPRINT("%x\n", InParams->irDriveRegs.bFeaturesReg);
                  Status = STATUS_INVALID_PARAMETER;
                  break;
                }
            }
          else
            {
              Status = STATUS_INVALID_PARAMETER;
              break;
            }
          if (OutputLength < Information)
            {
              Status = STATUS_BUFFER_TOO_SMALL;
              break;
            }
          
          SrbIoControl = ExAllocatePool(NonPagedPool, sizeof(SRB_IO_CONTROL) + max(Information, sizeof(SENDCMDINPARAMS) - 1));
          if (SrbIoControl == NULL) 
            {
              Status =  STATUS_INSUFFICIENT_RESOURCES;
              Information = 0;
              break;
            }
          memset(SrbIoControl, 0, sizeof(SRB_IO_CONTROL) + max(Information, sizeof(SENDCMDINPARAMS) - 1));

          SrbIoControl->HeaderLength = sizeof(SRB_IO_CONTROL);
          memcpy(SrbIoControl->Signature, "SCSIDISK", 8);
          SrbIoControl->Timeout = DeviceExtension->TimeOutValue * 4;
          SrbIoControl->Length = Information;
          SrbIoControl->ControlCode = ControlCode;

          InParams = (PSENDCMDINPARAMS)(SrbIoControl + 1);

          memcpy(InParams, Irp->AssociatedIrp.SystemBuffer, sizeof(SENDCMDINPARAMS) - 1);
          
          InParams->bDriveNumber = DeviceExtension->TargetId;

          KeInitializeEvent(&Event, NotificationEvent, FALSE);
          LocalIrp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT,
                                                   DeviceExtension->PortDeviceObject,
                                                   SrbIoControl,
                                                   sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1,
                                                   SrbIoControl,
                                                   sizeof(SRB_IO_CONTROL) + Information,
                                                   FALSE,
                                                   &Event,
                                                   &IoSB);
          if (LocalIrp == NULL)
            {
              ExFreePool(SrbIoControl);
              Information = 0;
	      Status = STATUS_INSUFFICIENT_RESOURCES;
              break;
            }
          Status = IoCallDriver(DeviceExtension->PortDeviceObject, LocalIrp);
          if (Status == STATUS_PENDING)
            {
              KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
              Status = IoSB.Status;
            }
          if (NT_SUCCESS(Status))
            {
              Information = SrbIoControl->Length;
            }
          else
            {
              Information = sizeof(SENDCMDOUTPARAMS) - 1;
            }
          memcpy(Irp->AssociatedIrp.SystemBuffer, InParams, Information);
          ExFreePool(SrbIoControl);
          break;
        }

      case SMART_RCV_DRIVE_DATA:
        {
          DPRINT("SMART_RCV_DRIVE_DATA\n");

          if (InputLength < sizeof(SENDCMDINPARAMS) - 1)
            {
	      Status = STATUS_INFO_LENGTH_MISMATCH;
              break;
            }

          InParams = (PSENDCMDINPARAMS)Irp->AssociatedIrp.SystemBuffer;
          if (InParams->irDriveRegs.bCommandReg == ID_CMD) 
            {
              DPRINT("IOCTL_SCSI_MINIPORT_IDENTIFY\n");
              ControlCode = IOCTL_SCSI_MINIPORT_IDENTIFY;
              Information = IDENTIFY_BUFFER_SIZE + sizeof(SENDCMDOUTPARAMS) - 1;
            }
          else if (InParams->irDriveRegs.bCommandReg == SMART_CMD) 
            {
              if (InParams->irDriveRegs.bFeaturesReg == READ_ATTRIBUTES)
                {
                  DPRINT("IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS\n");
                  ControlCode = IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS;
                  Information = READ_ATTRIBUTE_BUFFER_SIZE + sizeof(SENDCMDOUTPARAMS) - 1;
                }
              else if (InParams->irDriveRegs.bFeaturesReg == READ_THRESHOLDS)
                {
                  DPRINT("IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS\n");
                  ControlCode = IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS;
                  Information = READ_THRESHOLD_BUFFER_SIZE + sizeof(SENDCMDOUTPARAMS) - 1;
                }
              else if (InParams->irDriveRegs.bFeaturesReg == SMART_READ_LOG)
                {
                  DPRINT("IOCTL_SCSI_MINIPORT_READ_SMART_LOG\n");
                  ControlCode = IOCTL_SCSI_MINIPORT_READ_SMART_LOG;
                  Information = sizeof(SENDCMDOUTPARAMS) - 1 + 512 * max(1, InParams->irDriveRegs.bSectorCountReg); 
                }
              else
                {
                  DPRINT("%x\n", InParams->irDriveRegs.bFeaturesReg);
                  Status = STATUS_INVALID_PARAMETER;
                  break;
                }
            }
          else
            {
              DPRINT("%x\n", InParams->irDriveRegs.bCommandReg);
              Status = STATUS_INVALID_PARAMETER;
              break;
            }
          if (OutputLength < Information)
            {
              Status =  STATUS_BUFFER_TOO_SMALL;
              break;
            }
          SrbIoControl = ExAllocatePool(NonPagedPool, sizeof(SRB_IO_CONTROL) + Information);
          if (SrbIoControl == NULL) 
            {
              Status =  STATUS_INSUFFICIENT_RESOURCES;
              Information = 0;
              break;
            }
          memset(SrbIoControl, 0, sizeof(SRB_IO_CONTROL) + Information);

          SrbIoControl->HeaderLength = sizeof(SRB_IO_CONTROL);
          memcpy(SrbIoControl->Signature, "SCSIDISK", 8);
          SrbIoControl->Timeout = DeviceExtension->TimeOutValue * 4;
          SrbIoControl->Length = Information;
          SrbIoControl->ControlCode = ControlCode;

          InParams = (PSENDCMDINPARAMS)(SrbIoControl + 1);

          memcpy(InParams, Irp->AssociatedIrp.SystemBuffer, sizeof(SENDCMDINPARAMS) - 1);
          
          InParams->bDriveNumber = DeviceExtension->TargetId;

          KeInitializeEvent(&Event, NotificationEvent, FALSE);
          LocalIrp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_MINIPORT,
                                                   DeviceExtension->PortDeviceObject,
                                                   SrbIoControl,
                                                   sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1,
                                                   SrbIoControl,
                                                   sizeof(SRB_IO_CONTROL) + Information,
                                                   FALSE,
                                                   &Event,
                                                   &IoSB);
          if (LocalIrp == NULL)
            {
              ExFreePool(SrbIoControl);
              Information = 0;
	      Status = STATUS_INSUFFICIENT_RESOURCES;
              break;
            }
          Status = IoCallDriver(DeviceExtension->PortDeviceObject, LocalIrp);
          if (Status == STATUS_PENDING)
            {
              KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
              Status = IoSB.Status;
            }
          if (NT_SUCCESS(Status))
            {

⌨️ 快捷键说明

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