From 69688ce6abf2451e86a422a61849c44fdc1ae9d7 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Mon, 17 Jan 2005 14:30:31 +0000 Subject: [PATCH] Patch by tinus.Fix media change support for CDROMs. This fixes bug #471. Patch by tinus. svn path=/trunk/; revision=13097 --- reactos/drivers/fs/cdfs/common.c | 13 +++++ reactos/drivers/fs/cdfs/create.c | 23 +------- reactos/drivers/fs/cdfs/fsctl.c | 1 + reactos/drivers/storage/cdrom/cdrom.c | 72 +++++++++++++++++++++++-- reactos/drivers/storage/class2/class2.c | 66 ++++++++++++++++------- 5 files changed, 132 insertions(+), 43 deletions(-) diff --git a/reactos/drivers/fs/cdfs/common.c b/reactos/drivers/fs/cdfs/common.c index 940179adbf4..9e247805872 100644 --- a/reactos/drivers/fs/cdfs/common.c +++ b/reactos/drivers/fs/cdfs/common.c @@ -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; diff --git a/reactos/drivers/fs/cdfs/create.c b/reactos/drivers/fs/cdfs/create.c index 24201978719..7bbef26a01c 100644 --- a/reactos/drivers/fs/cdfs/create.c +++ b/reactos/drivers/fs/cdfs/create.c @@ -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; diff --git a/reactos/drivers/fs/cdfs/fsctl.c b/reactos/drivers/fs/cdfs/fsctl.c index 5122ea7dde2..85f67040781 100644 --- a/reactos/drivers/fs/cdfs/fsctl.c +++ b/reactos/drivers/fs/cdfs/fsctl.c @@ -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)); diff --git a/reactos/drivers/storage/cdrom/cdrom.c b/reactos/drivers/storage/cdrom/cdrom.c index e849a749a08..2a41355a2b0 100644 --- a/reactos/drivers/storage/cdrom/cdrom.c +++ b/reactos/drivers/storage/cdrom/cdrom.c @@ -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 */ diff --git a/reactos/drivers/storage/class2/class2.c b/reactos/drivers/storage/class2/class2.c index 81561dbc908..a76ce6532eb 100644 --- a/reactos/drivers/storage/class2/class2.c +++ b/reactos/drivers/storage/class2/class2.c @@ -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: