Kernel Driver Module
Detailed documentation of the
WindowsFileSystemMinifilter.syskernel driver β source files, callback implementations, context management, and communication port handling.
Related: Driver Architecture Β· File Interception Flow Β· Driver Lifecycle Β· Kernel β User Interface
1. Source Files
| File | Purpose |
|---|---|
Windows File System Minifilter/main.cpp |
DriverEntry β initialization, registration, port creation |
Windows File System Minifilter/FsMinifilter.cpp |
All callback implementations (860+ lines) |
Windows File System Minifilter/FsMinifilter.h |
Stream context struct, function declarations, globals |
Windows File System Minifilter/FsMinifilterCommon.h |
Shared message types and structures (kernel β user) |
WindowsFileSystemMinifilter.inf |
Driver installation INF file |
2. Module Architecture
classDiagram
class DriverEntry {
+FltRegisterFilter()
+FltCreateCommunicationPort()
+FltStartFiltering()
}
class CallbackHandlers {
+PreOperationCreate()
+PostOperationCreate()
+PreOperationRead()
+PreOperationWrite()
+PreOperationSetInfo()
+PostOperationSetInfo()
+PreOperationCleanup()
+PostOperationCleanup()
}
class InstanceCallbacks {
+InstanceFilterUnloadCallback()
+InstanceSetupCallback()
+InstanceQueryTeardownCallback()
}
class PortCallbacks {
+PortConnectCallback()
+PortDisconnectCallback()
}
class Helpers {
+IsTargetExtension()
+SendMessageToUserMode()
+GetOrSetStreamContext()
+StreamContextCleanupCallback()
}
class Globals {
+PFLT_FILTER g_minifilterHandle
+PFLT_PORT g_serverPort
+PFLT_PORT g_clientPort
+ULONG g_clientProcessId
}
DriverEntry --> CallbackHandlers : registers
DriverEntry --> InstanceCallbacks : registers
DriverEntry --> PortCallbacks : registers
CallbackHandlers --> Helpers : calls
CallbackHandlers --> Globals : reads/writes
PortCallbacks --> Globals : reads/writes
3. Global State
| Variable | Type | Initialized | Modified By |
|---|---|---|---|
g_minifilterHandle |
PFLT_FILTER |
DriverEntry |
InstanceFilterUnloadCallback (set to NULL after unregister) |
g_serverPort |
PFLT_PORT |
DriverEntry |
InstanceFilterUnloadCallback (closed) |
g_clientPort |
PFLT_PORT |
PortConnectCallback |
PortDisconnectCallback (set to NULL) |
g_clientProcessId |
ULONG |
PortConnectCallback |
PortDisconnectCallback (set to 0) |
Thread Safety: g_clientPort is read by all callback threads and written only by the single-threaded port callbacks. The driver assumes atomic pointer reads on the target architecture. g_clientProcessId is similarly safe because itβs a 32-bit value on all platforms.
4. Callback Implementation Details
4.1 PreOperationCreate / PostOperationCreate
Purpose: Detect new file opens and track FILE_DELETE_ON_CLOSE.
Pre-op logic:
- Check if
FILE_DELETE_ON_CLOSEflag is set inCreate.Options - If yes: allocate a
FS_STREAM_CONTEXT, pass it viaCompletionContext, returnFLT_PREOP_SYNCHRONIZE - If no: return
FLT_PREOP_SUCCESS_WITH_CALLBACK
Post-op logic:
- Skip if create failed or returned
STATUS_REPARSE - Get normalized file name via
FltGetFileNameInformation - If target extension and not self-PID β
SendMessageToUserMode(MSG_TYPE_FILE_CREATE) - If stream context was passed from pre-op β attach it via
FltSetStreamContext, markDeleteOnClose = TRUE
4.2 PreOperationRead
Purpose: Monitor read access to .exe/.dll files.
Single pre-op callback, no post-op needed:
- Quick rejection: no client, zero-length read, self-PID
- Get file name, check extension
- Send
MSG_TYPE_FILE_READ
4.3 PreOperationWrite
Purpose: Monitor write/modification of .exe/.dll files.
Identical structure to PreOperationRead, sends MSG_TYPE_FILE_MODIFY.
4.4 PreOperationSetInfo / PostOperationSetInfo
Purpose: Track delete disposition changes for accurate delete detection.
Pre-op logic:
- Only handle
FileDispositionInformationandFileDispositionInformationEx - Get or create stream context via
GetOrSetStreamContext - Increment
NumOpsatomically for race detection - If
NumOps == 1: pass context to post-op viaFLT_PREOP_SYNCHRONIZE - If
NumOps > 1: racing operations detected, release context
Post-op logic:
- If operation succeeded, update
SetDisporDeleteOnClosebased on the info class - Handle both legacy
FileDispositionInformationand modernFileDispositionInformationExwithFILE_DISPOSITION_ON_CLOSEflag - Decrement
NumOpsatomically
4.5 PreOperationCleanup / PostOperationCleanup
Purpose: Confirm actual file deletion and send notification.
Pre-op: Attempt to get existing stream context. If found, synchronize for post-op.
Post-op:
- Check if
SetDisp,DeleteOnClose, orNumOps > 0 - If delete candidate β
FltQueryInformationFile(FileStandardInformation) - If returns
STATUS_FILE_DELETEDβ confirm deletion InterlockedIncrement(IsNotified)β only send notification if this is the first increment (value becomes 1)- Send
MSG_TYPE_FILE_DELETEwith file path and PID
5. Helper Functions
IsTargetExtension
BOOLEAN IsTargetExtension(PCUNICODE_STRING FileName)
Case-insensitive check for .exe and .dll extensions. Operates directly on the UNICODE_STRING buffer without allocating memory.
Algorithm: Check last 4 characters of the filename against .exe and .dll using character-by-character comparison with upper/lower variants.
SendMessageToUserMode
NTSTATUS SendMessageToUserMode(ULONG MessageType, PCUNICODE_STRING FilePath, ULONG ProcessId)
Sends a MINIFILTER_MESSAGE to the connected user-mode monitor.
- Timeout: 100ms (relative) β prevents blocking the I/O path
- No reply expected:
replyLength = 0, reply buffer is NULL - Timeout tolerance:
STATUS_TIMEOUTis silently converted toSTATUS_SUCCESS - Disconnection check: Returns
STATUS_PORT_DISCONNECTEDimmediately ifg_clientPort == NULL
GetOrSetStreamContext
NTSTATUS GetOrSetStreamContext(PCFLT_RELATED_OBJECTS, PFILE_OBJECT, PFS_STREAM_CONTEXT*)
Race-safe context acquisition pattern:
- Try
FltGetStreamContextβ if found, return existing - If
STATUS_NOT_FOUNDβ allocate new context - Try
FltSetStreamContextwithFLT_SET_CONTEXT_KEEP_IF_EXISTS - If
STATUS_FLT_CONTEXT_ALREADY_DEFINEDβ another thread beat us, use the existing one
6. Port Callbacks
PortConnectCallback
Called when FsMinifilterMonitor.exe connects:
- Stores the client port handle in
g_clientPort - Records the monitorβs PID via
PsGetCurrentProcessId()intog_clientProcessId - Sets
*ConnectionCookie = NULL(no cookie needed)
PortDisconnectCallback
Called when the monitor disconnects or exits:
- Resets
g_clientProcessId = 0 - Closes client port via
FltCloseClientPort - Sets
g_clientPort = NULL
7. Build Configuration
| Setting | Value |
|---|---|
| Driver Type | KMDF (file system minifilter) |
| Target OS | Windows 10+ |
| Architectures | ARM64, x64 |
| Configurations | Debug, Release |
| Dependencies | FltMgr (Filter Manager) |
| INF Class | Bottom |
| Catalog | windowsfilesystemminifilter.cat |
Next Steps
- See callback execution in action: File Interception Flow
- See the message format: Kernel β User Interface
- See the monitor that receives these messages: Monitor Module