Thursday, February 11, 2010

Filter Manager Concepts: Part 7 – IRP_CTRL

One very important structure that everyone writing minifilters very quickly becomes familiar is the FLT_CALLBACK_DATA. This is pretty much the equivalent of an IRP in the minifilter model. The structure is public and is pretty well documented. However, it is in fact just the public part of the picture. Filter manager has an internal structure (the IRP_CTRL) that wraps the FLT_CALLBACK_DATA. So there is a one-to-one relationship between the IRP, the IRP_CTRL and the FLT_CALLBACK_DATA. Let’s see that !fltkd tells us about it:

3: kd> !fltkd.irpctrl fffffa80075ef7d0
IRP_CTRL: fffffa80075ef720  CREATE (0) [00000009] Irp SystemBuffer
Flags                    : [1000000c] DontCopyParms Synchronize FixedAlloc
Irp                      : fffffa8003e6dc60
DeviceObject             : fffffa8004603be0 "\Device\HarddiskVolume1"
FileObject               : fffffa8008437070
CompletionNodeStack      : fffffa80075ef870   Size=2  Next=1
SyncEvent                : (fffffa80075ef738)
InitiatingInstance       : 0000000000000000
Icc                      : fffff8800244f5b0
CreateIrp.NameCacheCtrl  : 0000000000000000
CreateIrp.SavedFsContext : 0000000000000000
CallbackData             : (fffffa80075ef7d0)
 Flags                    : [00000009] Irp SystemBuffer
 Thread                   : fffffa8006b9cb60
 Iopb                     : fffffa80075ef828
 RequestorMode            : [01] UserMode
 IoStatus.Status          : 0x00000000
 IoStatus.Information     : 0000000000000000
 TagData                  : 0000000000000000
 FilterContext[0]         : 0000000000000000
 FilterContext[1]         : 0000000000000000
 FilterContext[2]         : 0000000000000000
 FilterContext[3]         : 0000000000000000
   Cmd     IrpFl   OpFl  CmpFl  Instance FileObjt Completion-Context  Node Adr
--------- -------- ----- -----  -------- -------- ------------------  --------
 [0,0]    00000000  00   0000   0000000000000000 0000000000000000 0000000000000000-0000000000000000   fffffa80075ef8f0
            Args: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000
 [0,0]    00000884  00   0000   fffffa800623a010 fffffa8008437070 fffff88004e5e474-0000000000000000   fffffa80075ef870
            ("luafv","luafv")  luafv!LuafvPostCreate
            Args: fffff8800244f750 0000000001200000 0000000000070000 0000000000000000 0000000000000000 0000000000000000
Working IOPB:
>[0,0]    00000884  00          fffffa800623a010 fffffa8008437070                     fffffa80075ef828
            Args: fffff8800244f750 0000000001200000 0000000000070000 0000000000000000 0000000000000000 0000000000000000
3: kd>

As you can see, a lot of information. The first thing I’d like to point out is there is another extension you could have used to display exactly the same information, !fltkd.cbd. In fact, they are exactly the same function internally and you can pass in the address of an IRP_CTRL or a FLT_CALLBACK_DATA and it’ll figure out what it is and display it. Also, very useful in debugging is the flag ‘1’. I didn’t use in this because it tends to generate a lot of output but try it yourself and you’ll see it displays a lot of good stuff.

This structure is central to filter manager and it is pretty much where the vast majority of my debugging sessions start. Some of the very interesting things you can get using this listing are, of course, the IRP, the InitiatingInstance (who initiated this IO? does it come from the user or was it a minifilter ?) and the Flags of the IRP_CTRL itself.