Asking about filtering target LBA of an I/O request

Hi. I'm currently making a software similar to linux's iowatcher in Windows, and is making a filter driver to filter I/O requests.
Since I'm making recreating iowatcher, I need to know which LBA is the target of the request and the length in blocks.
Currently, I'm filtering from \Filesystem\FltMgr with IRP_MJ_READ and IRP_MJ_WRITE packets handled, but I don't think the packet contains the LBA for I/O.

My question is: to which device should I attach in order to filter IRP packets containing LBA and read/write length?
Thank you in advance.

LBAs are present in the SRBs sent from the storage class drivers to the storage port drivers. So you need to filter IRP_MJ_SCSI either as a lower filter driver for disk devices or an upper filter for storage port devices.

1 Like

Thanks for the reply.

This got me thinking about something:

  1. I'm using NVMe in my VM.
    Does disks with NVMe also use IRP_MJ_SCSI?

  2. For storage port devices, would \Device\RaidPortX or \Device\IdePortX be sufficient?

The storage class drivers don't care what type of adapter they are communicating with, they just send IRP_MJ_SCSI Irps containing an SRB.

The architecture is described here: Windows Storage Driver Architecture - Windows drivers | Microsoft Learn

A disk class lower filter driver would attach to all disk devices and allow you to filter all the SRB's going through.

1 Like

Thanks alot.

I'll try to add the lower filter device tomorrow, and ask some question if needed.

Okay. I've made the lower filter driver for the storage class driver, and am experiencing some problems.
Apparently, the driver seems to be causing access violation.
This is the stack trace:

1: kd> kb
 # RetAddr               : Args to Child                                                           : Call Site
00 fffff805`f049697e     : fffff805`85807a70 fffff805`857b824c ffff8208`152e7b90 ffff8208`159031b0 : 0x0
01 fffff805`8580dd8e     : ffff8208`15903a20 fffff805`f106c400 00000000`00001001 00000000`00000fff : nt!IofCallDriver+0xbe
02 fffff805`857b510a     : ffff8cc3`005000b0 00000000`00000000 ffff8208`15903a20 00000058`00140016 : CLASSPNP!ClassDispatchPnp+0x17e
03 fffff805`f049697e     : ffffba8b`278075b0 fffff805`f0d310d1 00000000`00000000 00000000`00000000 : CLASSPNP!ClassGlobalDispatch+0x3a
04 fffff805`82aa48eb     : 00000000`00000100 ffff8208`15903a20 00000000`00000000 ffff8208`15904040 : nt!IofCallDriver+0xbe
05 fffff805`82a83bb1     : ffff8208`15903a20 00000000`00000000 ffff8208`15904040 ffff8208`13844e10 : partmgr!PmPnp+0x8b
06 fffff805`f049697e     : ffff8208`15904040 ffffaa06`b4806590 00000000`00000020 00000000`69706e04 : partmgr!PmGlobalDispatch+0x101
07 fffff805`f0af7cb0     : ffff8208`15904040 00000000`00000000 ffffaa06`b4806590 ffff8208`13fb23c0 : nt!IofCallDriver+0xbe
08 fffff805`f0bb0f9a     : ffff8208`13fb2584 ffffaa06`b48066f0 ffff8208`151e2050 ffff8208`13fb2580 : nt!IopSynchronousCall+0xf8
09 fffff805`f0bb0bf7     : ffff8208`13fb2584 00000000`00000000 ffffaa06`b48066f0 ffff8208`13fb2580 : nt!IopQueryLegacyBusInformation+0x62
0a fffff805`f08f3084     : 00000000`00000000 ffff8208`13fb23c0 ffff8208`13fb23c0 ffffba8b`276818e0 : nt!PipCallDriverAddDevice+0x8af
0b fffff805`f0ddea1b     : 00000000`00000000 ffffba8b`27807710 00000000`00000000 00000000`00000000 : nt!PiProcessAddBootDevices+0x60
0c fffff805`f08f1d65     : 00000000`00000001 ffffaa06`b4806870 ffffba8b`276818e0 fffff805`f0bdacb8 : nt!PipAddDevicesToBootDriverWorker+0x23
0d fffff805`f0ddd190     : ffffffff`800002c8 ffffba8b`276739d0 ffff8208`00000092 ffffba8b`00000078 : nt!PipApplyFunctionToServiceInstances+0x1c5
0e fffff805`f0dda06c     : 00000000`00000006 00000000`00000006 00000000`00000010 fffff805`7cd4c3a0 : nt!IopInitializeBootDrivers+0x5ac
0f fffff805`f0dd90bf     : fffff805`85ab2fc0 fffff805`7cd4c3a0 fffff805`f08ca6f0 fffff805`7cd4c300 : nt!IoInitSystemPreDrivers+0xf40
10 fffff805`f08ca72b     : fffff805`f08ca6f0 fffff805`f118b9f0 fffff805`f08ca6f0 fffff805`7cd4c3a0 : nt!IoInitSystem+0x17
11 fffff805`f065904a     : ffff8208`1369b100 fffff805`f08ca6f0 608b8b4c`000000f4 0f41c78a`44000003 : nt!Phase1Initialization+0x3b
12 fffff805`f08741c4     : fffff805`7d0fb180 ffff8208`1369b100 fffff805`f0658ff0 e0ba0f48`00000698 : nt!PspSystemThreadStartup+0x5a
13 00000000`00000000     : ffffaa06`b4807000 ffffaa06`b4801000 00000000`00000000 00000000`00000000 : nt!KiStartSystemThread+0x34

May I ask you about some directions as to how to debug this error?

Apparently, the arguments passed to 0x0 matched the arguments of the routine that goes into IoSetCompletionRoutine.

NTSTATUS
WINIOWATCHER_DispatchDefault(
	PDEVICE_OBJECT	DeviceObject,
	PIRP			Irp
)
{
	PDEVICE_EXTENSION	Ext;

	Ext = DeviceObject->DeviceExtension;

	IoCopyCurrentIrpStackLocationToNext(Irp);
	IoSetCompletionRoutine(
		Irp,
		CompletionRoutine,
		NULL,
		TRUE,
		TRUE,
		TRUE
	);
	return IoCallDriver(Ext->LowerDeviceObject, Irp);
}

This is my dispatch function. Is there something missing?

  1. Use the windbg command !analyze -v with correct symbols set up.
  2. Set a breakpoint in your WINIOWATCHER_DispatchDefault routine and step through it.

Why are you not using KMDF for this driver? It would make your life much simpler.

1 Like

Unfortunately, I was not able to find any useful resources related to KMDF in my country, so I had to stick to this.
Anyway, I'll try to set some breakpoints and debug the driver.

Okay. I found the problem.

I forgot to register the major function for function number 0x1b.

//            ↓ this had to be <=
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
{
	if (DriverObject->MajorFunction[i] == NULL)
		DriverObject->MajorFunction[i] = WINIOWATCHER_DispatchDefault;
}

Now I can successfully boot the OS.
Thanks a lot for your help!