General question about lower filter driver and IRP_MJ_SCSI request

Hallo folks,

First of all I am still a beginner at driver developement but it seems that I got a general problem at the moment that may be more about theoretical background information and not about code.

My goal summarized:
I want to be a “lower filter driver” and attach to \Device\Harddisk0\DR0 (the bootdisk) and register to IRP_MJ_SCSI request. The only thing I want to do right now is log some information about the incoming SCSI command blocks and than return to the PDO driver below.

Here is most of my code I have go so far:
extern “C” NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath )
{
NTSTATUS ntStatus;
WCHAR deviceNameBuffer = L"\Device\FLT";
UNICODE_STRING deviceNameUnicodeString = {0};

//WCHAR physicalDevice = L"\DosDevices\PhysicalDrive0";
WCHAR physicalDevice = L"\Device\Harddisk0\DR0";
UNICODE_STRING physicalDeviceUnicodeString = {0};

PFILE_OBJECT fileObject;
PDEVICE_OBJECT targetDevice;
PDEVICE_OBJECT attachedTargetDevice;

NTGuardDriver = DriverObject;

WriteLogFile(“DriverEntry”);

RtlInitUnicodeString (&deviceNameUnicodeString,deviceNameBuffer);

ntStatus = IoCreateDevice (DriverObject,
DEVICE_EXTENSION_SIZE,
&deviceNameUnicodeString,
FILE_DEVICE_NTGUARD,
0,
FALSE,
&NTGuardDevice);

if(!NT_SUCCESS(ntStatus))
return ntStatus;

WriteLogFile(“Device created”);

RtlInitUnicodeString(&physicalDeviceUnicodeString,physicalDevice);

ntStatus = IoGetDeviceObjectPointer(&physicalDeviceUnicodeString,
FILE_READ_ACCESS,
&fileObject,
&targetDevice);

if(!NT_SUCCESS(ntStatus)) {
ObDereferenceObject(fileObject);
return ntStatus;
}

//targetDevice = IoGetDeviceAttachmentBaseRef(fileObject->DeviceObject);

WriteLogFile(“Target”);
PrintDeviceName(targetDevice);

if( ((PDEVICE_EXTENSION)NTGuardDevice->DeviceExtension)->TargetDeviceObject = attachedTargetDevice = IoAttachDeviceToDeviceStack(NTGuardDevice, fileObject->DeviceObject)) {
WriteLogFile("Attaching to ");
PrintDeviceName(attachedTargetDevice);
}

//DriverObject->MajorFunction[IRP_MJ_CREATE] = Guard_Irp_Mj_Create;
//DriverObject->MajorFunction[IRP_MJ_CLEANUP] = Guard_Irp_Mj_Cleanup;
//DriverObject->MajorFunction[IRP_MJ_WRITE] = Guard_Irp_Mj_Write;
//DriverObject->MajorFunction[IRP_MJ_READ] = Guard_Irp_Mj_Read;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = Guard_Irp_Mj_SCSI;
//DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Guard_Irp_Mj_DevCntrl;

//ObDereferenceObject(fileObject);

return ntStatus;
}

NTSTATUS Guard_Irp_Mj_SCSI(PDEVICE_OBJECT HookDevice, IN PIRP Irp) {

WriteLogFile(“SCSI”);

PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
PSCSI_REQUEST_BLOCK Srb = IrpStack->Parameters.Scsi.Srb;

PDEVICE_EXTENSION ext = (PDEVICE_EXTENSION)HookDevice->DeviceExtension;

UCHAR CdbOpCode = ((PCDB)Srb->Cdb)->CDB6GENERIC.OperationCode;

if (CdbOpCode == SCSIOP_READ) {
WriteLogFile(“SCSIOP_READ”);
} else if(CdbOpCode == SCSIOP_WRITE) {
WriteLogFile(“SCSIOP_WRITE”);
} else if(CdbOpCode == SCSIOP_READ_DATA_BUFF) {
WriteLogFile(“SCSIOP_READ_DATA_BUFF”);
} else if(CdbOpCode == SCSIOP_WRITE_DATA_BUFF) {
WriteLogFile(“SCSIOP_WRITE_DATA_BUFF”);
} else {
WriteLogFile(“Unknown SCSIOP”);
}

// some more code to be written when i finally get here :smiley:

return IoCallDriver(ext->TargetDeviceObject, Irp);
}

