Paths differ between moving a file and copying it

I am aware of the various discussions surrounding this topic: https://community.osr.com/discussion/242666/minifilter-proxy-folder

For instance, I want to restrict the total path length of a file/folder to 200. (This is done as an example to learn.) Creating, renaming, and moving all work as expected (too long of a path will be prevented); however, copying does not. When I look at my Dbgprint, rather than seeing \Device\HarddiskVolume3\Shares\Data\REALLYLONGFILENAME.txt, I see \Device\HarddiskVolume3\Shares\Data. Again, I don’t care where it came from, just that copying seems to circumvent my minifilter. Both FltGetFileNameInformation and Data->Iopb->TargetFileObject->FileName give the same result.

FLT_PREOP_CALLBACK_STATUS
FLTAPI CreateCheckPathLengthPre(
    _Inout_ PFLT_CALLBACK_DATA Data,
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _Flt_CompletionContext_Outptr_ PVOID* CompletionContext
)
{
    UNREFERENCED_PARAMETER(FltObjects);
    UNREFERENCED_PARAMETER(CompletionContext);

    if (Data->RequestorMode == KernelMode)
        return FLT_PREOP_SUCCESS_NO_CALLBACK;

    ULONG createDisp = (Data->Iopb->Parameters.Create.Options >> 24) & 0x000000FF;
    ULONG isCreation = ((createDisp == FILE_CREATE));

    if (!isCreation)
        return FLT_PREOP_SUCCESS_NO_CALLBACK;

    NTSTATUS status;
    PFLT_FILE_NAME_INFORMATION info = NULL;
    if (NULL != FltObjects->FileObject) {
        status = FltGetFileNameInformation(Data, FLT_FILE_NAME_OPENED | FLT_FILE_NAME_QUERY_DEFAULT | FLT_FILE_NAME_DO_NOT_CACHE, &info);

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

        size_t path_len = wcslen(info->Name.Buffer);
        if (path_len >= MAX_PATH_LENGTH) {
            Data->IoStatus.Status = STATUS_NAME_TOO_LONG;
            Data->IoStatus.Information = 0;

            return FLT_PREOP_COMPLETE;
        }
    }

    return FLT_PREOP_SUCCESS_NO_CALLBACK;
}

Sorry, there’s nothing here to say more than “you have a bug”. Add more traces, set breakpoints, etc. You can also run ProcMon and see what it sees.

1 Like

@“Scott_Noone_(OSR)” said:
Sorry, there’s nothing here to say more than “you have a bug”. Add more traces, set breakpoints, etc. You can also run ProcMon and see what it sees.

Turns out this thread was right when suggesting IRP_MJ_SET_INFORMATION: https://community.osr.com/discussion/154815/how-to-detect-file-moved-or-copied

Once I used FltGetDestinationFileNameInformation, as opposed to casting InfoBuffer to PFILE_RENAME_INFORMATION, things worked as expected. (I was filtering for specific paths. I thought I had done enough testing to confirm I was getting the correct path information. Not only was FileName empty, but I should have been checking the destination not the source.)

SetInfo for copy, but not for move?