Drivers can use a DispatchCleanup routine to perform any cleanup operations that are needed after all of the handles to a file object have been closed. Note that DispatchCleanup is called in the process context of the process that closed the final handle; this process might be different from the process that initially opened the handle. (Typically this difference happens because another process uses the DuplicateHandle user-mode routine to duplicate the processes handles.) Drivers that must perform cleanup in the original process context can use the PsSetCreateProcessNotifyRoutine routine to register a callback routine for that purpose, but keep in mind that such callbacks are a limited system resource.
In general, a DispatchCleanup routine must process an IRP_MJ_CLEANUP request by doing the following for every IRP that is currently in the device queue (or in the driver's internal queue of IRPs), for the target device object, and is associated with the file object:
Cancel every IRP that is currently in the queue for the target device object, if the file object that is specified in the driver's I/O stack location of the queued IRP matches the file object that was received in the I/O stack location of the IRP_MJ_CLEANUP request.
Call IoCompleteRequest to complete the IRP, and return STATUS_SUCCESS.
While processing an IRP_MJ_CLEANUP request, a driver can receive additional requests, such as IRP_MJ_READ or IRP_MJ_WRITE. Therefore, a driver that must deallocate resources must also synchronize execution of its DispatchCleanup routine with other dispatch routines, such as DispatchRead and DispatchWrite.