cdrom.c
来自「一个类似windows」· C语言 代码 · 共 1,704 行 · 第 1/4 页
C
1,704 行
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest (Irp,
IO_DISK_INCREMENT);
IoStartNextPacket (DeviceObject,
FALSE);
return;
}
/* Allocate an SRB */
Srb = ExAllocatePool (NonPagedPool,
sizeof (SCSI_REQUEST_BLOCK));
if (Srb == NULL)
{
IoFreeIrp (SubIrp);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest (Irp,
IO_DISK_INCREMENT);
IoStartNextPacket (DeviceObject,
FALSE);
return;
}
/* Allocte a sense buffer */
SenseBuffer = ExAllocatePool (NonPagedPoolCacheAligned,
SENSE_BUFFER_SIZE);
if (SenseBuffer == NULL)
{
ExFreePool (Srb);
IoFreeIrp (SubIrp);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest (Irp,
IO_DISK_INCREMENT);
IoStartNextPacket (DeviceObject,
FALSE);
return;
}
/* Initialize the IRP */
IoSetNextIrpStackLocation (SubIrp);
SubIrp->IoStatus.Information = 0;
SubIrp->IoStatus.Status = STATUS_SUCCESS;
SubIrp->Flags = 0;
SubIrp->UserBuffer = NULL;
SubIrpStack = IoGetCurrentIrpStackLocation (SubIrp);
SubIrpStack->DeviceObject = DeviceExtension->DeviceObject;
SubIrpStack->Parameters.Others.Argument2 = (PVOID)Irp;
/* Initialize next stack location */
SubIrpStack = IoGetNextIrpStackLocation (SubIrp);
SubIrpStack->MajorFunction = IRP_MJ_SCSI;
SubIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_EXECUTE_IN;
SubIrpStack->Parameters.Scsi.Srb = Srb;
/* Initialize the SRB */
RtlZeroMemory(Srb,
sizeof (SCSI_REQUEST_BLOCK));
Srb->Length = sizeof (SCSI_REQUEST_BLOCK);
Srb->PathId = DeviceExtension->PathId;
Srb->TargetId = DeviceExtension->TargetId;
Srb->Lun = DeviceExtension->Lun;
Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
Srb->SrbStatus = SRB_STATUS_SUCCESS;
Srb->ScsiStatus = 0;
Srb->NextSrb = 0;
Srb->OriginalRequest = SubIrp;
Srb->SenseInfoBuffer = SenseBuffer;
Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
/* Initialize the CDB */
Cdb = (PCDB)Srb->Cdb;
/* Set the completion routine */
IoSetCompletionRoutine (SubIrp,
CdromDeviceControlCompletion,
Srb,
TRUE,
TRUE,
TRUE);
switch (IrpStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
DPRINT ("CdromClassStartIo: IOCTL_CDROM_GET_DRIVE_GEOMETRY\n");
Srb->DataTransferLength = sizeof(READ_CAPACITY_DATA);
Srb->CdbLength = 10;
Srb->TimeOutValue = DeviceExtension->TimeOutValue;
Srb->SrbFlags = SRB_FLAGS_DISABLE_SYNCH_TRANSFER | SRB_FLAGS_DATA_IN;
Cdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY;
/* Allocate data buffer */
DataBuffer = ExAllocatePool (NonPagedPoolCacheAligned,
sizeof(READ_CAPACITY_DATA));
if (DataBuffer == NULL)
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest (Irp,
IO_DISK_INCREMENT);
ExFreePool (SenseBuffer);
ExFreePool (Srb);
IoFreeIrp (SubIrp);
IoStartNextPacket (DeviceObject,
FALSE);
return;
}
/* Allocate an MDL for the data buffer */
SubIrp->MdlAddress = IoAllocateMdl (DataBuffer,
sizeof(READ_CAPACITY_DATA),
FALSE,
FALSE,
NULL);
if (SubIrp->MdlAddress == NULL)
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest (Irp,
IO_DISK_INCREMENT);
ExFreePool (DataBuffer);
ExFreePool (SenseBuffer);
ExFreePool (Srb);
IoFreeIrp (SubIrp);
IoStartNextPacket (DeviceObject,
FALSE);
return;
}
MmBuildMdlForNonPagedPool (SubIrp->MdlAddress);
Srb->DataBuffer = DataBuffer;
IoCallDriver (DeviceExtension->PortDeviceObject,
SubIrp);
return;
case IOCTL_CDROM_CHECK_VERIFY:
DPRINT ("CdromClassStartIo: IOCTL_CDROM_CHECK_VERIFY\n");
Srb->CdbLength = 6;
Srb->TimeOutValue = DeviceExtension->TimeOutValue * 2;
Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER;
Cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
IoCallDriver (DeviceExtension->PortDeviceObject,
SubIrp);
return;
default:
IoCompleteRequest (Irp,
IO_NO_INCREMENT);
return;
}
}
/* Call the SCSI port driver */
IoCallDriver (DeviceExtension->PortDeviceObject,
Irp);
}
NTSTATUS STDCALL
CdromDeviceControlCompletion (IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context)
{
PDEVICE_EXTENSION DeviceExtension;
PDEVICE_EXTENSION PhysicalExtension;
PIO_STACK_LOCATION IrpStack;
PIO_STACK_LOCATION OrigCurrentIrpStack;
PIO_STACK_LOCATION OrigNextIrpStack;
PSCSI_REQUEST_BLOCK Srb;
PIRP OrigIrp;
BOOLEAN Retry;
NTSTATUS Status;
DPRINT ("CdromDeviceControlCompletion() called\n");
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
PhysicalExtension = (PDEVICE_EXTENSION)DeviceExtension->PhysicalDevice->DeviceExtension;
Srb = (PSCSI_REQUEST_BLOCK) Context;
IrpStack = IoGetCurrentIrpStackLocation (Irp);
/* Get the original IRP */
OrigIrp = (PIRP)IrpStack->Parameters.Others.Argument2;
OrigCurrentIrpStack = IoGetCurrentIrpStackLocation (OrigIrp);
OrigNextIrpStack = IoGetNextIrpStackLocation (OrigIrp);
if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS)
{
Status = STATUS_SUCCESS;
}
else
{
DPRINT ("SrbStatus %lx\n", Srb->SrbStatus);
/* Interpret sense info */
Retry = ScsiClassInterpretSenseInfo (DeviceObject,
Srb,
IrpStack->MajorFunction,
IrpStack->Parameters.DeviceIoControl.IoControlCode,
MAXIMUM_RETRIES - (ULONG)OrigNextIrpStack->Parameters.Others.Argument1,
&Status);
DPRINT ("Retry %u\n", Retry);
if (Retry == TRUE &&
(ULONG)OrigNextIrpStack->Parameters.Others.Argument1 > 0)
{
DPRINT1 ("Try again (Retry count 0x%p)\n",
(ULONG)OrigNextIrpStack->Parameters.Others.Argument1);
OrigNextIrpStack->Parameters.Others.Argument1 = (PVOID)((ULONG_PTR)OrigNextIrpStack->Parameters.Others.Argument1 - 1);
/* Release 'old' buffers */
ExFreePool (Srb->SenseInfoBuffer);
if (Srb->DataBuffer)
ExFreePool(Srb->DataBuffer);
ExFreePool(Srb);
if (Irp->MdlAddress != NULL)
IoFreeMdl(Irp->MdlAddress);
IoFreeIrp(Irp);
/* Call the StartIo routine again */
CdromClassStartIo (DeviceObject,
OrigIrp);
return STATUS_MORE_PROCESSING_REQUIRED;
}
DPRINT ("Status %lx\n", Status);
}
if (NT_SUCCESS (Status))
{
switch (OrigCurrentIrpStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
{
PREAD_CAPACITY_DATA CapacityBuffer;
ULONG LastSector;
ULONG SectorSize;
DPRINT ("CdromClassControlCompletion: IOCTL_CDROM_GET_DRIVE_GEOMETRY\n");
CapacityBuffer = (PREAD_CAPACITY_DATA)Srb->DataBuffer;
SectorSize = (((PUCHAR)&CapacityBuffer->BytesPerBlock)[0] << 24) |
(((PUCHAR)&CapacityBuffer->BytesPerBlock)[1] << 16) |
(((PUCHAR)&CapacityBuffer->BytesPerBlock)[2] << 8) |
((PUCHAR)&CapacityBuffer->BytesPerBlock)[3];
LastSector = (((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[0] << 24) |
(((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[1] << 16) |
(((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[2] << 8) |
((PUCHAR)&CapacityBuffer->LogicalBlockAddress)[3];
if (SectorSize == 0)
SectorSize = 2048;
DeviceExtension->DiskGeometry->BytesPerSector = SectorSize;
DeviceExtension->PartitionLength.QuadPart = (LONGLONG)(LastSector + 1);
WHICH_BIT(DeviceExtension->DiskGeometry->BytesPerSector,
DeviceExtension->SectorShift);
DeviceExtension->PartitionLength.QuadPart =
(DeviceExtension->PartitionLength.QuadPart << DeviceExtension->SectorShift);
if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
{
DeviceExtension->DiskGeometry->MediaType = RemovableMedia;
}
else
{
DeviceExtension->DiskGeometry->MediaType = FixedMedia;
}
DeviceExtension->DiskGeometry->Cylinders.QuadPart =
(LONGLONG)((LastSector + 1)/(32 * 64));
DeviceExtension->DiskGeometry->SectorsPerTrack = 32;
DeviceExtension->DiskGeometry->TracksPerCylinder = 64;
RtlCopyMemory (OrigIrp->AssociatedIrp.SystemBuffer,
DeviceExtension->DiskGeometry,
sizeof(DISK_GEOMETRY));
OrigIrp->IoStatus.Information = sizeof(DISK_GEOMETRY);
}
break;
case IOCTL_CDROM_CHECK_VERIFY:
DPRINT ("CdromDeviceControlCompletion: IOCTL_CDROM_CHECK_VERIFY\n");
if (OrigCurrentIrpStack->Parameters.DeviceIoControl.OutputBufferLength != 0)
{
/* Return the media change counter */
*((PULONG)(OrigIrp->AssociatedIrp.SystemBuffer)) =
PhysicalExtension->MediaChangeCount;
OrigIrp->IoStatus.Information = sizeof(ULONG);
}
else
{
OrigIrp->IoStatus.Information = 0;
}
break;
default:
OrigIrp->IoStatus.Information = 0;
Status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
}
/* Release the SRB and associated buffers */
if (Srb != NULL)
{
DPRINT("Srb %p\n", Srb);
if (Srb->DataBuffer != NULL)
ExFreePool (Srb->DataBuffer);
if (Srb->SenseInfoBuffer != NULL)
ExFreePool (Srb->SenseInfoBuffer);
ExFreePool (Srb);
}
if (OrigIrp->PendingReturned)
{
IoMarkIrpPending (OrigIrp);
}
/* Release the MDL */
if (Irp->MdlAddress != NULL)
{
IoFreeMdl (Irp->MdlAddress);
}
/* Release the sub irp */
IoFreeIrp (Irp);
/* Set io status information */
OrigIrp->IoStatus.Status = Status;
if (!NT_SUCCESS(Status) && IoIsErrorUserInduced (Status))
{
IoSetHardErrorOrVerifyDevice (OrigIrp,
DeviceObject);
OrigIrp->IoStatus.Information = 0;
}
/* Complete the original IRP */
IoCompleteRequest (OrigIrp,
IO_DISK_INCREMENT);
IoStartNextPacket (DeviceObject,
FALSE);
DPRINT ("CdromDeviceControlCompletion() done\n");
return STATUS_MORE_PROCESSING_REQUIRED;
}
VOID STDCALL
CdromTimerRoutine(IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context)
{
PIO_WORKITEM WorkItem;
DPRINT ("CdromTimerRoutine() called\n");
WorkItem = IoAllocateWorkItem(DeviceObject);
if (!WorkItem)
{
return;
}
IoQueueWorkItem(WorkItem,
CdromWorkItem,
DelayedWorkQueue,
WorkItem);
}
VOID STDCALL
CdromWorkItem(IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context)
{
PIRP Irp;
KEVENT Event;
IO_STATUS_BLOCK IoStatus;
NTSTATUS Status;
DPRINT("CdromWorkItem() called\n");
IoFreeWorkItem((PIO_WORKITEM) Context);
KeInitializeEvent(&Event,
NotificationEvent,
FALSE);
Irp = IoBuildDeviceIoControlRequest(IOCTL_CDROM_CHECK_VERIFY,
DeviceObject,
NULL,
0,
NULL,
0,
FALSE,
&Event,
&IoStatus);
if (Irp == NULL)
{
DPRINT("IoBuildDeviceIoControlRequest failed\n");
return;
}
Status = IoCallDriver(DeviceObject, Irp);
DPRINT("Status: %x\n", Status);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event,
Suspended,
KernelMode,
FALSE,
NULL);
}
}
/* EOF */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?