Perhaps the only reasonably-documented aspect of the crash dump stack (roughly 1,000 words)1, crash dump filter drivers are the only supported mechanism for modifying the crash dump path. Similar to file system filter drivers in the normal I/O path, crash dump filter drivers allow the component to read and modify I/O requests inline.
As documented on MSDN, a crash dump filter is installed by simply adding its module name to the registry key HKLMSYSTEMCurrentControlSetControlCrashControlDumpFilters. On the next reboot, crashdmp.sys will load the filter driver into the dump stack, just as it does the dump port and miniport driver during pre-initialization. Note that these drivers must conform to kernel mode code digital signature requirements. The call chain below, initiated by the kernel during this phase, summarizes the process:
- crashdmp.sys!DriverEntry() – Crashdmp.sys call table is setup
- The kernel calls crashdmp.sys!CrashdmpInitialize() entry in call table
- crashdmp.sys!LoadFilterDrivers() iterates over the entries in the REG_MULTI_SZ value for the DumpFilters value name in the registry; for each entry, allocates an undocumented filter context structure, loads the filter driver into memory as dump_<filterModuleName>.sys, and links the context structure to the prior list entry via a doubly-linked list.
After loading all of the filter drivers in this manner and storing a pointer to the linked list of filter context structures in a global context structure, crashdmp.sys initializes the filter drivers. This is done in a function called crashdmp.sys!FilterCallback which handles all of the filter operations (Start, Finish, Unload, Read and Write). For an initialization operation, the function initializes the two arguments passed to the filter’s DriverEntry and calls it. Note that crash dump filter drivers are the only drivers in the crash dump stack that are actually invoked (i.e, code in the image is actually executed) during pre-initialization. This is done so that the drivers have a chance to perform initialization that might not be possible during crash mode (such as allocate memory). The documented prototype for a crash filter driver’s DriverEntry routine is:
DriverEntry(__in PFILTER_EXTENSION FilterExtension, __inout FILTER_INITIALIZATION_DATA FilterInitialization);
In its DriverEntry routine, a filter driver is supposed to populate the FilterInitialization structure with pointers to notification callback routines that will be used by crashdmp.sys during crash and hibernation. Crash dump filter drivers can provide up to five callback functions to be notified of I/O activity:
- Dump_Start – This callback is called when a system crash has occurred, just after initializing the crash I/O path and before writing to the dump file
- Dump_Write – This callback is called each time a buffer is about to be written to the dump file
- Dump_Read – This callback is called each time a buffer is read from disk
- Dump_Finish – This callback is called after the dump file has been finalized and written to disk
- Dump_Unload – This callback is called when the dump stack is unloading and allows the filter to release resources
The Dump_Read callback is new in Windows 8. During crashes, it will only be called once when the dump stack log is read from disk (and only if dump stack logging is enabled), since the only purpose of the dump stack during a system crash is to write a crash dump file to disk. During resume from hibernation, the callback will be called much more frequently as hibernation data is read from disk.
Crash dump filter drivers can freely modify data that is read or written through the crash path during a hibernation or crash. The modification can be accomplished in Dump_Read and Dump_Write callbacks (as whole disk encryption filter drivers do to decrypt/encrypt the hibernation and crash dump files). For source code examples of how to modify this data, please refer to the DmpFlt source code.