none
Code in minifilter PreOperation callback of IRP_MJ_WRITE that produced 2 files with exactly same name in directory RRS feed

  • Question

  • I found that the flowing code in PreOperation of IRP_MJ_WRITE sometimes produce two instances of files with exactly the same name (ChangesBitmap.txt) in one directory, only size differs, but both of them target one location. I can delete one file.

    This is test code ..it is not perfect at all, and this callback is the only thing that my filter is doing now.  Is this some NTFS race bug?
    I found this issue reports from users in google with now answers why...



    FLT_PREOP_CALLBACK_STATUS
    MyFilterPreOperation (
        _Inout_ PFLT_CALLBACK_DATA Data,
        _In_ PCFLT_RELATED_OBJECTS FltObjects,
        _Flt_CompletionContext_Outptr_ PVOID *CompletionContext
        )
    /*++

    Routine Description:

        This routine is a pre-operation dispatch routine for IRP_MJ_WRITE.
    --*/
    {
        NTSTATUS status;
    PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
    PMYFILTER_FILE_CONTEXT fileContext;
    UNICODE_STRING fileName;
    IO_STATUS_BLOCK ioStatus;


        UNREFERENCED_PARAMETER( FltObjects );
        UNREFERENCED_PARAMETER( CompletionContext );


    if (FltObjects->FileObject != NULL) {



    OBJECT_ATTRIBUTES objectAttributes;


    const UNICODE_STRING Filename = RTL_CONSTANT_STRING(L"\\Device\\HarddiskVolume1\\temp\\ChangesBitmap.txt");

    InitializeObjectAttributes(&objectAttributes,
    &Filename,
    OBJ_KERNEL_HANDLE,
    NULL,
    NULL);



    status = FltCreateFile(gFilterHandle,
    NULL,
    &bitmapFileHandle,
    FILE_WRITE_DATA | FILE_APPEND_DATA,
    &objectAttributes,
    &ioStatus,
    (PLARGE_INTEGER)NULL,
    FILE_ATTRIBUTE_NORMAL,
    FILE_SHARE_READ,
    FILE_OPEN_IF,
    FILE_NON_DIRECTORY_FILE | FILE_WRITE_THROUGH | FILE_RANDOM_ACCESS,
    (PVOID)NULL,
    0L,
    IO_IGNORE_SHARE_ACCESS_CHECK);

    if (status == STATUS_OBJECT_PATH_SYNTAX_BAD)
    {
    KdPrintEx((DPFLTR_MyFilter_ID, DPFLTR_INFO_LEVEL, "MyFilter!STATUS_OBJECT_PATH_SYNTAX_BAD\n"));
    }
    if (status == STATUS_MOUNT_POINT_NOT_RESOLVED)
    {
    KdPrintEx((DPFLTR_MyFilter_ID, DPFLTR_INFO_LEVEL, "MyFilter!STATUS_MOUNT_POINT_NOT_RESOLVED\n"));
    }


    status = FltGetFileNameInformation(Data,
    FLT_FILE_NAME_NORMALIZED |
    FLT_FILE_NAME_QUERY_DEFAULT,
    &nameInfo);

    if (!NT_SUCCESS(status)) {
    return FLT_PREOP_SUCCESS_WITH_CALLBACK;
    }
    }

    fileName = nameInfo->Name;

    #ifdef DBG

    FLT_ASSERT(NT_SUCCESS(FltParseFileNameInformation(nameInfo)));


    #else

    FltParseFileNameInformation(nameInfo);

    #endif


    const UNICODE_STRING Filename = RTL_CONSTANT_STRING(L"New Text Document.txt");

    if (RtlCompareUnicodeString(&Filename, &nameInfo->FinalComponent, TRUE) == 0)
    {
    status = FltAllocateContext(FltObjects->Filter,
    FLT_FILE_CONTEXT,
    sizeof(MYFILTER_FILE_CONTEXT),
    PagedPool,
    &fileContext);

    if (!NT_SUCCESS(status)) {
    return status;
    }

    status = FltSetFileContext(FltObjects->Instance,
    FltObjects->FileObject,
    FLT_SET_CONTEXT_KEEP_IF_EXISTS,
    fileContext,
    NULL);

    if (status == STATUS_FLT_CONTEXT_ALREADY_DEFINED)
    {
    status = FltGetFileContext(FltObjects->Instance,
    FltObjects->FileObject,
    &fileContext);
    }
    else
    {
    RtlZeroMemory(fileContext, sizeof(MYFILTER_FILE_CONTEXT));
    }


    fileContext->OperationCount++;

    //FsRtlInitPerFileContext(&fileContext, 10, FsRtlGetPerFileContextPointer, NULL);
    KdPrintEx((DPFLTR_MyFilter_ID, DPFLTR_INFO_LEVEL, "MyFilter! Write to target file: ByteOffset - %ld, Length - %lu,",
    Data->Iopb->Parameters.Write.ByteOffset,
    Data->Iopb->Parameters.Write.Length));
    }



    if (NULL != nameInfo) {

    FltReleaseFileNameInformation(nameInfo);
    }


        return FLT_PREOP_SUCCESS_WITH_CALLBACK;
    }




    (Also i have the same FltCreateFile in DriverEntry, but i don't think it metters).






    • Edited by The Brans Thursday, December 11, 2014 2:55 PM
    Monday, June 2, 2014 2:11 PM

All replies

  • First show us the code in DriverEntry, and check if the cases of the two instances are the same. 


    Don Burn Windows Filesystem and Driver Consulting Website: http://www.windrvr.com Blog: http://msmvps.com/blogs/WinDrvr

    Monday, June 2, 2014 3:04 PM
  • Two instances are the same (same content, i can change any of those files and content changes)

    NTSTATUS

    DriverEntry (
        _In_ PDRIVER_OBJECT DriverObject,
        _In_ PUNICODE_STRING RegistryPath
        )
    {
        NTSTATUS status;
    IO_STATUS_BLOCK ioStatus;

        UNREFERENCED_PARAMETER( RegistryPath );

    KdPrintEx((DPFLTR_MYFILEFILTER_ID, DPFLTR_INFO_LEVEL, "MyFileFilter!DriverEntry: Entered\n"));

        status = FltRegisterFilter( DriverObject,
                                    &FilterRegistration,
                                    &gFilterHandle );

        FLT_ASSERT( NT_SUCCESS( status ) );

        if (NT_SUCCESS( status )) {

    OBJECT_ATTRIBUTES objectAttributes;


    const UNICODE_STRING Filename = RTL_CONSTANT_STRING(L"\\Device\\HarddiskVolume1\\temp\\ChangesBitmap.txt");

    InitializeObjectAttributes(&objectAttributes,
    &Filename,
    OBJ_KERNEL_HANDLE,
    NULL,
    NULL);

    status = FltCreateFile(gFilterHandle,
    NULL,
    &bitmapFileHandle,
    FILE_WRITE_DATA | FILE_APPEND_DATA,
    &objectAttributes,
    &ioStatus,
    (PLARGE_INTEGER)NULL,
    FILE_ATTRIBUTE_NORMAL,
    FILE_SHARE_READ,
    FILE_OPEN_IF,
    FILE_NON_DIRECTORY_FILE | FILE_WRITE_THROUGH | FILE_RANDOM_ACCESS,
    (PVOID)NULL,
    0L,
    IO_IGNORE_SHARE_ACCESS_CHECK);


    if (status == STATUS_OBJECT_PATH_SYNTAX_BAD)
    {
    KdPrintEx((DPFLTR_MyFILEFILTER_ID, DPFLTR_INFO_LEVEL, "MyFileFilter!STATUS_OBJECT_PATH_SYNTAX_BAD\n"));
    }
    if (status == STATUS_MOUNT_POINT_NOT_RESOLVED)
    {
    KdPrintEx((DPFLTR_MYFILEFILTER_ID, DPFLTR_INFO_LEVEL, "MyFileFilter!STATUS_MOUNT_POINT_NOT_RESOLVED\n"));
    }

    //FLT_ASSERT(bitmapFileHandle);
            //
            //  Start filtering i/o
            //

            status = FltStartFiltering( gFilterHandle );

            if (!NT_SUCCESS( status )) {

                FltUnregisterFilter( gFilterHandle );
            }
        }

        return status;
    }



    • Edited by The Brans Thursday, December 11, 2014 2:56 PM
    Tuesday, June 3, 2014 6:44 AM