Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Home NTFSD
Before Posting...
Please check out the Community Guidelines in the Announcements and Administration Category.

More Info on Driver Writing and Debugging


The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.


Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/


minifilter callbacks routines sometimes not calling

johnhouldingjohnhoulding Member Posts: 28
edited January 13 in NTFSD

I have minifilter which intercept create or rename operation (only for exe file). So I have these callback routines. PreCreate + PostCreate, PreWrite, PreCleanup + PostCleanup.
in postcreate i create stream handle context for newly created exe file and copy filename to context. in PreWrite if NT_SUCCESS(FltGetStreamHandleContext) I set context->rescan = TRUE and return FLT_PREOP_SUCCESS_WITH_CALLBACK. Then in PreCleanup if NT_SUCCESS(FltGetStreamHandleContext) I return FLT_PREOP_SYNCHRONIZE. And in postCleanup i send filename to user mode app with FltSendMessage .Actually it works but sometimes I didnt see filename in my usermode app. İt occur randomly and it also occur IRP_MJ_SET_INFORMATION PreSetInformation. In my usermode app with FltGetMessage i get filename and open this file then read and close + call Sleep(2000) for testing. When I create new exe file and during usermode Sleep(2000) rename other file I didnt see renamed filename and vice versa.

I put my source code here maybe someone help me?

FLT_PREOP_CALLBACK_STATUS
ScannerPreCreate(
    _Inout_ PFLT_CALLBACK_DATA Data,
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _Flt_CompletionContext_Outptr_ PVOID* CompletionContext
)
{
    UNREFERENCED_PARAMETER(FltObjects);
    UNREFERENCED_PARAMETER(CompletionContext = NULL);



    if (IoThreadToProcess(Data->Thread) == ScannerData.UserProcess) {


        return FLT_PREOP_SUCCESS_NO_CALLBACK;
    }

    return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}



FLT_POSTOP_CALLBACK_STATUS ScannerPostOpCreate(PFLT_CALLBACK_DATA Data,
    PCFLT_RELATED_OBJECTS FltObjects,
    PVOID CompletionContext,
    FLT_POST_OPERATION_FLAGS Flags)
{

    PFLT_FILE_NAME_INFORMATION FileNameInfo = NULL;
    POBJECT_NAME_INFORMATION name = NULL;
    NTSTATUS status;
    PSCANNER_NOTIFICATION notification = NULL;
    ULONG replyLen = 0;
    UNICODE_STRING extension = RTL_CONSTANT_STRING(L"exe");
    PSCANNER_CONTEXT scannerContext = NULL;



    if (!NT_SUCCESS(Data->IoStatus.Status) ||
        (STATUS_REPARSE == Data->IoStatus.Status)) {
        return FLT_POSTOP_FINISHED_PROCESSING;
    }


    if (ScannerData.ClientPort == NULL)
    {
        return FLT_POSTOP_FINISHED_PROCESSING;
    }

    status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &FileNameInfo);
    if (!NT_SUCCESS(status))
    {
        return FLT_POSTOP_FINISHED_PROCESSING;
    }


    status = FltParseFileNameInformation(FileNameInfo);
    if (!NT_SUCCESS(status))
    {
        FltReleaseFileNameInformation(FileNameInfo);
        return FLT_POSTOP_FINISHED_PROCESSING;
    }

    if (FileNameInfo->Extension.Length == 0)
    {
        FltReleaseFileNameInformation(FileNameInfo);
        return FLT_POSTOP_FINISHED_PROCESSING;
    }


    if (RtlCompareUnicodeString(&extension, &FileNameInfo->Extension, TRUE) != 0)
    {
        FltReleaseFileNameInformation(FileNameInfo);
        return FLT_POSTOP_FINISHED_PROCESSING;
    }

    FltReleaseFileNameInformation(FileNameInfo);

    if (FltObjects->FileObject->WriteAccess)
    {

        status = IoQueryFileDosDeviceName(FltObjects->FileObject, &name);
        if (NT_SUCCESS(status))
        {

            status = FltAllocateContext(ScannerData.Filter,
                FLT_STREAMHANDLE_CONTEXT,
                sizeof(SCANNER_CONTEXT),
                NonPagedPool,
                &scannerContext);

            if (NT_SUCCESS(status))
            {
                RtlCopyMemory(scannerContext->Path, name->Name.Buffer, name->Name.MaximumLength);
                scannerContext->Len = name->Name.MaximumLength;
                scannerContext->Rescan = FALSE;

                status = FltSetStreamHandleContext(FltObjects->Instance,
                    FltObjects->FileObject,
                    FLT_SET_CONTEXT_REPLACE_IF_EXISTS,
                    scannerContext,
                    NULL);

                if (!NT_SUCCESS(status))
                {
                    DbgPrint("Error set setram context");
                    FltReleaseContext(scannerContext);
                    ExFreePool(name);
                    return FLT_POSTOP_FINISHED_PROCESSING;
                }

                DbgPrint("Context yaradildi\n");


                FltReleaseContext(scannerContext);

            }
            else {
                DbgPrint("Cant allocate memory\n");
            }



            ExFreePool(name);
        }

    }

    return FLT_POSTOP_FINISHED_PROCESSING;
}

FLT_PREOP_CALLBACK_STATUS
ScannerPreWrite(
    _Inout_ PFLT_CALLBACK_DATA Data,
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _Flt_CompletionContext_Outptr_ PVOID* CompletionContext
)
{

    NTSTATUS status;
    PSCANNER_CONTEXT scannerContext = NULL;
    /*POBJECT_NAME_INFORMATION name = NULL;*/


    status = FltGetStreamHandleContext(FltObjects->Instance, FltObjects->FileObject, &scannerContext);
    if (NT_SUCCESS(status))
    {

        if (scannerContext->Rescan == FALSE)
        {
            scannerContext->Rescan = TRUE;

            FltSetStreamHandleContext(FltObjects->Instance, FltObjects->FileObject, FLT_SET_CONTEXT_REPLACE_IF_EXISTS, scannerContext, NULL);

            FltReleaseContext(scannerContext);

            return FLT_PREOP_SUCCESS_WITH_CALLBACK;
        }


        FltReleaseContext(scannerContext);

    }

    return FLT_PREOP_SUCCESS_NO_CALLBACK;
}


FLT_PREOP_CALLBACK_STATUS
ScannerPreCleanup(
    _Inout_ PFLT_CALLBACK_DATA Data,
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _Flt_CompletionContext_Outptr_ PVOID* CompletionContext
)
{
    NTSTATUS status;
    PSCANNER_CONTEXT scannerContext = NULL;

    status = FltGetStreamHandleContext(FltObjects->Instance, FltObjects->FileObject, &scannerContext);
    if (!NT_SUCCESS(status))
    {
        return FLT_PREOP_SUCCESS_NO_CALLBACK;
    }



    FltReleaseContext(scannerContext);

    return FLT_PREOP_SYNCHRONIZE;
}





FLT_POSTOP_CALLBACK_STATUS ScannerPostCleanup(PFLT_CALLBACK_DATA Data,
    PCFLT_RELATED_OBJECTS FltObjects,
    PVOID CompletionContext,
    FLT_POST_OPERATION_FLAGS Flags)
{
    NTSTATUS status;
    PSCANNER_CONTEXT scannerContext = NULL;
    PSCANNER_NOTIFICATION notification = NULL;
    ULONG replyLen = 0;


    if (ScannerData.ClientPort == NULL)
    {
        return FLT_POSTOP_FINISHED_PROCESSING;
    }


    status = FltGetStreamHandleContext(FltObjects->Instance, FltObjects->FileObject, &scannerContext);
    if (NT_SUCCESS(status))
    {
        if (scannerContext->Rescan == TRUE)
        {
            notification = ExAllocatePoolWithTag(NonPagedPool, sizeof(SCANNER_NOTIFICATION), 'X66');
            if (notification == NULL)
            {
                FltReleaseContext(scannerContext);
                return FLT_POSTOP_FINISHED_PROCESSING;;
            }

            replyLen = sizeof(SCANNER_REPLY);

            RtlCopyMemory(notification->PathName, scannerContext->Path, scannerContext->Len);

            status = FltSendMessage(ScannerData.Filter,
                &ScannerData.ClientPort,
                notification,
                sizeof(SCANNER_NOTIFICATION),
                notification,
                &replyLen,
                NULL
            );

            if (!NT_SUCCESS(status))
            {
                DbgPrint("Error FltSendMessage\n");
            }

            ExFreePoolWithTag(notification, 'X66');

        }

        scannerContext->Rescan = FALSE;

        FltSetStreamHandleContext(FltObjects->Instance, FltObjects->FileObject, FLT_SET_CONTEXT_REPLACE_IF_EXISTS, scannerContext, NULL);


        FltReleaseContext(scannerContext);
    }


    return FLT_POSTOP_FINISHED_PROCESSING;
}