From what I read this should be enough to get me started but my problem is that I never get into Guard_Irp_Mj_SCSI function.
For testings purpose I was also registering to READ, WRITE, CLEANUP and CREATE but the only functions I got inside where CREATE and CLEANUP.

So actually I got three questions except from why my code is not working:

1.) How can i actually determine to be an upper or a lower filter? The only thing I found on the internet so far was specifiyng by an .inf file.
I always thought it depends on the device I am attaching too, where I get in the stack and therefore lower and upper is just a naming convention where I get attached too.

2.) Is there some general guideline which requests should/can be handled bei either an upper or lower filter?

3.) I had a look at the DiskPerf sample from DDK. Someone said that this example can be either used as volume filter (so I guess upper level) or disk filter (so I guess lower level). This question is probably related to my first and second one but how can the same driver be used for different purposes?

First, a volume filter is just that, a volume filter, it is not a disk upper filter. You need to explicitly set the “LowerFilters” registry key in your inf for the disk class. Your driver is most likely loading as a disk upper filter which does not receive SCSI, it receives IRP_MJ_READ/WRITE. The disk lower filter will receive SCSI.

Also, do not hardcode your device name. While you may think that DR0 is always the boot disk, it is most certainly not. If you have any other storage in the system (PCIE, SAN, etc) your local boot disk may be DR1 DR2 etc.

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@paxi.at
Sent: Tuesday, February 4, 2014 6:40 AM
To: Windows File Systems Devs Interest List
Subject: [ntfsd] General question about lower filter driver and IRP_MJ_SCSI request

Hallo folks,

First of all I am still a beginner at driver developement but it seems that I got a general problem at the moment that may be more about theoretical background information and not about code.

My goal summarized:
I want to be a “lower filter driver” and attach to \Device\Harddisk0\DR0 (the bootdisk) and register to IRP_MJ_SCSI request. The only thing I want to do right now is log some information about the incoming SCSI command blocks and than return to the PDO driver below.

Here is most of my code I have go so far:
extern “C” NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) {
NTSTATUS ntStatus;
WCHAR deviceNameBuffer = L"\Device\FLT";
UNICODE_STRING deviceNameUnicodeString = {0};

//WCHAR physicalDevice = L"\DosDevices\PhysicalDrive0";
WCHAR physicalDevice = L"\Device\Harddisk0\DR0";
UNICODE_STRING physicalDeviceUnicodeString = {0};

PFILE_OBJECT fileObject;
PDEVICE_OBJECT targetDevice;
PDEVICE_OBJECT attachedTargetDevice;

NTGuardDriver = DriverObject;

WriteLogFile(“DriverEntry”);

RtlInitUnicodeString (&deviceNameUnicodeString,deviceNameBuffer);

ntStatus = IoCreateDevice (DriverObject,
DEVICE_EXTENSION_SIZE,
&deviceNameUnicodeString,
FILE_DEVICE_NTGUARD,
0,
FALSE,
&NTGuardDevice);

if(!NT_SUCCESS(ntStatus))
return ntStatus;

WriteLogFile(“Device created”);

RtlInitUnicodeString(&physicalDeviceUnicodeString,physicalDevice);

ntStatus = IoGetDeviceObjectPointer(&physicalDeviceUnicodeString,
FILE_READ_ACCESS,
&fileObject,
&targetDevice);

if(!NT_SUCCESS(ntStatus)) {
ObDereferenceObject(fileObject);
return ntStatus;
}

//targetDevice = IoGetDeviceAttachmentBaseRef(fileObject->DeviceObject);

WriteLogFile(“Target”);
PrintDeviceName(targetDevice);

if( ((PDEVICE_EXTENSION)NTGuardDevice->DeviceExtension)->TargetDeviceObject = attachedTargetDevice = IoAttachDeviceToDeviceStack(NTGuardDevice, fileObject->DeviceObject)) {
WriteLogFile("Attaching to ");
PrintDeviceName(attachedTargetDevice);
}

//DriverObject->MajorFunction[IRP_MJ_CREATE] = Guard_Irp_Mj_Create;
//DriverObject->MajorFunction[IRP_MJ_CLEANUP] = Guard_Irp_Mj_Cleanup;
//DriverObject->MajorFunction[IRP_MJ_WRITE] = Guard_Irp_Mj_Write;
//DriverObject->MajorFunction[IRP_MJ_READ] = Guard_Irp_Mj_Read;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = Guard_Irp_Mj_SCSI;
//DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Guard_Irp_Mj_DevCntrl;

//ObDereferenceObject(fileObject);

return ntStatus;
}

