RE: File filter hangs on IRP_MJ_CLEANUP .ZwCreate/ZwRead -flags

> * You are using fast mutexes. Using a fast mutex around a Zw* API call is

prohibited because it will raise IRQL above PASSIVE_LEVEL and this will in
turn block the delivery of APCs which are essential to correct I/O
completion. The DDK clearly documents that Zw I/O calls may only be used
at
PASSIVE_LEVEL (and for good reason.)

It is a good idea to NEVER call any complex stuff like ZwCreateFile while
holding a lock. Let’s imagine you need to call a ComplexFunction while
initializing some structure. Then:

  • add the “completely initialized” flag and KEVENT in the structure layout.
  • write the code as the following:
  • grab the lock
  • find the structure in the list
  • if not found - allocate it, put it on the list, set the flag to
    “not completely
    initialized” and the event to non-signaled, set the local
    variables
    AddedByMe to TRUE and MustWait to TRUE
  • if found and the flag is set to “not completely initialized” - set
    AddedByMe to FALSE and MustWait to TRUE
  • if found and the flag is set to “completely initialized” - set
    AddedByMe to FALSE and MustWait to FALSE
  • release the lock
  • if AddedByMe is TRUE - do the ComplexFunction stuff, then
  • grab the lock
  • set the flag to “completely initialized” and signal the event
  • release the lock
  • else if MustWait is TRUE - wait on the event
  • return the structure pointer
    This logic is free from races and does the ComplexFunction call without any
    locks held.
    NT uses this to call IoPageRead in the pagefault path - no MM locks are held
    during the call, and collided faults are handled in race-free way.

Max