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

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

Modifying data when processing IRP_WRITE request

Alexey_YerakhavetsAlexey_Yerakhavets Member - All Emails Posts: 31
Hello everybody. I wrote a wdf filter driver for the usb device. When EvtIoWrite triggers, I want to change the data and put it on the device. I tried to use these methods WdfRequestRetrieveInputMemory, WdfMemoryCopyFromBuffer and WdfMemoryCopyToBuffer. But after sending this request to the next driver, there is a fatal error 0x00000023: FAT_FILE_SYSTEM. If you can explain the principle or give an example, I will be very happy. Thank you.

Comments

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 12,914
    xxxxx@gmail.com wrote:
    > Hello everybody. I wrote a wdf filter driver for the usb device.

    For WHICH USB device?  Upper filter or lower filter?


    > When EvtIoWrite triggers, I want to change the data and put it on the device. I tried to use these methods WdfRequestRetrieveInputMemory, WdfMemoryCopyFromBuffer and WdfMemoryCopyToBuffer. But after sending this request to the next driver, there is a fatal error 0x00000023: FAT_FILE_SYSTEM.

    How did you decide which requests to modify?  If you do have a filter on
    USB disks, and you arbitrarily change write requests without
    understanding what those requests contain, then you should not be
    surprised by this result.

    What are you actually trying to do?
    --
    Tim Roberts, xxxxx@probo.com
    Providenza & Boekelheide, Inc.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • Alexey_YerakhavetsAlexey_Yerakhavets Member - All Emails Posts: 31
    Hi, Tim. I installed my driver as a upper filter driver.
    When I write a file to the device, I want to encrypt it, and when processing the read request, I decrypt the files on the device. I've found some examples based on wdm, but would like to write a wdf driver. Is it possible to somehow check when a write request comes, exactly, on a file record?
    An example of processing a write request on wdm that I could find.
    NTSTATUS
    FilterWrite (
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp
    )
    {
    PVOID Buffer, Buffer2;
    LARGE_INTEGER ByteOffset;
    ULONG Length, sector;
    PDISK_CRYPT_EXTENSION ext = DeviceObject->DeviceExtension;
    PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
    PMDL OriginalMdl, Mdl2;
    #ifdef _DBG_TEST
    DbgPrint("FilterWrite\n");
    #endif

    ByteOffset.QuadPart = irpStack->Parameters.Read.ByteOffset.QuadPart;
    Length = irpStack->Parameters.Read.Length;

    Buffer = MapUserBuffer (Irp);
    Buffer2 = ExAllocatePool (NonPagedPool, Length);

    CryptSectors (
    &ext->Filter.CryptKey,
    Buffer,
    Buffer2,
    irpStack->Parameters.Read.ByteOffset,
    irpStack->Parameters.Read.Length >> 9,
    TRUE);

    OriginalMdl = Irp->MdlAddress;

    MmBuildMdlForNonPagedPool (IoAllocateMdl (Buffer2, Length, FALSE, FALSE, Irp));

    IoCopyCurrentIrpStackLocationToNext (Irp);

    IoSetCompletionRoutine(
    Irp,
    FilterWriteCompletion,
    OriginalMdl,
    TRUE, TRUE, TRUE);

    return IoCallDriver(ext->LowerDevice, Irp);
    }

    NTSTATUS
    FilterWriteCompletion (
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PVOID Context
    )
    {
    PMDL OriginalMdl = Context;
    PVOID Buffer2;
    #ifdef _DBG_TEST
    DbgPrint("FilterWriteCompletion\n");
    #endif
    Buffer2 = MapUserBuffer (Irp);

    IoFreeMdl (Irp->MdlAddress);
    ExFreePool (Buffer2);

    Irp->MdlAddress = OriginalMdl;

    if (Irp->PendingReturned)
    IoMarkIrpPending(Irp);

    return STATUS_SUCCESS;
    }
  • Tim_RobertsTim_Roberts Member - All Emails Posts: 12,914
    xxxxx@gmail.com wrote:
    > Hi, Tim. I installed my driver as a upper filter driver.

    Upper filter to what?  It doesn't help to know where you are filtering,
    if we don't know which device you are filtering.


    > When I write a file to the device, I want to encrypt it, and when processing the read request, I decrypt the files on the device.

    But you never deal with files, at ANY level.  You deal with sectors, or
    with parts of sectors.  Above the file system level, the user opens a
    file handle, and then reads and writes portions of the file, possibly at
    random.  Below the file system level, drivers deal with sectors
    addressed by sector numbers, and you can't tell whether the request is
    inside a file or inside the file system's bookkeeping tables.

    If your encryption algorithm changes the size of the buffer, then this
    whole approach is doomed.  To do that, you have to work above the file
    system level, and you DO have to do whole files at a time.

    If the input and output are the same size, then your approach can be
    made to work, although there are many, many problems to overcome. How
    will you handle a device being plugged in that is not encrypted?  How
    will you know whether to decrypt or not?  And, if you operate below the
    file system level, then your drive will appear as unformatted garbage to
    any system that does not have your filter.


    > I've found some examples based on wdm, but would like to write a wdf driver. Is it possible to somehow check when a write request comes, exactly, on a file record?

    Assuming you are filtering at the USB level, then no, there is no way. 
    At the USB level, it's all just reads and writes of sectors. The device
    has no knowledge of file systems, or even whether a file system is
    present or not.  You need to sit down with a whiteboard and figure out
    where you need to filter, what requests you are going to see, and how
    you will handle the various combinations of requests.


    > An example of processing a write request on wdm that I could find.

    Unless there's more code you aren't showing us, that example has a
    serious problem.  It allocates a new MDL for the new encrypted buffer,
    but it never replaces the buffer pointer in the IRP.  The IRP gets
    submitted with the user's buffer.  Then, in the completion routine, you
    fetch the user's buffer and free it.  That's a BSOD.

    --
    Tim Roberts, xxxxx@probo.com
    Providenza & Boekelheide, Inc.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

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 25 Feb 2019 OSR Seminar Space
Developing Minifilters 8 April 2019 OSR Seminar Space