Patch by tinus.Fix media change support for CDROMs. This fixes bug #471. Patch by tinus.

svn path=/trunk/; revision=13097
This commit is contained in:
Eric Kohl 2005-01-17 14:30:31 +00:00
parent 968f3f7c24
commit 69688ce6ab
5 changed files with 132 additions and 43 deletions

View file

@ -191,6 +191,19 @@ CdfsDeviceIoControl (IN PDEVICE_OBJECT DeviceObject,
*OutputBufferSize = IoStatus.Information;
}
if (Status == STATUS_VERIFY_REQUIRED)
{
PDEVICE_OBJECT DeviceToVerify;
NTSTATUS NewStatus;
DPRINT1("STATUS_VERIFY_REQUIRED\n");
DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread());
IoSetDeviceToVerify(PsGetCurrentThread(), NULL);
NewStatus = IoVerifyVolume(DeviceToVerify, FALSE);
DPRINT1("IoVerifyVolume() retuned (Status %lx)\n", NewStatus);
}
DPRINT("Returning Status %x\n", Status);
return Status;

View file

@ -140,28 +140,9 @@ CdfsOpenFile(PDEVICE_EXTENSION DeviceExt,
0,
NULL,
0,
TRUE);
FALSE);
DPRINT ("Status %lx\n", Status);
if (Status == STATUS_VERIFY_REQUIRED)
{
PDEVICE_OBJECT DeviceToVerify;
DPRINT1 ("Media change detected!\n");
DPRINT1 ("Device %p\n", DeviceExt->VolumeDevice);
DeviceToVerify = IoGetDeviceToVerify (PsGetCurrentThread ());
IoSetDeviceToVerify (PsGetCurrentThread (),
NULL);
Status = IoVerifyVolume (DeviceToVerify,
FALSE);
if (!NT_SUCCESS(Status))
{
DPRINT1 ("Status %lx\n", Status);
return Status;
}
}
else if (!NT_SUCCESS(Status))
if (!NT_SUCCESS(Status))
{
DPRINT1 ("Status %lx\n", Status);
return Status;

View file

@ -345,6 +345,7 @@ CdfsMountVolume(PDEVICE_OBJECT DeviceObject,
goto ByeBye;
NewDeviceObject->Flags = NewDeviceObject->Flags | DO_DIRECT_IO;
NewDeviceObject->Flags &= ~DO_VERIFY_VOLUME;
DeviceExt = (PVOID)NewDeviceObject->DeviceExtension;
RtlZeroMemory(DeviceExt,
sizeof(DEVICE_EXTENSION));

View file

@ -134,6 +134,10 @@ VOID STDCALL
CdromTimerRoutine(IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context);
VOID
CdromWorkItem(IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context);
/* FUNCTIONS ****************************************************************/
@ -1203,7 +1207,10 @@ CdromClassStartIo (IN PDEVICE_OBJECT DeviceObject,
Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED;
/* FIXME: Update drive capacity */
IoCompleteRequest (Irp,
IO_DISK_INCREMENT);
IoStartNextPacket (DeviceObject,
FALSE);
return;
}
}
@ -1614,11 +1621,68 @@ CdromDeviceControlCompletion (IN PDEVICE_OBJECT DeviceObject,
VOID STDCALL
CdromTimerRoutine(PDEVICE_OBJECT DeviceObject,
PVOID Context)
CdromTimerRoutine(IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context)
{
DPRINT ("CdromTimerRoutine() called\n");
PIO_WORKITEM WorkItem;
DPRINT ("CdromTimerRoutine() called\n");
WorkItem = IoAllocateWorkItem(DeviceObject);
if (!WorkItem)
{
return;
}
IoQueueWorkItem(WorkItem,
CdromWorkItem,
DelayedWorkQueue,
WorkItem);
}
VOID
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 */

View file

@ -1026,6 +1026,46 @@ ScsiClassInternalIoControl(IN PDEVICE_OBJECT DeviceObject,
}
/*
* Implements part of the directives on:
* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/kmarch/hh/kmarch/other_c694d732-fa95-4841-8d61-2a55ee787905.xml.asp
*/
static VOID
ScsiClassInvalidateMedia(IN PDEVICE_OBJECT DeviceObject,
OUT NTSTATUS *Status)
{
PDEVICE_EXTENSION DeviceExtension;
PDEVICE_EXTENSION PhysicalExtension;
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
PhysicalExtension = (PDEVICE_EXTENSION)DeviceExtension->PhysicalDevice->DeviceExtension;
if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
{
DPRINT("Invalidate: test char yields TRUE\n");
}
else
{
DPRINT("Invalidate: test char yields FALSE\n");
}
if ((DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) &&
(DeviceObject->Vpb->Flags & VPB_MOUNTED))
{
DPRINT("Set DO_VERIFY_VOLUME\n");
DeviceObject->Flags |= DO_VERIFY_VOLUME;
*Status = STATUS_VERIFY_REQUIRED;
}
else
{
*Status = STATUS_IO_DEVICE_ERROR;
}
/* Increment the media change count */
PhysicalExtension->MediaChangeCount++;
}
/*
* @implemented
*/
@ -1106,9 +1146,12 @@ ScsiClassInterpretSenseInfo(IN PDEVICE_OBJECT DeviceObject,
case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE:
DPRINT("SCSI_ADSENSE_NO_MEDIA_IN_DEVICE\n");
*Status = STATUS_NO_MEDIA_IN_DEVICE;
ScsiClassInvalidateMedia(DeviceObject,
Status);
*Status = STATUS_NO_MEDIA_IN_DEVICE;
Retry = FALSE;
if((DeviceExtension->MediaChangeEvent != NULL) &&
(!DeviceExtension->MediaChangeEvent))
{
@ -1200,22 +1243,9 @@ ScsiClassInterpretSenseInfo(IN PDEVICE_OBJECT DeviceObject,
break;
}
if ((DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) &&
(DeviceObject->Vpb->Flags & VPB_MOUNTED))
{
DPRINT("SCSI_SENSE_UNIT_ATTENTION set DoVerifyVol\n");
DeviceObject->Flags |= DO_VERIFY_VOLUME;
*Status = STATUS_VERIFY_REQUIRED;
Retry = FALSE;
}
else
{
*Status = STATUS_IO_DEVICE_ERROR;
}
/* Increment the media change count */
PhysicalExtension->MediaChangeCount++;
ScsiClassInvalidateMedia(DeviceObject,
Status);
Retry = FALSE;
break;
case SCSI_SENSE_DATA_PROTECT: