Rename of a reparse target

Hi,

I have a file with a custom reparse point on it. It will reparse to another target file. The name resolution seems to work fine. When working with word or other office apps that use the rename to save back the file, the reparse file gets overwritten as well as the reparse point. To avoid this I am intercepting IRP_MJ_SET_INFORMATION for rename and issue the rename to the target but when I complete the operation, driver verifier complains that I cannot complete the IRP since I am not a name provider.

In order to redirect the rename do I really need to be a name provider or is there a better way to handle redirection of a rename?

I am looking at being a name provider to satisfy driver verify. Since I am not trying to virtualize anything, I think just a passthrough name provider may be solve this. From my understanding the minimal name provider would need to implement PFLT_GENERATE_FILE_NAME and
PFLT_NORMALIZE_NAME_COMPONENT. The PFLT_GENERATE_FILE_NAME seems pretty simple to just use FltGetFileNameInformation/FltGetFileNameInformationUnsafe. However I am not understanding what I would need to do in order to implement PFLT_NORMALIZE_NAME_COMPONENT. Is there a way to just send it down to the next filter in the stack?

Thanks for any advice on how to solve this.

Are you using FltSetFileNameInformation and are you a minifilter?
Minifilters must use FSFNI. If this is not your case, you may disregard the post.

Have you looked at SimRep?

@Dejan_Maksimovic, yes I am a minifilter. In order to target the rename to the actual backing target (not the reparse file) I am trying to reissue the io to the backing file. I am currently calling FltSetFileNameInformation from within the IRP_MJ_SET_INFORMATION pre operation to set this on the target file. Then complete the operation to avoid it being sent down and performing the rename on the reparse file.

When I attempted to create a new PFILE_RENAME_INFORMATION and replaced the original buffer in the data->Iopb->Parameters.SetFileInformation.InfoBuffer and let the IO continue there seems to be no effect as the original reparse file still gets renamed. I was able to get the behavior that I wanted when instead I call FltSetFileNameInformation with the new buffer and complete the pre operation but this causes driver verifier to complain that I cannot complete the irp if I am not a name provider (which is more than I want to implement for this).

I hope you meant fltsetinformationfile, that I misspelled also :slight_smile:

How do you call it exactly, can you share the code? I don't recall name filter being a requirement

Thanks @Scott_Noone_OSR I did take a look at simRep and NameChanger as well for the name provider. SimRep seems to be doing what I am already doing by calling FltSetInformationFile with the updated buffer and completing the irp. The only issue with this approach is that driver verifier complains that it is not a name provider when I return FLT_PREOP_COMPLETE. I will keep looking as this does look simpler than the name provider approach.

Yes FltSetInformationFile is what I intended. Here is what I am doing with error checking removed. Excuse any typos as I am unwinding the functions that I am actually calling to make this simpler

if (is_rename_operation(data) && data->Iopb->TargetFileObject) {
  NTSTATUS status;

   PFILE_RENAME_INFORMATION p = (PFILE_RENAME_INFORMATION)data->Iopb->Parameters.SetFileInformation.InfoBuffer;

  UNICODE_STRING file;
  RtlInitUnicodeString(&file, p->FileName);

  // open target file to get the reparse point data
  HANDLE fileHandle;
  PFILE_OBJECT fo;
  OBJECT_ATTRIBUTES objAttr = {NULL};
  IO_STATUS_BLOCK ios;

  InitializeObjectAttributes(&objAttr, file,
                               OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE | OBJ_FORCE_ACCESS_CHECK,
                               NULL, NULL);
  status = FltCreateFileEx2(filter, data->Iopb->TargetInstance, &handle, &fo, FILE_READ_ATTRIBUTES, &objAttr, &ios, nullptr, 0, FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT, nullptr, 0, 0, nullptr);
  if (!NT_SUCCESS(status))
   return status;

  UNICODE_STRING targetFile = target_from_reparse_data(data->Iopb->TargetInstance, fo);

  PFILE_RENAME_INFORMATION buffer = ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(FILE_RENAME_INFORMATION) + targetFile.Length - sizeof(WCHAR), 'tag');

  buffer->Flags = FILE_RENAME_REPLACE_IF_EXISTS | FILE_RENAME_SUPPRESS_PIN_STATE_INHERITANCE;
  buffer->RootDirectory = NULL;
  buffer->FileNameLength = targetFile.Length;
  RtlCopyMemory(buffer->FileName, targetFile.Buffer, targetFile.Length);

  status = FltSetInformationFile(data->Iopb->TargetInstance, data->Iopb->TargetFileObject, buffer, sizeof(FILE_RENAME_INFORMATION) + target->Length - sizeof(WCHAR), FileRenameInformationEx);

  data_->IoStatus.Status = STATUS_SUCCESS;
  return FLT_PREOP_COMPLETE;
}

This seems to be working but after this returns driver verifier breaks.

FILTER VERIFIER ERROR: A filter has completed an operation but does not implement name provider callbacks. For example
if a filter completes an IRP_MJ_CREATE and is not a name provider it is possible that during name
queries the FO will make it's way to the file system and bugcheck. (Filter = FFFFBC0BD8F20050, Cbd = FFFFBC0BE16B4418)

At a quick glance it looks like you are opening the target file and using its FO as the FO (source) in FltSetInformationFile? So renaming it to itself?
Long shot: IoStatus.Information should be set to 0 (not likely to matter here)