Thursday, February 11, 2010

Filter Manager Concepts: Part 1 – FLTP_FRAME

Filter Manager's only purpose is to simplify writing file system filters and sometimes it does this by abstracting some of the things that a filter needs to deal with. However, in my experience a good understanding of the mechanisms behind any abstraction is worth having as there usually are some corner cases where abstractions are either broken or unnatural. Also, even though some of the FltMgr's internal structures are not accessible to developers, they might still show up in debugging. So, without further ado, let's go through them one by one:


The FLTP_FRAME structure

A FRAME is a structure that describes a range of altitudes in FltMgr, across all volumes. If there are no legacy filters present, there is only one frame, "Frame 0". If there are some legacy filters present on the system (attached on top of Frame 0), FltMgr might create more frames. They aren’t very interesting for the minifilter writer but still one can see them in the debugger (this is the output on one of my test machines):


0: kd> !fltkd.frames
Frame List: fffff88001ab7380
   FLTP_FRAME: fffff98020692ac0 "Frame 3" "361111111.1 to 421111111.1"
   FLTP_FRAME: fffff9801e04eac0 "Frame 2" "271111111.1 to 361111111.1"
   FLTP_FRAME: fffff9801f7acac0 "Frame 1" "41111111.1 to 271111111.1"
   FLTP_FRAME: fffff98001218ac0 "Frame 0" "0 to 41111111.1"
      FLT_FILTER: fffff980163fe7b0 "PassThrough" "370130"
         FLT_INSTANCE: fffff9801629a6b0 "PassThrough Instance" "370130"
      FLT_FILTER: fffff980082026a0 "luafv" "135000"
         FLT_INSTANCE: fffff980082f84c0 "luafv" "135000"
      FLT_FILTER: fffff980012d2b40 "FileInfo" "45000"
         FLT_INSTANCE: fffff980012e2bb0 "FileInfo" "45000"
         FLT_INSTANCE: fffff9801ec96bb0 "FileInfo" "45000"


One important thing to note is that the frame is a logical unit that has no references to any objects outside itself. Which means that a frame is not aware of the existence of other frames in the system and of any objects in those frames and as such some of the functions that enumerate objects will only show objects inside a certain frame (for example FltGetLowerInstance, FltGetTopInstance, FltGetVolumeInstanceFromName and so on; these functions usually get a parameter that references some other object from which the function can figure out which frame it should look at). This can get in the way when trying to use more than one minifilter for some particular application as it is possible that each minifilter is in a different frame and this might need to be dealt with.


Also, a frame attaches to ALL mounted volumes in the system, which can lead to pretty strange layering:




As you can see, on \Device\HarddiskVolume1 there is only Frame 2 on top of Frame 1 on top of Frame 0. However, on \Device\CdRom0 there is Frame 2 on top of Legacy Filter 2 on top of Frame 1 on top of Frame 0. Currently frames can be created only when a minifilter is registering so it is possible that there are two legacy filters directly on top of one another without a frame between them, but I can't think of any case where that would cause problems.


I guess that's it for tonight. Frames aren't particularly interesting but I had to start somewhere. I also needed some entries on the blog so I can play with formatting :).