Intercept and changing SCSI Inquiry command

Hi,
I have this task to change the characteristic of a USB base removable storage device to show up as a “not removable device”.
What I was playing with is to have a filter driver that can intercept SCSI inquiry command and flip the removable bit.
So I wrote a Lower Class filter diver that sits below the disk driver. Since I know the name of my device, I unload the filter driver from all the devices except for the my device.
Now, I can see all the SCSI commands that are sent to my device, except for the first Inquiry command that determines the removable functionality of the device.

My questions are:

  1. Why I can not see the first SCSI Inquiry command?
  2. Is there any other way that I can get rid of the removable characteristic of the device?

Thanks for you help
pada

You wrote:

I have this task to change the characteristic of a USB base removable
storage device to show up as a “not removable device”.

Now, do you understand that this will not actually prevent the device from being removed?

What do you hope to accomplish by this?

Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

I’m trying to make Windows believe that this is a fix disk, rather than a removable disk. This way i.e. the right-click eject will not show up in the drive’s properties and there are also some backup applications that they work better if they think the disk is not removable.

pada

xxxxx@hotmail.com wrote:

My questions are:

  1. Why I can not see the first SCSI Inquiry command?

Because the inquiry commands are generated by scsiport to enumerate the
hba and create the PDOs, thus they will happen before your disk class
lower filter is instantiated.

  1. Is there any other way that I can get rid of the removable characteristic of the device?

Look at the IRP_MN_QUERY_CAPABILITIES PnP IRP.

Paul

Paul Durrant
http://www.linkedin.com/in/pdurrant

If the disk is not marked as removable, data written to the disk won’t be “write through”… which means it will be subject to loss when the drive IS removed by the user.

So long as you understand this, and you’re willing to live with the consequences, you should be able to accomplish what you want to do by filtering the QUERY_CAPABILITIES PnP IRP as suggested by Mr. Durrant.

Sorry for all the warnings, but we’re all just trying to be sure you understand the ramifications of what you’ve asked…

Peter
OSR

Thanks guys,
So In my case that I’m using USB, what driver enumerate the devices?
Is it still scsiport that does that?

pada

In your case, it’s USBSTOR.SYS that does the enumeration, and your filter driver is loading *ABOVE* that, so you’ll never see the commands (including INQUIRYs) that it generates internally while doing enumerations.

As Peter said, it’s best to massage the result of QUERY_CAPABILITIES *if you REALLY, REALLY want to do this.* However, if you ship a product that does this (that is, mark as non-removable a device that is EASILY removable by the end user), you are asking for trouble in terms of data corruption and not-so-mildly-upset end users who have come to expect that they can yank a USB device at any time regardless of the “Safely remove device” mechanism. Hence, the advice of probably all of us: if this is just for experimental purposes, fine; otherwise, please don’t do it.

– Keith

This is just for one specific backup application that does not like removable media.

Now I have a differnt problem.
I did intercept the the QUERY_CAPABILITIES in the IRP_MJ_PNP.
But I when I look at the DEVICE_CAPABILITIES data after my completion function returns, the following data are 0.
irpSp->Parameters.DeviceCapabilities.Capabilities->Removable, irpSp->Parameters.DeviceCapabilities.Capabilities->EjectSupported, irpSp->Parameters.DeviceCapabilities.Capabilities->WarmEjectSupported,

This is how I do it which is very much like the diskperf sample.

What I’m doing wrong?
Pada

/**************/
DispatchPnp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
case IRP_MN_QUERY_CAPABILITIES:
{

status = ForwardIrpSynchronous(DeviceObject, Irp);
KdPrint((“IRP_MN_QUERY_CAPABILITIES %d %d %d %d %d %d %d”, irpSp->Parameters.DeviceCapabilities.Capabilities->Removable, irpSp->Parameters.DeviceCapabilities.Capabilities->EjectSupported, irpSp->Parameters.DeviceCapabilities.Capabilities->WarmEjectSupported));

IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
}

/***********/
NTSTATUS ForwardIrpSynchronous( IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp )

{
PDEVICE_EXTENSION deviceExtension;
KEVENT event;
NTSTATUS status;

KeInitializeEvent(&event, NotificationEvent, FALSE);
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

IoCopyCurrentIrpStackLocationToNext(Irp);

IoSetCompletionRoutine(Irp, IrpCompletion,
&event, TRUE, TRUE, TRUE);

status = IoCallDriver(deviceExtension->TargetDeviceObject, Irp);

// wait for the actual completion

if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, &timeout);
status = Irp->IoStatus.Status;
}

return status;
}

/*****************/

NTSTATUS DiskPerfIrpCompletion( IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)

{
PKEVENT Event = (PKEVENT) Context;
PIO_STACK_LOCATION irpSp1 = IoGetCurrentIrpStackLocation(Irp);

UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(Irp);

KeSetEvent(Event, IO_NO_INCREMENT, FALSE);

return(STATUS_MORE_PROCESSING_REQUIRED);

}

Sorry, I’m stuck on the following statement for the moment.

This is just for one specific backup application that does not like removable media.

Are you saying that you are risking the corruption of a user’s “backup” because of some application that won’t play nicely with removable media? If my understanding is correct, I must strongly urge you against such a solution, as would any user of your product. There has to be a better way (from a business case perspective) to deal with the issue, such as working with the software vendor to get support for removable media.

– Keith

Keith,
I agree with you, but this is for a controlled system and end-users are not involved.

But do you know why data on the QUERY_CAPABILITIES seems to be incorrect? Or am I doing something wrong?

Thanks
Pada

No, it’s not obvious to me what is wrong. I’ve never tried to filter QUERY_CAPABILITIES. In theory, though, if it’s a USB device, the bus driver (PDO) should be setting those fields to reflect removability.

– Keith

>I did intercept the the QUERY_CAPABILITIES in the IRP_MJ_PNP. But I when >I look at the DEVICE_CAPABILITIES data after my completion function >returns, the following data are 0. >irpSp->Parameters.DeviceCapabilities.Capabilities->Removable, irpSp->Pa >rameters.DeviceCapabilities.Capabilities->EjectSupported, irpSp-> >Parameters.DeviceCapabilities.Capabilities->WarmEjectSupported,
Where do intercept QUERY_CAPABILITIES and where/when do you look DEVICE_CAPABILITIES? It is possible that other drivers in your stack could set up Removable bit again.

Igor Sharovar

Sorry for late response.

My filter driver is a lower disk filter driver. I look at the DEVICE_CAPABILITIES in completion routine of the PNP dispatch routine.
My issue is that DEVICE_CAPABILITIES data indicates that my device is not removable. But it actually is removable.

I have posted the code that I’m using earlier in this thread.
Thanks for your help
Payman