NTSTATUS Guard_Irp_Mj_SCSI(PDEVICE_OBJECT HookDevice, IN PIRP Irp) {

WriteLogFile(“SCSI”);

PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
PSCSI_REQUEST_BLOCK Srb = IrpStack->Parameters.Scsi.Srb;

PDEVICE_EXTENSION ext = (PDEVICE_EXTENSION)HookDevice->DeviceExtension;

UCHAR CdbOpCode = ((PCDB)Srb->Cdb)->CDB6GENERIC.OperationCode;

if (CdbOpCode == SCSIOP_READ) {
WriteLogFile(“SCSIOP_READ”);
} else if(CdbOpCode == SCSIOP_WRITE) {
WriteLogFile(“SCSIOP_WRITE”);
} else if(CdbOpCode == SCSIOP_READ_DATA_BUFF) {
WriteLogFile(“SCSIOP_READ_DATA_BUFF”);
} else if(CdbOpCode == SCSIOP_WRITE_DATA_BUFF) {
WriteLogFile(“SCSIOP_WRITE_DATA_BUFF”);
} else {
WriteLogFile(“Unknown SCSIOP”);
}

// some more code to be written when i finally get here :smiley:

return IoCallDriver(ext->TargetDeviceObject, Irp); }

From what I read this should be enough to get me started but my problem is that I never get into Guard_Irp_Mj_SCSI function.
For testings purpose I was also registering to READ, WRITE, CLEANUP and CREATE but the only functions I got inside where CREATE and CLEANUP.

So actually I got three questions except from why my code is not working:

1.) How can i actually determine to be an upper or a lower filter? The only thing I found on the internet so far was specifiyng by an .inf file.
I always thought it depends on the device I am attaching too, where I get in the stack and therefore lower and upper is just a naming convention where I get attached too.

2.) Is there some general guideline which requests should/can be handled bei either an upper or lower filter?

3.) I had a look at the DiskPerf sample from DDK. Someone said that this example can be either used as volume filter (so I guess upper level) or disk filter (so I guess lower level). This question is probably related to my first and second one but how can the same driver be used for different purposes?


NTFSD is sponsored by OSR

OSR is hiring!! Info at http://www.osr.com/careers

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Being loaded as a disk upper filter and not receiving SCSI sounds like a valid suggestions Thanks for that and your other information first.

But assuming I am attached as an upper filter driver I should at least receive MJ_IRP_READ and MJ_IRP_WRITE. But somehow I only receive MJ_IRP_CREATE and MJ_IRP_CLEANUP.
Can you think of any reason why this is the case?

And about the .inf file. I have to say that the .inf file is really confusing me. Is there some good reference to get me started about the minimum requirement about an .inf file?
I loaded my driver using a service and added it to autostart without an .inf file so far.

