So, as explained before, there are two steps to "starting" a minifilter:
- Registering it with FltMgr - This is done by calling FltRegisterFilter() and it is during this time where the FLT_FILTER structure is allocated by FltMgr. When the function returns the system can see the filter but filtering hasn't started yet, no callbacks are being called.
- Starting filtering - This is done in the call to FltStartFiltering() and a minifilter is expected to be ready to process callbacks even before the function returns. This separation is useful for cases where the filter needs to set up some additional things before it's ready to do any work, things that might require some time (for example it might need to create some threads).
- Size - this is pretty obvious, just sizeof(FLT_REGISTRATION).
- Version - this has changed a couple of times. Mainly exists for future compatibility. Look in fltkernel.h if you'd like to see what the versions look like.
- Flags - The values here are documented and pretty easy to understand. Keep in mind that support for NPFS and MSFS is only available for Win8 and newer.
- ContextRegistration - Now we're getting into the tricky bits. This is an array of structures that define which types of contexts the filter will use. This concept of the array of structures might feel a bit strange initially, but it works out great for things that are really sparse. For example there are 7 types of context and most applications only use one or two.
- OperationRegistration - This is also an array of the IRP_MJ operations you want to filter. I generally start with one or two operations (depending on the style of filter) and just keep adding stuff here.
- FilterUnloadCallback - Callback for unloading the filter. If NULL the filter can't be unloaded.
- InstanceSetupCallback - Callback for when an instance gets created.
- InstanceQueryTeardownCallback - Callback to check whether a manual detach should be allowed.
- InstanceTeardownStartCallback - Callback to indicate that the instance will start tearing down.
- InstanceTeardownCompleteCallback - Callback to indicate that the instance has finished tearing down.
- GenerateFileNameCallback - Name provider callback for generating names.
- NormalizeNameComponentCallback - Name provider callback for normalizing names.
- NormalizeContextCleanupCallback - Name provider callback for normalization context cleanup.
- TransactionNotificationCallback - Callback for transaction management.
- NormalizeNameComponentExCallback - Another normalization callback for with better transaction support.
- SectionNotificationCallback - A callback for notifications for sections created by the filter.
- ContextRegistration - for anything other than very trivial filters you'll need some contexts, so this will probably have something.
- OperationRegistration - same here, you can only do very limited stuff (like watching volumes appear and go away) without any operations to monitor. You'll have at least one callback defined here.
- FilterUnloadCallback - you can probably skip this initially but you won't be able to unload the filter. Doesn't matter much if you use a VM for debugging but in general I'd advise creating this callback, even if it doesn't do anything.
- InstanceXxxCallback - you can probably initially skip all these. In my experience it'll be pretty clear when you need to use them.
- XxxNameXxxCallback - unless you're a name provider you can skip all these. You probably shouldn't make your first filter a name provider anyway.
- TransactionNotificationCallback - very likely you can skip this initially.
- SectionNotificationCallback - same here, most likely not necessary.