cdrom.c

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

C
1,704
字号
 * NAME							EXPORTED
 *	CdromClassCreateDeviceObject
 *
 * DESCRIPTION:
 *	Create the raw device and any partition devices on this drive
 *
 * RUN LEVEL:
 *	PASSIVE_LEVEL
 *
 * ARGUMENTS:
 *	DriverObject
 *		System allocated Driver Object for this driver.
 *	RegistryPath
 *		Name of registry driver service key.
 *	PortDeviceObject
 *	PortNumber
 *	DeviceNumber
 *	Capabilities
 *	InquiryData
 *	InitializationData
 *
 * RETURNS:
 *	Status.
 */

static NTSTATUS
CdromClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
			     IN PUNICODE_STRING RegistryPath,
			     IN PDEVICE_OBJECT PortDeviceObject,
			     IN ULONG PortNumber,
			     IN ULONG DeviceNumber,
			     IN PIO_SCSI_CAPABILITIES Capabilities,
			     IN PSCSI_INQUIRY_DATA InquiryData,
			     IN PCLASS_INIT_DATA InitializationData)
{
  PDEVICE_EXTENSION DiskDeviceExtension; /* defined in class2.h */
  PDEVICE_OBJECT DiskDeviceObject;
  PCDROM_DATA CdromData;
  CHAR NameBuffer[80];
  SCSI_REQUEST_BLOCK Srb;
  PUCHAR Buffer;
  ULONG Length;
  PCDB Cdb;
  NTSTATUS Status;

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

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

  /* Create cdrom device */
  sprintf(NameBuffer,
	  "\\Device\\CdRom%lu",
	  DeviceNumber);

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

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

      return(Status);
    }

  DiskDeviceObject->Flags |= DO_DIRECT_IO;
  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 = DeviceNumber;
  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;

  /* zero-out disk data */
  CdromData = (PCDROM_DATA)(DiskDeviceExtension + 1);
  RtlZeroMemory(CdromData,
		sizeof(CDROM_DATA));

  DiskDeviceExtension->SenseData = ExAllocatePool(NonPagedPool,
						  sizeof(SENSE_DATA));
  if (DiskDeviceExtension->SenseData == NULL)
    {
      DPRINT1("Failed to allocate sense data buffer!\n");

      IoDeleteDevice(DiskDeviceObject);

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

      return(STATUS_INSUFFICIENT_RESOURCES);
    }

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

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

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

      ExDeleteNPagedLookasideList(&DiskDeviceExtension->SrbLookasideListHead);

      IoDeleteDevice(DiskDeviceObject);

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

      return(STATUS_INSUFFICIENT_RESOURCES);
    }

  /* Read the drive's capacity */
  Status = ScsiClassReadDriveCapacity(DiskDeviceObject);
  if (!NT_SUCCESS(Status) ||
      DiskDeviceExtension->DiskGeometry->BytesPerSector == 0)
    {
      /* Set ISO9660 defaults */
      DiskDeviceExtension->DiskGeometry->BytesPerSector = 2048;
      DiskDeviceExtension->DiskGeometry->MediaType = RemovableMedia;
      DiskDeviceExtension->SectorShift = 11;
      DiskDeviceExtension->PartitionLength.QuadPart = (ULONGLONG)0x7fffffff;
    }
  else
    {
      /* Make sure the BytesPerSector value is a power of 2 */
//      DiskDeviceExtension->DiskGeometry->BytesPerSector = 2048;
    }

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

  /* Initialize media change support */
  CdromClassCreateMediaChangeEvent (DiskDeviceExtension,
				    DeviceNumber);
  if (DiskDeviceExtension->MediaChangeEvent != NULL)
    {
      DPRINT("Allocated media change event!\n");

      /* FIXME: Allocate media change IRP and SRB */
    }

  /* Use 6 byte xa commands by default */
  CdromData->XaFlags |= XA_USE_6_BYTE;

  /* Read 'error recovery page' to get additional drive capabilities */
  Length = sizeof(MODE_READ_RECOVERY_PAGE) + MODE_HEADER_LENGTH;

  RtlZeroMemory (&Srb,
		 sizeof(SCSI_REQUEST_BLOCK));
  Srb.CdbLength = 6;
  Srb.TimeOutValue = DiskDeviceExtension->TimeOutValue;

  Cdb = (PCDB)Srb.Cdb;
  Cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
  Cdb->MODE_SENSE.PageCode = 0x01;
  Cdb->MODE_SENSE.AllocationLength = (UCHAR)Length;

  Buffer = ExAllocatePool (NonPagedPool,
                           max(sizeof(ERROR_RECOVERY_DATA6),
			       max(sizeof(ERROR_RECOVERY_DATA10),
			           max(sizeof(MODE_CAPABILITIES_DATA6),
				       sizeof(MODE_CAPABILITIES_DATA10)))));
  if (Buffer == NULL)
    {
      DPRINT1("Allocating recovery page buffer failed!\n");
      return STATUS_INSUFFICIENT_RESOURCES;
    }

  Status = ScsiClassSendSrbSynchronous (DiskDeviceObject,
					&Srb,
					Buffer,
					Length,
					FALSE);

  if (!NT_SUCCESS (Status))
    {
      DPRINT("MODE_SENSE(6) failed\n");

      /* Try the 10 byte version */
      Length = sizeof(MODE_READ_RECOVERY_PAGE) + MODE_HEADER_LENGTH10;

      RtlZeroMemory (&Srb,
		     sizeof(SCSI_REQUEST_BLOCK));
      Srb.CdbLength = 10;
      Srb.TimeOutValue = DiskDeviceExtension->TimeOutValue;

      Cdb = (PCDB)Srb.Cdb;
      Cdb->MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10;
      Cdb->MODE_SENSE10.PageCode = 0x01;
      Cdb->MODE_SENSE10.AllocationLength[0] = (UCHAR)(Length >> 8);
      Cdb->MODE_SENSE10.AllocationLength[1] = (UCHAR)(Length & 0xFF);

      Status = ScsiClassSendSrbSynchronous (DiskDeviceObject,
					    &Srb,
					    Buffer,
					    Length,
					    FALSE);

      if (Status == STATUS_DATA_OVERRUN)
	{
	  DPRINT1("Data overrun\n");

	  /* FIXME */
	}
      else if (NT_SUCCESS (Status))
	{
	  DPRINT("Use 10 byte commands\n");
	  CdromData->XaFlags &= XA_USE_6_BYTE;
	  CdromData->XaFlags |= XA_USE_10_BYTE;
	}
      else
	{
	  DPRINT("XA not supported\n");
	  CdromData->XaFlags |= XA_NOT_SUPPORTED;
	}
    }
  else
    {
      DPRINT("Use 6 byte commands\n");
    }

  /* Read 'capabilities & mechanical status page' to get additional drive capabilities */
  Length = sizeof(MODE_READ_RECOVERY_PAGE) + MODE_HEADER_LENGTH;

  if (!(CdromData->XaFlags & XA_NOT_SUPPORTED))
    {
      RtlZeroMemory (&Srb, sizeof(SCSI_REQUEST_BLOCK));
      Srb.TimeOutValue = DiskDeviceExtension->TimeOutValue;
      Cdb = (PCDB)Srb.Cdb;

      if (CdromData->XaFlags & XA_USE_10_BYTE)
        {
          /* Try the 10 byte version */
          Length = sizeof(MODE_CAPABILITIES_PAGE2) + MODE_HEADER_LENGTH10;

          Srb.CdbLength = 10;
          Cdb->MODE_SENSE10.OperationCode = SCSIOP_MODE_SENSE10;
          Cdb->MODE_SENSE10.PageCode = 0x2a;
          Cdb->MODE_SENSE10.AllocationLength[0] = (UCHAR)(Length >> 8);
          Cdb->MODE_SENSE10.AllocationLength[1] = (UCHAR)(Length & 0xFF);
	}
      else
        {
          Length = sizeof(MODE_CAPABILITIES_PAGE2) + MODE_HEADER_LENGTH;

          Srb.CdbLength = 6;
          Cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
          Cdb->MODE_SENSE.PageCode = 0x2a;
          Cdb->MODE_SENSE.AllocationLength = (UCHAR)Length;
        }
      Status = ScsiClassSendSrbSynchronous (DiskDeviceObject,
					    &Srb,
					    Buffer,
					    Length,
					    FALSE);
      if (NT_SUCCESS (Status))
	{
#if 0
          PMODE_CAPABILITIES_PAGE2 CapabilitiesData;
	  if (CdromData->XaFlags & XA_USE_10_BYTE)
	    {
	      CapabilitiesData = (PMODE_CAPABILITIES_PAGE2)(Buffer + sizeof(MODE_PARAMETER_HEADER10));
	    }
	  else
	    {
	      CapabilitiesData = (PMODE_CAPABILITIES_PAGE2)(Buffer + sizeof(MODE_PARAMETER_HEADER));
	    }

	  DbgPrint("Capabilities for '%s':\n", NameBuffer);
	  if (CapabilitiesData->Reserved2[0] & 0x20)
	    {
	      DbgPrint("  Drive supports reading of DVD-RAM discs\n");
	    }
	  if (CapabilitiesData->Reserved2[0] & 0x10)
	    {
	      DbgPrint("  Drive supports reading of DVD-R discs\n");
	    }
	  if (CapabilitiesData->Reserved2[0] & 0x08)
	    {
	      DbgPrint("  Drive supports reading of DVD-ROM discs\n");
	    }
	  if (CapabilitiesData->Reserved2[0] & 0x04)
	    {
	      DbgPrint("  Drive supports reading CD-R discs with addressing method 2\n");
	    }
	  if (CapabilitiesData->Reserved2[0] & 0x02)
	    {
	      DbgPrint("  Drive can read from CD-R/W (CD-E) discs (orange book, part III)\n");
	    }
	  if (CapabilitiesData->Reserved2[0] & 0x01)
	    {
	      DbgPrint("  Drive supports read from CD-R discs (orange book, part II)\n");
	    }
	  DPRINT("CapabilitiesData.Reserved2[1] %x\n", CapabilitiesData->Reserved2[1]);
	  if (CapabilitiesData->Reserved2[1] & 0x01)
	    {
	      DbgPrint("  Drive can write to CD-R discs (orange book, part II)\n");
	    }
	  if (CapabilitiesData->Reserved2[1] & 0x02)
	    {
	      DbgPrint("  Drive can write to CD-R/W (CD-E) discs (orange book, part III)\n");
	    }
	  if (CapabilitiesData->Reserved2[1] & 0x04)
	    {
	      DbgPrint("  Drive can fake writes\n");
	    }
	  if (CapabilitiesData->Reserved2[1] & 0x10)
	    {
	      DbgPrint("  Drive can write DVD-R discs\n");
	    }
	  if (CapabilitiesData->Reserved2[1] & 0x20)
	    {
	      DbgPrint("  Drive can write DVD-RAM discs\n");
	    }
	  DPRINT("CapabilitiesData.Capabilities[0] %x\n", CapabilitiesData->Capabilities[0]);
	  if (CapabilitiesData->Capabilities[0] & 0x01)
	    {
	      DbgPrint("  Drive supports audio play operations\n");
	    }
	  if (CapabilitiesData->Capabilities[0] & 0x02)
	    {
	      DbgPrint("  Drive can deliver a composite audio/video data stream\n");
	    }
	  if (CapabilitiesData->Capabilities[0] & 0x04)
	    {
	      DbgPrint("  Drive supports digital output on port 1\n");
	    }
	  if (CapabilitiesData->Capabilities[0] & 0x08)
	    {
	      DbgPrint("  Drive supports digital output on port 2\n");
	    }
	  if (CapabilitiesData->Capabilities[0] & 0x10)
	    {
	      DbgPrint("  Drive can read mode 2, form 1 (XA) data\n");
	    }
	  if (CapabilitiesData->Capabilities[0] & 0x20)
	    {
	      DbgPrint("  Drive can read mode 2, form 2 data\n");
	    }
	  if (CapabilitiesData->Capabilities[0] & 0x40)
	    {
	      DbgPrint("  Drive can read multisession discs\n");
	    }
	  DPRINT("CapabilitiesData.Capabilities[1] %x\n", CapabilitiesData->Capabilities[1]);
	  if (CapabilitiesData->Capabilities[1] & 0x01)
	    {
	      DbgPrint("  Drive can read Red Book audio data\n");
	    }
	  if (CapabilitiesData->Capabilities[1] & 0x02)
	    {
	      DbgPrint("  Drive can continue a read cdda operation from a loss of streaming\n");
	    }
	  if (CapabilitiesData->Capabilities[1] & 0x04)
	    {
	      DbgPrint("  Subchannel reads can return combined R-W information\n");
	    }
	  if (CapabilitiesData->Capabilities[1] & 0x08)
	    {
	      DbgPrint("  R-W data will be returned deinterleaved and error corrected\n");
	    }
	  if (CapabilitiesData->Capabilities[1] & 0x10)
	    {
	      DbgPrint("  Drive supports C2 error pointers\n");
	    }
	  if (CapabilitiesData->Capabilities[1] & 0x20)
	    {
	      DbgPrint("  Drive can return International Standard Recording Code info\n");
	    }
	  if (CapabilitiesData->Capabilities[1] & 0x40)
	    {
	      DbgPrint("  Drive can return Media Catalog Number (UPC) info\n");
	    }
	  DPRINT("CapabilitiesData.Capabilities[2] %x\n", CapabilitiesData->Capabilities[2]);
	  if (CapabilitiesData->Capabilities[2] & 0x01)
	    {
	      DbgPrint("  Drive can lock the door\n");
	    }
	  if (CapabilitiesData->Capabilities[2] & 0x02)
	    {
	      DbgPrint("  The door is locked\n");
	    }
	  if (CapabilitiesData->Capabilities[2] & 0x04)
	    {

⌨️ 快捷键说明

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