You must write a PnP filter instead of this technology of 1990ies.

DiskPerf is the sample.


Maxim S. Shatskih
Microsoft MVP on File System And Storage
xxxxx@storagecraft.com
http://www.storagecraft.com

wrote in message news:xxxxx@ntfsd…
> Hallo folks,
>
> First of all I am still a beginner at driver developement but it seems that I got a general problem at the moment that may be more about theoretical background information and not about code.
>
> My goal summarized:
> I want to be a “lower filter driver” and attach to \Device\Harddisk0\DR0 (the bootdisk) and register to IRP_MJ_SCSI request. The only thing I want to do right now is log some information about the incoming SCSI command blocks and than return to the PDO driver below.
>
> Here is most of my code I have go so far:
> extern “C” NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath )
> {
> NTSTATUS ntStatus;
> WCHAR deviceNameBuffer = L"\Device\FLT";
> UNICODE_STRING deviceNameUnicodeString = {0};
>
> //WCHAR physicalDevice = L"\DosDevices\PhysicalDrive0";
> WCHAR physicalDevice = L"\Device\Harddisk0\DR0";
> UNICODE_STRING physicalDeviceUnicodeString = {0};
>
> PFILE_OBJECT fileObject;
> PDEVICE_OBJECT targetDevice;
> PDEVICE_OBJECT attachedTargetDevice;
>
> NTGuardDriver = DriverObject;
>
> WriteLogFile(“DriverEntry”);
>
> RtlInitUnicodeString (&deviceNameUnicodeString,deviceNameBuffer);
>
> ntStatus = IoCreateDevice (DriverObject,
> DEVICE_EXTENSION_SIZE,
> &deviceNameUnicodeString,
> FILE_DEVICE_NTGUARD,
> 0,
> FALSE,
> &NTGuardDevice);
>
> if(!NT_SUCCESS(ntStatus))
> return ntStatus;
>
> WriteLogFile(“Device created”);
>
> RtlInitUnicodeString(&physicalDeviceUnicodeString,physicalDevice);
>
>
> ntStatus = IoGetDeviceObjectPointer(&physicalDeviceUnicodeString,
> FILE_READ_ACCESS,
> &fileObject,
> &targetDevice);
>
> if(!NT_SUCCESS(ntStatus)) {
> ObDereferenceObject(fileObject);
> return ntStatus;
> }
>
> //targetDevice = IoGetDeviceAttachmentBaseRef(fileObject->DeviceObject);
>
> WriteLogFile(“Target”);
> PrintDeviceName(targetDevice);
>
> if( ((PDEVICE_EXTENSION)NTGuardDevice->DeviceExtension)->TargetDeviceObject = attachedTargetDevice = IoAttachDeviceToDeviceStack(NTGuardDevice, fileObject->DeviceObject)) {
> WriteLogFile("Attaching to ");
> PrintDeviceName(attachedTargetDevice);
> }
>
> //DriverObject->MajorFunction[IRP_MJ_CREATE] = Guard_Irp_Mj_Create;
> //DriverObject->MajorFunction[IRP_MJ_CLEANUP] = Guard_Irp_Mj_Cleanup;
> //DriverObject->MajorFunction[IRP_MJ_WRITE] = Guard_Irp_Mj_Write;
> //DriverObject->MajorFunction[IRP_MJ_READ] = Guard_Irp_Mj_Read;
> DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = Guard_Irp_Mj_SCSI;
> //DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Guard_Irp_Mj_DevCntrl;
>
> //ObDereferenceObject(fileObject);
>
> return ntStatus;
> }
>
> NTSTATUS Guard_Irp_Mj_SCSI(PDEVICE_OBJECT HookDevice, IN PIRP Irp) {
>
> WriteLogFile(“SCSI”);
>
> PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
> PSCSI_REQUEST_BLOCK Srb = IrpStack->Parameters.Scsi.Srb;
>
> PDEVICE_EXTENSION ext = (PDEVICE_EXTENSION)HookDevice->DeviceExtension;
>
> UCHAR CdbOpCode = ((PCDB)Srb->Cdb)->CDB6GENERIC.OperationCode;
>
> if (CdbOpCode == SCSIOP_READ) {
> WriteLogFile(“SCSIOP_READ”);
> } else if(CdbOpCode == SCSIOP_WRITE) {
> WriteLogFile(“SCSIOP_WRITE”);
> } else if(CdbOpCode == SCSIOP_READ_DATA_BUFF) {
> WriteLogFile(“SCSIOP_READ_DATA_BUFF”);
> } else if(CdbOpCode == SCSIOP_WRITE_DATA_BUFF) {
> WriteLogFile(“SCSIOP_WRITE_DATA_BUFF”);
> } else {
> WriteLogFile(“Unknown SCSIOP”);
> }
>
> // some more code to be written when i finally get here :smiley:
>
> return IoCallDriver(ext->TargetDeviceObject, Irp);
> }
>
> From what I read this should be enough to get me started but my problem is that I never get into Guard_Irp_Mj_SCSI function.
> For testings purpose I was also registering to READ, WRITE, CLEANUP and CREATE but the only functions I got inside where CREATE and CLEANUP.
>
> So actually I got three questions except from why my code is not working:
>
> 1.) How can i actually determine to be an upper or a lower filter? The only thing I found on the internet so far was specifiyng by an .inf file.
> I always thought it depends on the device I am attaching too, where I get in the stack and therefore lower and upper is just a naming convention where I get attached too.
>
> 2.) Is there some general guideline which requests should/can be handled bei either an upper or lower filter?
>
> 3.) I had a look at the DiskPerf sample from DDK. Someone said that this example can be either used as volume filter (so I guess upper level) or disk filter (so I guess lower level). This question is probably related to my first and second one but how can the same driver be used for different purposes?
>
>

