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 + -
显示快捷键?