FLT_PREOP_CALLBACK_STATUS  ScannerPreSetInformation(
    PFLT_CALLBACK_DATA Data,
    PCFLT_RELATED_OBJECTS FltObjects,
    PVOID CompletionContext
)
{
    NTSTATUS status = FLT_PREOP_SUCCESS_NO_CALLBACK;
    PFILE_RENAME_INFORMATION renameInfo = NULL;
    PFLT_FILE_NAME_INFORMATION FileNameInfo = NULL;
    PSCANNER_CONTEXT scannerContext = NULL;
    PSCANNER_NOTIFICATION notification = NULL;
    ULONG replyLen = 0;
    UNICODE_STRING extension = RTL_CONSTANT_STRING(L"exe");

    if (FltObjects->FileObject == NULL)
    {
        return status;
    }


    if (Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileRenameInformation ||
        Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileRenameInformationEx)
    {

        renameInfo = Data->Iopb->Parameters.SetFileInformation.InfoBuffer;


        status = FltGetDestinationFileNameInformation(FltObjects->Instance,
            FltObjects->FileObject,
            renameInfo->RootDirectory,
            renameInfo->FileName,
            renameInfo->FileNameLength,
            FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT,
            &FileNameInfo);

        if (NT_SUCCESS(status))
        {

            FltParseFileNameInformation(FileNameInfo);


            if (FileNameInfo->Extension.Length == 0)
            {
                FltReleaseFileNameInformation(FileNameInfo);
                return FLT_PREOP_SUCCESS_NO_CALLBACK;
            }


            if (RtlCompareUnicodeString(&extension, &FileNameInfo->Extension, TRUE) != 0)
            {
                FltReleaseFileNameInformation(FileNameInfo);
                return FLT_PREOP_SUCCESS_NO_CALLBACK;
            }


            /*DbgPrint("%wZ\n", FileNameInfo->Name);*/

            notification = ExAllocatePoolWithTag(NonPagedPool, sizeof(SCANNER_NOTIFICATION), 'X66');
            if (notification == NULL)
            {
                FltReleaseFileNameInformation(FileNameInfo);
                return FLT_PREOP_SUCCESS_NO_CALLBACK;
            }

            replyLen = sizeof(SCANNER_REPLY);

            RtlCopyMemory(notification->PathName, FileNameInfo->Name.Buffer, FileNameInfo->Name.MaximumLength);

            status = FltSendMessage(ScannerData.Filter,
                &ScannerData.ClientPort,
                notification,
                sizeof(SCANNER_NOTIFICATION),
                notification,
                &replyLen,
                NULL
            );

            if (!NT_SUCCESS(status))
            {
                DbgPrint("Error FltSendMessage\n");
            }



            ExFreePoolWithTag(notification, 'X66');
            FltReleaseFileNameInformation(FileNameInfo);


        }

    }


    return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Kernel Debugging 30 Mar 2020 OSR Seminar Space
Developing Minifilters 15 Jun 2020 LIVE ONLINE
Writing WDF Drivers 22 June 2020 LIVE ONLINE
Internals & Software Drivers 28 Sept 2020 Dulles, VA