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

Sept/Oct 2019 Issue of The NT Insider available


Download PDF here: http://insider.osr.com/2019/ntinsider_2019_01.pdf

It’s a particularly BIG issue, too: 40 pages of technical goodness, ranging from WDF to Minifilters. Check it out.
Before Posting...
Please check out the Community Guidelines in the Announcements and Administration Category.

Data->Iopb->Parameters.Write.ByteOffset invalid in funtion of how user app manages the file written.

rsalvarez280rsalvarez280 Member Posts: 9

Hi all.

I'm trying to develop a minifilter to control the writes of a user application in a file. I am controling each write operation in PreWrite callback. The minifilter sends all data received to another user application using FltSendMessage function before the data is written in the file.

I have develop a test user application to write in the file continously (one line each 1 second, for example), and the data received in the minifilter is different in funtion on how this test application manages this file.

If this app is develop in C, and uses for example, log4cplus to write the file, each write operation is duplicated in the minifilter, allways duplicated. But the Data->Iopb->Parameters.Write.ByteOffset said me that the two PreWrite calls are for the same file line (the offset is the same for both PreWrite calls). So I can use this ByteOffset to discart the second one (I save each PreWrite offset in a variable and compare the last offset saved with the new offset received, if both are the same, the second line is not sent with FltSendMessage because is duplicated.

if this test app is develop in Java, with a FileWriter object, the PreWrite calls are not duplicated an the offset is allways -1. This offset never changes.

Reading about this ByteOffset parameter, I thought this parameter indicated the position of the data within the file. So, why is it received allways with -1 value? The data is written in the file in the correct position, so I don't understand this behaviour.

Another thing I have test is to check Data->Iopb->Parameters.Write.Key of each PreWrite call. But it is always received with 0 value.

Does anyone have any idea how to solve this?

Thanks!!

Comments

  • rsalvarez280rsalvarez280 Member Posts: 9

    Doing some investigation I have discover that -1 in ByteOffset means to write at the end of the file, without specifying a exact file position. So, now I need to understand why some preWrite calls are executed for the same write data. Any idea?
    This is my preWrite function:

    FLT_PREOP_CALLBACK_STATUS CFilCtrlDrvFilter::PreWrite(__inout PFLT_CALLBACK_DATA Data,
        __in PCFLT_RELATED_OBJECTS FltObjects,
        __deref_opt_out PVOID*     CompletionContext) {
    
        UNREFERENCED_PARAMETER(FltObjects);
        UNREFERENCED_PARAMETER(CompletionContext);
        UNREFERENCED_PARAMETER( Data);
    
    
        //If there is no config object, do nothing.
        if(!m_Config) {
            return FLT_PREOP_SUCCESS_NO_CALLBACK;
        }
    
        //If the filter is activated (my own registry parameter to filter or not filter).
        if(!m_Config->FilterActivated()) {
            return FLT_PREOP_SUCCESS_NO_CALLBACK;
        }
    
        // Check we are managing the right IRP
        NT_ASSERT(Data->Iopb->MajorFunction == IRP_MJ_WRITE);
    
    
        if(FlagOn( Data->Iopb->IrpFlags, IRP_NOCACHE))//IRP_WRITE_OPERATION))
            return FLT_PREOP_SUCCESS_NO_CALLBACK;
    
    
        // Get filename information
        PFLT_FILE_NAME_INFORMATION FileNameInfo = GetFileNameInfoWrite(Data);
        if(!FileNameInfo)
            return FLT_PREOP_SUCCESS_NO_CALLBACK;
    
        //If the file to write is not in the path configured, no nothing.
        CWString strFilePath(FileNameInfo->ParentDir);
        if(strFilePath != m_Config->GetMonitorizeFilePath()) {
            return FLT_PREOP_SUCCESS_NO_CALLBACK;
        }
    
        CWString strFinalComponent(FileNameInfo->FinalComponent);
        //KdPrint(("FILCtrl-PreWrite: Final: %wZ.\n", &FileNameInfo->FinalComponent));
    
        PWCHAR lpwFinalComponent = NULL;
        strFinalComponent >> lpwFinalComponent;
    
        PWCHAR lpwMonitorizeFile = NULL;
        m_Config->GetMonitorizeFileName() >> lpwMonitorizeFile;
    
            //Check if file name matches my configuration (regular expresions)
        int result = wslre_match(lpwMonitorizeFile , lpwFinalComponent, (int)wcslen(lpwFinalComponent), NULL, 0, 0);
        //If matches
        if( result >= 0) {
    
            LARGE_INTEGER lOffset = Data->Iopb->Parameters.Write.ByteOffset;
            KdPrint(( "FILCtrl-PreWrite: Offset: %i %i.\n", Data->Iopb->Parameters.Write.ByteOffset.u.HighPart, Data->Iopb->Parameters.Write.ByteOffset.u.LowPart));
    
            char *ioBuffer = NULL;
            PMDL MdlAddress = Data->Iopb->Parameters.Write.MdlAddress;
            ULONG Length = (ULONG)Data->Iopb->Parameters.Write.Length;
            if(MdlAddress != NULL) {
                ASSERT( MdlAddress->Next == NULL);
                ioBuffer = (char*) MmGetSystemAddressForMdlSafe( MdlAddress, NormalPagePriority);
    
            } else {
                __try {
                    ioBuffer = (char*)Data->Iopb->Parameters.Write.WriteBuffer;
                    if(Data->RequestorMode != KernelMode) {
                        ProbeForRead(ioBuffer, Data->Iopb->Parameters.Write.Length, 1);
                    }
                }__except(EXCEPTION_EXECUTE_HANDLER) {
                    KdPrint(("FILCtrl-PreWrite: Exception ProbeForRead.\n"));
                    ioBuffer = NULL;
                }
    
            }
    
            if( ioBuffer != NULL) {
    
                if(lOffset.u.HighPart == -1 && lOffset.u.LowPart == -1) {
                    KdPrint(("FILCtrl-PreWrite: Offset -1. Writing %ld.\n", Length));
                                    //Send data to client app using FltSendMessage 
                    sendDataToClient(ioBuffer, Length);
                } else {
                    //Compare this offset with the last preWrite executions offset.
                                    if(differentOffset(&lOffset)) {
                        KdPrint(("FILCtrl-PreWrite: Offset different. Writing %ld.\n", Length));
                                            //Send data to client app using FltSendMessage 
                        sendDataToClient(ioBuffer, Length);
                                            //Safe this preWrite offset to compare with the next preWrite offset.
                        saveNewOffset(&lOffset);
                    }
                    else {
                        KdPrint(("FILCtrl-PreWrite: Same offset.\n"));
                    }
                }
            }
        }
    
        FltReleaseFileNameInformation(FileNameInfo);
        FileNameInfo = NULL;
    
        return FLT_PREOP_SUCCESS_NO_CALLBACK;
    
    }
    
  • rod_widdowsonrod_widdowson Member - All Emails Posts: 1,073
    edited October 23

    So, why is it received allways with -1 value? The data is written in the file in the correct position, so I don't understand this behaviour.

    That would be FILE_WRITE_TO_END_OF_FILE

  • rsalvarez280rsalvarez280 Member Posts: 9

    @rod_widdowson said:

    So, why is it received allways with -1 value? The data is written in the file in the correct position, so I don't understand this behaviour.

    That would be FILE_WRITE_TO_END_OF_FILE

    Yes, I now know the -1 meaning, so my develop is not valid because I assumed that the offset should be always different. If the offset received in one PreWrite is the same than the last PreWrite offset, I could discard this data because I had already processed it in the previous call.

    If the offset is not valid for me, the only possibility is to know why some times the minifilter receives more than one PreWrite for the same data. I think that some of this repeated PreWrite must be discarted in my minifilter before processed the data, but I don't know how to identify this callbacks.

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
Writing WDF Drivers 21 Oct 2019 OSR Seminar Space & ONLINE
Internals & Software Drivers 18 Nov 2019 Dulles, VA
Kernel Debugging 30 Mar 2020 OSR Seminar Space
Developing Minifilters 27 Apr 2020 OSR Seminar Space & ONLINE