File System API Hook

This hook is very similar to the way TSRs work in DOS but with a few important differences. The hook interposes itself between the IFS manager and the FSD. The hooker gets control before the FSD is called to perform the function and it can do anything it wants. Hookers can do one of four things when they get called on a hooked call:

  1. Ignore the call and chain on to the previous hooker in the hook chain.
  2. Process the call and return directly to the IFS manager.
  3. Change the call or make multiple calls to the FSD directly, and then return to the IFS manager.
  4. It can call down the chain and do some processing on the way back.

Basically, the hooker has complete control over how it wants to process the call. The hooker gets exactly the same information that the FSD gets, it gets the pointer to the IOREQ structure and can interpret this according to the IFS-FSD interface description given in section 8.5. In addition, it also gets information about the operation that is being performed, the drive or resource on which the operation is being done, the type of resource (for example, net or local), and, on path-based APIs, the codepage that is being used.

The preferred method for hookers to perform other functions while on a hooked call is to use the ring 0 APIs. It is usually quite safe to issue a ring 0 API call while on a file system API hook, the IFS manager is reentrant. There are, however, certain special cases in which the hook cannot make these calls. These restrictions are listed below.

  1. If the call being hooked is issued for a swapfile operation, that is, ir_options contains the R0_SWAPPER_CALL flag, then the call must be processed without reentering the IFS manager via the ring 0 APIs. This can cause additional paging and can lead to a deadlock. Note that multiple calls read/write I/O calls can be made to the FSD, however, the calls must all specify the R0_SWAPPER_CALL flag so that the FSD does special handling for it.
  2. The same restrictions mentioned above also apply to memory-mapped files, that is, read/write I/O operations with the R0_MM_READ_WRITE flag specified in ir_options.

Another important restriction on file system API hookers applies to paging I/O, that is, I/O with the R0_SWAPPER_CALL or R0_MM_READ_WRITE bits set in ir_options. Any code that is executed in the file system hook during paging I/O must be locked down. If the hook causes additional paging activity on a paging I/O, system deadlocks can result. This also means that the code executed during paging I/O cannot perform memory allocations or call any services that can cause paging.

One important difference this hook has when compared to TSRs is that it can be removed at any time, even if there are other hookers after it. For purposes of chaining on, the IFS manager returns a pointer to a variable containing the address of the previous hooker. This double indirection enables the IFS manager to let a hook be removed at any point of time.

File hooks that deregister dynamically need to take care. The IFS manager does not prevent a hook from being deregistered. A hook function that provides crucial functionality that the system or other file hooks depend on cannot deregister itself dynamically. For example, if data encryption is provided by a file hook, the file hook cannot deregister dynamically. Doing so would almost certainly cause a system crash. The same caveat also applies to file hooks that bypass other file hooks beneath them in the chain and call the FSD directly. They need to make sure that there are no other crucial file API hookers beneath that need to process the call as well. The IFS manager does not provide any information about the presence or absence of such crucial file hookers.