DiskPerf seems to be a bit heavyweight for what I am looking for.
I will go through the code again the next days and try to learn from it.

But I still would be happy about some suggestions why I am not even receiving READ and WRITE requests with my current code.

> DiskPerf seems to be a bit heavyweight for what I am looking for.

No, it is exactly what you need.


Maxim S. Shatskih
Microsoft MVP on File System And Storage
xxxxx@storagecraft.com
http://www.storagecraft.com

Your question is too generic. At first you were not receiving SCSI, we have no idea what you changed and now you don’t receive READ/WRITE. Are you referring to IRP_MJ_READ? If so, please be specific.

Where is your driver loading? (not where do you think it’s loading, but where is it actually loading) (hint: use windbg !devstack)

IMHO, you should spend some time reading about the Windows driver stack and the difference between a Volume, Partition, Disk, etc. And then learn the difference between a bus, device, port, class, etc. Search these forums for those topics as there are quite a few very good explanations and links to additional documents.

~kenny

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@paxi.at
Sent: Wednesday, February 5, 2014 1:45 AM
To: Windows File Systems Devs Interest List
Subject: RE:[ntfsd] General question about lower filter driver and IRP_MJ_SCSI request

DiskPerf seems to be a bit heavyweight for what I am looking for.
I will go through the code again the next days and try to learn from it.

But I still would be happy about some suggestions why I am not even receiving READ and WRITE requests with my current code.


NTFSD is sponsored by OSR

OSR is hiring!! Info at http://www.osr.com/careers

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Thanks for your input Kenny. I really need to gather some extra information about different types of filter drivers.
My question made up some confusion I guess because I was mixing stuff a bit.
First i wanted to see IRP_MJ_SCSI (in thinking of being a lower filter). As it turned out I?m still attached as upper filter I wanted to at least see IRP_MJ_READ and IRP_MJ_WRITE but I did not receive these messages as well, what somehow confused me.

I made a new start now, compiled the diskperf sample and will modify it for my needs at first.