Kernel โ†” User Interface

This document specifies the communication protocol between the kernel-mode minifilter driver and the user-mode monitor application, including port setup, message format, and connection lifecycle.

Related: Communication Architecture ยท Kernel Driver Module ยท Monitor Module ยท Data Types Reference


1. Protocol Overview

flowchart LR
    subgraph Kernel
        Driver["Driver\n(message producer)"]
    end
    
    subgraph Protocol["Filter Communication Port Protocol"]
        Port["\\FsMinifilterPort"]
        direction TB
    end
    
    subgraph User
        Monitor["Monitor\n(message consumer)"]
    end

    Driver -->|"FltSendMessage\n(MINIFILTER_MESSAGE)"| Port
    Port -->|"FilterGetMessage\n(FILTER_MESSAGE)"| Monitor

    style Protocol fill:#4361ee,color:#fff

Direction: Unidirectional (kernel โ†’ user only). The driver does not register a MessageNotifyCallback, so the monitor cannot send messages to the driver.


2. Port Configuration

Driver Side (Server)

FltCreateCommunicationPort(
    g_minifilterHandle,    // Filter handle
    &g_serverPort,         // [out] Server port handle
    &objectAttributes,     // Port name + security
    NULL,                  // No server cookie
    PortConnectCallback,   // Called on client connect
    PortDisconnectCallback,// Called on client disconnect
    NULL,                  // No message callback (unidirectional)
    1                      // MaxConnections = 1
);
Parameter Value Notes
Port Name \FsMinifilterPort NT object namespace
Security FLT_PORT_ALL_ACCESS via FltBuildDefaultSecurityDescriptor Default ACL
Max Connections 1 Single monitor at a time
Message Direction Kernel โ†’ User No MessageNotifyCallback

User Side (Client)

FilterConnectCommunicationPort(
    L"\\FsMinifilterPort",  // Port name
    0,                       // Options
    NULL,                    // Connection context
    0,                       // Context size
    NULL,                    // Security attributes
    &port                    // [out] Port handle
);

3. Message Structures

Kernel-Side Message (Sent)

classDiagram
    class MINIFILTER_MESSAGE {
        +ULONG MessageType
        +ULONG ProcessId
        +WCHAR FilePath[520]
    }
    
    note for MINIFILTER_MESSAGE "Defined in: FsMinifilterCommon.h\nSize: 1048 bytes\nSent via FltSendMessage()"
Field Offset Size Description
MessageType 0 4 bytes Operation type (see message types below)
ProcessId 4 4 bytes PID of the process that initiated the I/O
FilePath 8 1040 bytes Null-terminated NT file path (max 520 WCHARs)
Total ย  1048 bytes ย 

User-Side Message (Received)

classDiagram
    class FILTER_MESSAGE {
        +FILTER_MESSAGE_HEADER Header
        +MINIFILTER_MESSAGE Message
    }
    
    class FILTER_MESSAGE_HEADER {
        +ULONG ReplyLength
        +ULONGLONG MessageId
    }

    FILTER_MESSAGE --> FILTER_MESSAGE_HEADER
    FILTER_MESSAGE --> MINIFILTER_MESSAGE

    note for FILTER_MESSAGE "Defined in: FsMinifilterMonitor/main.cpp\nFilter Manager prepends the header"

The monitor receives FILTER_MESSAGE which includes a FILTER_MESSAGE_HEADER prepended by Filter Manager, followed by the MINIFILTER_MESSAGE payload.


4. Message Types

Constant Value Trigger Filtered To
MSG_TYPE_FILE_CREATE 1 IRP_MJ_CREATE completed successfully .exe, .dll only
MSG_TYPE_FILE_READ 2 IRP_MJ_READ with non-zero length .exe, .dll only
MSG_TYPE_FILE_MODIFY 3 IRP_MJ_WRITE with non-zero length .exe, .dll only
MSG_TYPE_FILE_DELETE 4 IRP_MJ_CLEANUP confirms deletion All files with stream context
flowchart LR
    subgraph KernelEvents["Kernel IRP Events"]
        CREATE["IRP_MJ_CREATE"]
        READ["IRP_MJ_READ"]
        WRITE["IRP_MJ_WRITE"]
        CLEANUP["IRP_MJ_CLEANUP\n(delete confirmed)"]
    end

    subgraph Messages["Message Types"]
        M1["MSG_TYPE_FILE_CREATE (1)"]
        M2["MSG_TYPE_FILE_READ (2)"]
        M3["MSG_TYPE_FILE_MODIFY (3)"]
        M4["MSG_TYPE_FILE_DELETE (4)"]
    end

    CREATE --> M1
    READ --> M2
    WRITE --> M3
    CLEANUP --> M4

    style Messages fill:#4361ee,color:#fff

5. Send Semantics

FltSendMessage Call

FltSendMessage(
    g_minifilterHandle,      // Filter handle
    &g_clientPort,           // Client port pointer
    &message,                // MINIFILTER_MESSAGE buffer
    sizeof(MINIFILTER_MESSAGE), // Message size
    NULL,                    // No reply buffer
    &replyLength,            // Reply length = 0
    &timeout                 // 100ms timeout
);
Behavior Detail
Blocking Waits up to 100ms for the monitor to receive
Timeout handling STATUS_TIMEOUT is silently converted to STATUS_SUCCESS
No reply Reply buffer is NULL, replyLength = 0
Disconnected Returns STATUS_PORT_DISCONNECTED if g_clientPort == NULL
Thread context Called from the I/O thread; 100ms timeout limits impact

FilterGetMessage Call

FilterGetMessage(
    port,                    // Port handle
    &message.Header,         // Output buffer (FILTER_MESSAGE)
    sizeof(FILTER_MESSAGE),  // Buffer size
    NULL                     // No overlapped (synchronous)
);
Behavior Detail
Blocking Blocks until a message arrives
Synchronous No overlapped I/O (NULL parameter)
Error Returns HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE) on disconnection

6. Connection Lifecycle Callbacks

PortConnectCallback

Called by Filter Manager when a user-mode client connects.

Action Code
Store client port g_clientPort = ClientPort
Record monitor PID g_clientProcessId = HandleToULong(PsGetCurrentProcessId())
Set connection cookie *ConnectionCookie = NULL

PortDisconnectCallback

Called by Filter Manager when the client disconnects or the port is closed.

Action Code
Clear monitor PID g_clientProcessId = 0
Close client port FltCloseClientPort(g_minifilterHandle, &g_clientPort)
Clear port pointer g_clientPort = NULL

7. Error Codes

Status Meaning Handling
STATUS_SUCCESS Message delivered Continue
STATUS_TIMEOUT Monitor didnโ€™t receive within 100ms Ignored (treated as success)
STATUS_PORT_DISCONNECTED No client connected Early return, no send attempt
HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE) (User-side) Driver disconnected Monitor exits message loop

Next Steps