16.7 Handling Removable Media

NT file systems and removable-media device drivers share the responsibility for ensuring that the correct media is mounted when a file is opened on a removable-media device and that the correct media remains mounted during operations that access the media. Any NT intermediate driver layered between such a file system and removable-media device driver also shares this responsiblity.

Responding to FS-Initiated Check-Verify Requests

At its discretion, the file system can send an IRP to the device driver’s Dispatch entry point for IRP_MJ_DEVICE_CONTROL requests with Parameters.DeviceIoControl.IoControlCode in the I/O stack location set to the following:

IOCTL_XXX_CHECK_VERIFY
where XXX  is the type of device, such as DISK, TAPE, or CDROM.

The type DISK includes both unpartitionable (floppy) and partitionable removable-media devices.

If the underlying device driver determines that the media has not changed, the driver should complete the IRP, returning the IoStatus block with the following values:

Status

set to STATUS_SUCCESS

Information

set to zero

In addition, if the device type is DISK or CDROM and the caller specified an output buffer, the driver returns the media change count in the buffer at
Irp->AssociatedSystemBuffer and sets IoStatus.Information to sizeof(ULONG). By returning this count the driver gives the caller an opportunity to determine whether the media has changed from its perspective.

If the underlying device driver determines that the media has changed, it should do the following:

Notifying the File System of Possible Media Changes

An NT removable-media device driver must ensure that the media is not changed for the device represented by the DeviceObject (input to every driver routine that is sent an IRP) whenever the driver processes an IRP that requests a transfer to/from the media or a device I/O control operation that affects the media. The best possible time to check for changed media is just after the transition from a no-media-present state to a media-present state if the physical device always notifies the driver about these state changes.

If its physical device indicates that the state of the media might have changed before the driver begins an I/O operation or during an operation, the driver must do the following:

  1. Ensure that the volume is mounted by checking the VPB_MOUNTED flag in the VPB. (If the volume is not mounted, the driver must not set the DO_VERIFY_VOLUME bit. The driver should set IoStatus.Status to STATUS_VERIFY_REQUIRED, set IoStatus.Information to zero, and call IoCompleteRequest with the IRP.)

  2. Set the Flags in the DeviceObject by ORing Flags with DO_VERIFY_VOLUME.

  3. Set the IoStatus block in the IRP to the following:

    Status            STATUS_VERIFY_REQUIRED

    Information        zero

  4. Before completing any IRP with an IoStatus block in which the Status field is not set to STATUS_SUCCESS, the driver must call IoIsErrorUserInduced, which returns a Boolean TRUE for any of the following Status values:

    STATUS_VERIFY_REQUIRED
    STATUS_NO_MEDIA_IN_DEVICE
    STATUS_WRONG_VOLUME
    STATUS_UNRECOGNIZED_MEDIA
    STATUS_MEDIA_WRITE_PROTECTED
    STATUS_IO_TIMEOUT
    STATUS_DEVICE_NOT_READY

    If IoIsErrorUserInduced returns TRUE, the driver must call IoSetHardErrorOrVerifyDevice so the FSD can send a popup to the user, who can then supply the correct media, decide to retry the original request, or decide to cancel the requested operation.

Checking the DeviceObject->Flags

For each IRP requesting an I/O operation to/from removable media, a removable-media device driver must determine whether DO_VERIFY_VOLUME is already set in its DeviceObject->Flags. If this value is set, the driver must do the following:

Otherwise, if a removable-media device driver neglects to fail IRPs when DO_VERIFY_VOLUME is set and SL_OVERRIDE_VERIFY_VOLUME is not set for the preceding transfer requests, the file system can neither maintain the integrity of cached file data nor cause the user to be prompted to remount the media that holds an open file.

Setting up IRPs in Intermediate Drivers

Any intermediate driver layered between an NT file system driver and a removable-media device driver must set up the next-lower-level driver’s I/O stack location in IRPs. From incoming IRP_MJ_READ, IRP_MJ_WRITE, and IRP_MJ_DEVICE_CONTROL requests, such an intermediate driver must copy its own I/O stack location Flags into the next-lower-level driver’s I/O stack location when it sets up the I/O stack location for the lower driver.

If such an intermediate driver allocates new IRPs for lower-level removable-media drivers, it must set up the IRPs it allocates as follows:

Otherwise, the file system can neither maintain the integrity of cached file data nor cause the user to be prompted to remount the media that holds an open file.