Mini filter driver to redirect file access

Hello,

I’m new to driver and windows programming and I have some doubts about a project I’m doing. I’m developing a minifilter driver to redirect all create, open and write operations of a local file to a shared one. For example:
I want to redirect all the operations mentioned above from C:\tmp\foo.txt to D:\dir\foo.txt.
After looking the microsoft examples and another posts trying to do some redirections like me I arrived to the conclusion that I should use STATUS_REPARSE. Is this the correct approach or should I use a different method?

Actually I know it works for the IRP_MJ_CREATE, but will it work with write and delete operations or should I use a different method?

Thank you for any help.

I’m new to driver and windows programming
Two learning cliffs for the price of one. Three if you include Windows File systems as being as complicated again as windows device drivers. Good luck.

Actually I know it works for the IRP_MJ_CREATE, but will it work with write and delete operations or should I use a different method?

Once the file has been opened that’s it. The read/write/delete operations go to the file object and it doesn’t care what the name is.

Which is the right way to go? Without knowing your requirements in detail we cannot say, but for a first project doing reparse is relatively easy approach.

Amongst the many issues you will have will be that the name of the file object will now be d:\dir\foo.txt. So (for instance) if this file contains a virus the AV will complain about the virus on d:\dir\foo.txt and the user (who opened the file) c:\tmp\foo.txt might get confused.

Off the top of my head renames and relative opens are other things to worry about.

  • c:\> move c:\tmp\foo.txt c:\usersjkrian\desktop\krian.txt will fail which might make people surprised
  • An open of tmp\foo\txt relative to a HANDLE opened to c:\ might not give you d:\dir\foo.txt

There are no doubt other issues. Drop back in and let us know how you are getting on…

Hello,
thank you for your help rod_widdowson, and sorry for my late response, i’ve been busy coding this week

This project origins because I want to acces a file that normally it’s stored in local from different servers. Let’s say that I have with an app that stores info in a local file and I have this app installed in different servers. I want to redirect all the operations to that file to a remote disk shared by all the servers so this app will always read the file in the remote device, reading the same file from all servers.

I’ve been coding this week, using some examples I found online and the ones in the Microsoft GitHub I am able to redirect the file operations when they are done in the same drive but I am not able to redirect the acces to a remote drive.

I notice that with FltParseFileNameInformation() function I get the Volume name like \Device\VolumeHarddisk2\ for the C: drive and \Device\VolumeHarddisk3\ for the D: drive, the one I want to redirect the files.
I modify the name of the FIleObject with IoReplaceFileObjectName with the final Path I want to redirect the file and then I set the STATUS_REPARSE and call FltSetCallbackDataDirty().
This approach works fine when redirecting into the same drive but it is crashing when I try to redirect to the drive D:
Do I need to use a different approach to achieve the drive redirection? Or is there something that I am missing?

Thank you for your time.

I want to redirect all the operations to that file to a remote disk shared by all the servers
so this app will always read the file in the remote device, reading the same file from
all servers.
Surely the solution is for all versions of the app to access the file by its network name. Job done. Or are you saying that you don’t have control over the app and you want to intercept its open to the local file system?

Have you considered making a symbolic link on the files mklink d:\foo \\mymachine\share\foo\bar (better still do it for the parent directory). That will do what you need and not require any programming (aside works a treat for OneDrive too!).

What you describe is the coding equivalent of the above. Precisely why it isn’t working will be in the details of your implementation.

Thank you for your answer rod_widdowson,

Or are you saying that you don’t have control over the app and you want to intercept its open to the local file system?
Yes I don’t have any control over the app, and I want to intercept all the operations to the local File System.

I know that there may be several solutions to the problem but I want to implement a Minifilter to do the work as a project to myself and to get started into the drivers world.

I tried several solutions and test and I don’t get why I can redirect a file when I only change the path in local drives but I get a crash when trying to change the drive, this is essentially the code I’m running now to test the redirect, since it is not working I simplied it as much as I can. Is the path that I am writing invalid ? Should I use another path like \\??\\D:\\ for the drive?

Here is the code of the pre callback operation. I don’t know why some code is in the code format and the other one is like plain text :confused:

FLT_PREOP_CALLBACK_STATUS FSPreOperation (PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID *CompletionContext)
{
NTSTATUS status;
PFLT_FILE_NAME_INFORMATION FileInfo;
UNICODE_STRING redirectTarget;

status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED|FLT_FILE_NAME_QUERY_DEFAULT|FLT_FILE_NAME_DO_NOT_CACHE, &FileInfo);
if (NT_SUCCESS(status)) {
status = FltParseFileNameInformation(FileInfo);

	if (NT_SUCCESS(status)) {

		if (FileNeedsRedirect(FileInfo)) {
			RtlInitUnicodeString(&redirectTarget, L"\\Device\\HarddiskVolume3\\newname.txt");

			status = IoReplaceFileObjectName(Data->Iopb->TargetFileObject, redirectTarget.Buffer, redirectTarget.Length);

			Data->IoStatus.Information = IO_REPARSE;
			Data->IoStatus.Status = STATUS_REPARSE;
			Data->Iopb->TargetFileObject->RelatedFileObject = NULL;

			FltSetCallbackDataDirty(Data);
			FltReleaseFileNameInformation(FileInfo);

			return FLT_PREOP_COMPLETE;
		}
	}

	FltReleaseFileNameInformation(FileInfo);
}
return FLT_PREOP_SUCCESS_NO_CALLBACK;

}

Thank you for your time.

Its too long, but I have a suspicion that you have to set up a reparse buffer. Others will remember better than I.

Also getting the file name in pre is pretty bad for performance.

Did mklink not work for you?

Thank you for your answer rod_widdowson,

yes mklink worked, but as I said, I’m looking to develop this minifilter.
I managed to solve the problem and it redirects all the file access correctly now!

Thank you for your help!