Fun with file system file redirection.

Hi,

I have an issue I’ve been banging my head against and thought I’d post up for thoughts/comments.

I’m currently writing a file redirect mini filter, which watches IRP_MJ_CREATE operations for certain processes, and re-directs IRP_MJ_CREATE operations made by those processes under a specified directory, to a target directory.
Unfortunately for me, my current version is an abject failure.

For example, lets say I have a VisualStudio project, which I would like to redirect all compile output for, just as a test, thus:

C:\Temp\Source\TestApp\
stdafx.h
stdafx.cpp
MyTest.sln
MyTest.vcproj
D:\Temp\Target\TestApp\
stdafx.h
stdafx.cpp

MyTest.sln
MyTest.vcproj

Now, to get things going, I specify the process i’d like to track, PID=3378, and give the source and target directories
Src=C:\Temp\Source, Tgt=D:\Temp\Target
to my API

The mini filter will now track all file iop made by the process PID, and optionally any iop made by child processes that PID generates. All IRP_MJ_CREATE io events with relevant directories are re-directed via FltSetCallbackDataDirty and FLT_PREOP_COMPLETE.
All good so far? OK, as far as I’m aware, one is not allowed to re-direct anything other than IRP_MJ_CREATE. So currently that’s all that I re-direct.

With the directory structure as above, and PID=VisualStudio, a compile produces quite a large number of IOP events, many CREATE ops which are re-directed, for example:
1
Process devenv.com
Major Code IRP_MJ_CREATE
Minor Code
Result Success
File C:\Temp\Source\TestApp\Debug
2
Process devenv.com
Major Code IRP_MJ_CREATE
Minor Code
Result Success
File C:\Temp\Target\TestApp\Debug
3
Process devenv.com
Major Code IRP_MJ_DIRECTORY_CONTROL
Minor Code IRP_MN_QUERY_DIRECTORY
Result NO_SUCH_FILE
File C:\Temp\Target\TestApp\Debug

quite a large number of…

k
Process devenv.com
Major Code IRP_MJ_CREATE
Minor Code
Result Success
File C:\Temp\Source\TestApp\Debug\vc80.pdb
k+1
Process devenv.com
Major Code IRP_MJ_CREATE
Minor Code
Result OBJECT_NAME_NOT_FOUND
File C:\Temp\Target\TestApp\Debug\vc80.pdb

and a whole bunch of other exciting records which I wont bore you with here.
The interesting part is the records concening vc80.pdb

Process devenv.com
Major Code IRP_MJ_NETWORK_QUERY_OPEN
Minor Code
Result OBJECT_NAME_NOT_FOUND
File C:\Temp\Source\TestApp\Debug\vc80.pdb

which occur a number of times down the list of events.
Along with a bunch of

Process devenv.com
Major Code IRP_MJ_NETWORK_QUERY_OPEN
Minor Code
Result OBJECT_PATH_NOT_FOUND
File C:\Temp\Source\TestApp\Debug\vc80.idb

Process devenv.com
Major Code IRP_MJ_NETWORK_QUERY_OPEN
Minor Code
Result OBJECT_PATH_NOT_FOUND
File C:\Temp\source\testapp\debug\stdafx.obj

Process devenv.com
Major Code IRP_MJ_NETWORK_QUERY_OPEN
Minor Code
Result OBJECT_PATH_NOT_FOUND
File C:\Temp\source\testapp\debug\TestAppView.obj

Process devenv.com
Major Code IRP_MJ_NETWORK_QUERY_OPEN
Minor Code
Result OBJECT_PATH_NOT_FOUND
File C:\Temp\source\testapp\debug\TestAppDoc.obj

The result is a compile failure.

Microsoft (R) Visual Studio Version 8.0.50727.762.
Copyright (C) Microsoft Corp 1984-2005. All rights reserved.
------ Build started: Project: TestApp, Configuration: Debug Win32 ------
TestApp : error PRJ0007 : Could not create output directory ‘c:\temp\source\testapp\debug’.
Compiling…
cl : Command line warning D9028 : minimal rebuild failure, reverting to normal build
stdafx.cpp
c:\temp\source\testapp\stdafx.cpp : fatal error C1033: cannot open program database ‘c:\temp\source\testapp\debug\vc80.pdb’
TestApp - 2 error(s), 1 warning(s)

The resulting directory structure looks like this…

C:\Temp\Source\TestApp\
stdafx.h
stdafx.cpp
MyTest.sln
MyTest.vcproj
D:\Temp\Target\TestApp\
Debug
BuildLog.htm
TestApp.exe.embed.manifest
stdafx.h
stdafx.cpp
MyTest.sln
MyTest.vcproj

OK, so a bit of head scratching later I noticed that if I created a \Debug directory in the source, the build works, but unfortunately the source \Debug folder contains the following three files:

C:\Temp\Source\TestApp\Debug
TestApp.pdb
vc80.idb
vc80.pdb

(the destination contains the following files:)

D:\Temp\Target\TestApp\Debug
BuildLog.htm
MainFrm.obj
mt.dep
stdafx.obj
TestApp.exe
TestApp.exe.embed.manifest
TestApp.exe.embed.manifest.res
TestApp.exe.intermediate.manifest
TestApp.ilk
TestApp.obj
TestApp.pch
TestApp.res
TestAppDoc.obj
TestAppView.obj

The events that create the idb

Process devenv.com
Major Code IRP_MJ_NETWORK_QUERY_OPEN
Minor Code
Result Success
File C:\Temp\Source\TestApp\Debug\vc80.idb

Process devenv.com
Major Code IRP_MJ_CREATE
Minor Code
Result Success
File C:\Temp\Source\TestApp\Debug\vc80.idb

Process devenv.com
Major Code IRP_MJ_CREATE
Minor Code
Result OBJECT_NAME_NOT_FOUND
File D:\Temp\Source\TestApp\Debug\vc80.idb

Process devenv.com
Major Code IRP_MJ_CREATE
Minor Code
Result Success
File C:\Temp\Source\TestApp\Debug\vc80.idb

Process devenv.com
Major Code IRP_MJ_CREATE
Minor Code
Result OBJECT_NAME_NOT_FOUND
File D:\Temp\Source\TestApp\Debug\vc80.idb

However all events captured for vc80.pdb fail with OBJECT_PATH_NOT_FOUND, yet it’s still created in Source. Very odd.

So, these pdb, idb files are not being re-directed / re-located correctly, obviously as I’m not intercepting IRP_MJ_NETWORK_QUERY_OPEN (perhaps?) and re-directing it.
Could this be the reason, or is it something more subtle (I suspect so).
Am I missing a re-direction event along the way? Or is this actually indicative of ‘something that’s not possible’?
Some relevant points - My filter is running on WinXP at altitude 40100 as a test in order to try to redirect the filename before any other filters get at it. The result codes shown above are written during PostOp

Apologies for the longish post. I’m wondering whether anyone has come across this type of issue before?
Many thanks

Mike

To start I would begin testing with something other than a compile
process. Say notepad? Editing a file c:\Dir1\foo.txt which actually ends
up editing a file c:\Dir2\foo.txt.

Next, you are not clear in how you are actually performing the
redirection in the code. Are you returning a STATUS_REPARSE and
supplying the correct information for the new file name? Can you show us
what you are actually doing in the handling of the redirection within
your filter driver?

Again, start with something simple like notepad editing a file.

Pete

xxxxx@scee.net wrote:

Hi,

I have an issue I’ve been banging my head against and thought I’d post up for thoughts/comments.

I’m currently writing a file redirect mini filter, which watches IRP_MJ_CREATE operations for certain processes, and re-directs IRP_MJ_CREATE operations made by those processes under a specified directory, to a target directory.
Unfortunately for me, my current version is an abject failure.

For example, lets say I have a VisualStudio project, which I would like to redirect all compile output for, just as a test, thus:

C:\Temp\Source\TestApp\
stdafx.h
stdafx.cpp
MyTest.sln
MyTest.vcproj
D:\Temp\Target\TestApp\
stdafx.h
stdafx.cpp

MyTest.sln
MyTest.vcproj

Now, to get things going, I specify the process i’d like to track, PID=3378, and give the source and target directories
Src=C:\Temp\Source, Tgt=D:\Temp\Target
to my API

The mini filter will now track all file iop made by the process PID, and optionally any iop made by child processes that PID generates. All IRP_MJ_CREATE io events with relevant directories are re-directed via FltSetCallbackDataDirty and FLT_PREOP_COMPLETE.
All good so far? OK, as far as I’m aware, one is not allowed to re-direct anything other than IRP_MJ_CREATE. So currently that’s all that I re-direct.

With the directory structure as above, and PID=VisualStudio, a compile produces quite a large number of IOP events, many CREATE ops which are re-directed, for example:
1
Process devenv.com
Major Code IRP_MJ_CREATE
Minor Code
Result Success
File C:\Temp\Source\TestApp\Debug
2
Process devenv.com
Major Code IRP_MJ_CREATE
Minor Code
Result Success
File C:\Temp\Target\TestApp\Debug
3
Process devenv.com
Major Code IRP_MJ_DIRECTORY_CONTROL
Minor Code IRP_MN_QUERY_DIRECTORY
Result NO_SUCH_FILE
File C:\Temp\Target\TestApp\Debug

quite a large number of…

k
Process devenv.com
Major Code IRP_MJ_CREATE
Minor Code
Result Success
File C:\Temp\Source\TestApp\Debug\vc80.pdb
k+1
Process devenv.com
Major Code IRP_MJ_CREATE
Minor Code
Result OBJECT_NAME_NOT_FOUND
File C:\Temp\Target\TestApp\Debug\vc80.pdb

and a whole bunch of other exciting records which I wont bore you with here.
The interesting part is the records concening vc80.pdb

Process devenv.com
Major Code IRP_MJ_NETWORK_QUERY_OPEN
Minor Code
Result OBJECT_NAME_NOT_FOUND
File C:\Temp\Source\TestApp\Debug\vc80.pdb

which occur a number of times down the list of events.
Along with a bunch of

Process devenv.com
Major Code IRP_MJ_NETWORK_QUERY_OPEN
Minor Code
Result OBJECT_PATH_NOT_FOUND
File C:\Temp\Source\TestApp\Debug\vc80.idb

Process devenv.com
Major Code IRP_MJ_NETWORK_QUERY_OPEN
Minor Code
Result OBJECT_PATH_NOT_FOUND
File C:\Temp\source\testapp\debug\stdafx.obj

Process devenv.com
Major Code IRP_MJ_NETWORK_QUERY_OPEN
Minor Code
Result OBJECT_PATH_NOT_FOUND
File C:\Temp\source\testapp\debug\TestAppView.obj

Process devenv.com
Major Code IRP_MJ_NETWORK_QUERY_OPEN
Minor Code
Result OBJECT_PATH_NOT_FOUND
File C:\Temp\source\testapp\debug\TestAppDoc.obj

The result is a compile failure.

Microsoft (R) Visual Studio Version 8.0.50727.762.
Copyright (C) Microsoft Corp 1984-2005. All rights reserved.
------ Build started: Project: TestApp, Configuration: Debug Win32 ------
TestApp : error PRJ0007 : Could not create output directory ‘c:\temp\source\testapp\debug’.
Compiling…
cl : Command line warning D9028 : minimal rebuild failure, reverting to normal build
stdafx.cpp
c:\temp\source\testapp\stdafx.cpp : fatal error C1033: cannot open program database ‘c:\temp\source\testapp\debug\vc80.pdb’
TestApp - 2 error(s), 1 warning(s)

The resulting directory structure looks like this…

C:\Temp\Source\TestApp\
stdafx.h
stdafx.cpp
MyTest.sln
MyTest.vcproj
D:\Temp\Target\TestApp\
Debug
BuildLog.htm
TestApp.exe.embed.manifest
stdafx.h
stdafx.cpp
MyTest.sln
MyTest.vcproj

OK, so a bit of head scratching later I noticed that if I created a \Debug directory in the source, the build works, but unfortunately the source \Debug folder contains the following three files:

C:\Temp\Source\TestApp\Debug
TestApp.pdb
vc80.idb
vc80.pdb

(the destination contains the following files:)

D:\Temp\Target\TestApp\Debug
BuildLog.htm
MainFrm.obj
mt.dep
stdafx.obj
TestApp.exe
TestApp.exe.embed.manifest
TestApp.exe.embed.manifest.res
TestApp.exe.intermediate.manifest
TestApp.ilk
TestApp.obj
TestApp.pch
TestApp.res
TestAppDoc.obj
TestAppView.obj

The events that create the idb

Process devenv.com
Major Code IRP_MJ_NETWORK_QUERY_OPEN
Minor Code
Result Success
File C:\Temp\Source\TestApp\Debug\vc80.idb

Process devenv.com
Major Code IRP_MJ_CREATE
Minor Code
Result Success
File C:\Temp\Source\TestApp\Debug\vc80.idb

Process devenv.com
Major Code IRP_MJ_CREATE
Minor Code
Result OBJECT_NAME_NOT_FOUND
File D:\Temp\Source\TestApp\Debug\vc80.idb

Process devenv.com
Major Code IRP_MJ_CREATE
Minor Code
Result Success
File C:\Temp\Source\TestApp\Debug\vc80.idb

Process devenv.com
Major Code IRP_MJ_CREATE
Minor Code
Result OBJECT_NAME_NOT_FOUND
File D:\Temp\Source\TestApp\Debug\vc80.idb

However all events captured for vc80.pdb fail with OBJECT_PATH_NOT_FOUND, yet it’s still created in Source. Very odd.

So, these pdb, idb files are not being re-directed / re-located correctly, obviously as I’m not intercepting IRP_MJ_NETWORK_QUERY_OPEN (perhaps?) and re-directing it.
Could this be the reason, or is it something more subtle (I suspect so).
Am I missing a re-direction event along the way? Or is this actually indicative of ‘something that’s not possible’?
Some relevant points - My filter is running on WinXP at altitude 40100 as a test in order to try to redirect the filename before any other filters get at it. The result codes shown above are written during PostOp

Apologies for the longish post. I’m wondering whether anyone has come across this type of issue before?
Many thanks

Mike


NTFSD is sponsored by OSR

For our schedule debugging and file system seminars
(including our new fs mini-filter seminar) visit:
http://www.osr.com/seminars

You are currently subscribed to ntfsd as: xxxxx@kerneldrivers.com
To unsubscribe send a blank email to xxxxx@lists.osr.com


Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com
866.263.9295

Hi Peter,
Thanks for your response.
OK, yes I’ve tried notepad and a dos box. I can perform operations like:

c:\temp\source>touch fred.txt
c:\temp\source>mkdir fred
c:\temp\source>rmdir fred
c:\temp\source>dir

and all ops are correctly re-directed to the d:\temp\target without error, apart from the following

c:\temp\source>mkdir fred
c:\temp\source>cd fred
The system cannot find the path specified.

The iop for that event is:

Process: (RootProcess)
MajorCode: IRP_MJ_NETWORK_QUERY_OPEN
MinorCode: -
Result: OBJECT_NAME_NOT_FOUND
File: c:\temp\Source\fred

This is somewhat unsurprising, as the iop major code is not being redirected.
I’ve also tried the following experiment:

File: c:\temp\Source\fred.txt
Content: Bad!
File: d:\temp\Target\fred.txt
Content: Good!

Fire up a DOS box, set the API params correctly to watch the DOS process and children, then type
c:\temp\source>notepad fred.txt

notepad loads the file showing Good!
Edit the file, adding Grief! and save. Have a look via Explorer, d:\temp\Target\fred.txt shows Good!Grief!

My redirection code performs an update on the filename, either by using the same buffer if there’s enough space, or by freeing that buffer and providing a new non paged pool buffer. Apart from the file overwrite, the code performs

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

FltSetCallbackDataDirty( pData );

// I think that if you are setting STATUS_REPARSE then you are completing the
// IRP and need to return FLT_PREOP_COMPLETE. The IO Manager will then start
// all over with the new file name/path.
// You have to return FLT_PREOP_COMPLETE. If you return
// FLT_PREOP_SUCCESS_WITH_CALLBACK, the I/O operation won’t be restarted.

return FLT_PREOP_COMPLETE;
}

Obviously the file overwrite is important. I have a whole slew of unit tests in a (simulated kernel) usermode sandbox for checking redirect file function, to test as many combinations as I can imagine. The results suggest the new pathname is formed correctly with all '' chars correctly maintained.

However, all as indicated in the first post, the iop events registered on the file vc80.pdb are all
IRP_MJ_NETWORK_QUERY_OPEN
and hence currently have nothing to do with my redirect code, as the redirect code only gets called for IRP_MJ_CREATE. Granted the file redirect code might have some indirect effect perhaps?

Cheers

  • Mike

Ah, of course IRP_MJ_NETWORK_QUERY_OPEN is a fast io operation.
Preventing fast io via a PreOp { return FLT_PREOP_DISALLOW_FASTIO; } isn’t a solution.
One would need to perform some action to re-direct the fastio, however this is perhaps disallowed?

xxxxx@scee.net wrote:

Hi Peter,
Thanks for your response.
OK, yes I’ve tried notepad and a dos box. I can perform operations like:

c:\temp\source>touch fred.txt
c:\temp\source>mkdir fred
c:\temp\source>rmdir fred
c:\temp\source>dir

and all ops are correctly re-directed to the d:\temp\target without error, apart from the following

c:\temp\source>mkdir fred
c:\temp\source>cd fred
The system cannot find the path specified.

The iop for that event is:

Process: (RootProcess)
MajorCode: IRP_MJ_NETWORK_QUERY_OPEN

As you probably know, this is not truly an IRP based operation but a
FastIo operation. Use the FLT_IS_FASTIO_OPERATION macro and fail it with
FLT_PREOP_DISALLOW_FASTIO. This will force the request down through the
IRP_MJ_CREATE handler instead. Of course eventually you will want to
handle this request correctly and only fail it for requests you are
interested in but failing all Fast IO operations for your initial
implementation is fine.

Pete

MinorCode: -
Result: OBJECT_NAME_NOT_FOUND
File: c:\temp\Source\fred

This is somewhat unsurprising, as the iop major code is not being redirected.
I’ve also tried the following experiment:

File: c:\temp\Source\fred.txt
Content: Bad!
File: d:\temp\Target\fred.txt
Content: Good!

Fire up a DOS box, set the API params correctly to watch the DOS process and children, then type
c:\temp\source>notepad fred.txt

notepad loads the file showing Good!
Edit the file, adding Grief! and save. Have a look via Explorer, d:\temp\Target\fred.txt shows Good!Grief!

My redirection code performs an update on the filename, either by using the same buffer if there’s enough space, or by freeing that buffer and providing a new non paged pool buffer. Apart from the file overwrite, the code performs

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

FltSetCallbackDataDirty( pData );

// I think that if you are setting STATUS_REPARSE then you are completing the
// IRP and need to return FLT_PREOP_COMPLETE. The IO Manager will then start
// all over with the new file name/path.
// You have to return FLT_PREOP_COMPLETE. If you return
// FLT_PREOP_SUCCESS_WITH_CALLBACK, the I/O operation won’t be restarted.

return FLT_PREOP_COMPLETE;
}

Obviously the file overwrite is important. I have a whole slew of unit tests in a (simulated kernel) usermode sandbox for checking redirect file function, to test as many combinations as I can imagine. The results suggest the new pathname is formed correctly with all '' chars correctly maintained.

However, all as indicated in the first post, the iop events registered on the file vc80.pdb are all
IRP_MJ_NETWORK_QUERY_OPEN
and hence currently have nothing to do with my redirect code, as the redirect code only gets called for IRP_MJ_CREATE. Granted the file redirect code might have some indirect effect perhaps?

Cheers

  • Mike

NTFSD is sponsored by OSR

For our schedule debugging and file system seminars
(including our new fs mini-filter seminar) visit:
http://www.osr.com/seminars

You are currently subscribed to ntfsd as: xxxxx@kerneldrivers.com
To unsubscribe send a blank email to xxxxx@lists.osr.com


Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com
866.263.9295

xxxxx@scee.net wrote:

Ah, of course IRP_MJ_NETWORK_QUERY_OPEN is a fast io operation.
Preventing fast io via a PreOp { return FLT_PREOP_DISALLOW_FASTIO; } isn’t a solution.
One would need to perform some action to re-direct the fastio, however this is perhaps disallowed?

Disallowing the FastIO will simply force the IO manager to send the IRP
based equivalent to you, which you can then redirect.

Pete


NTFSD is sponsored by OSR

For our schedule debugging and file system seminars
(including our new fs mini-filter seminar) visit:
http://www.osr.com/seminars

You are currently subscribed to ntfsd as: xxxxx@kerneldrivers.com
To unsubscribe send a blank email to xxxxx@lists.osr.com


Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com
866.263.9295

How do you get the source full path? Probably you missed some file paths
which causes your redirection failure.

Shangwu

wrote in message news:xxxxx@ntfsd…
> Hi Peter,
> Thanks for your response.
> OK, yes I’ve tried notepad and a dos box. I can perform operations like:
>
> c:\temp\source>touch fred.txt
> c:\temp\source>mkdir fred
> c:\temp\source>rmdir fred
> c:\temp\source>dir
>
> and all ops are correctly re-directed to the d:\temp\target without error,
> apart from the following
>
> c:\temp\source>mkdir fred
> c:\temp\source>cd fred
> The system cannot find the path specified.
>
> The iop for that event is:
>
> Process: (RootProcess)
> MajorCode: IRP_MJ_NETWORK_QUERY_OPEN
> MinorCode: -
> Result: OBJECT_NAME_NOT_FOUND
> File: c:\temp\Source\fred
>
> This is somewhat unsurprising, as the iop major code is not being
> redirected.
> I’ve also tried the following experiment:
>
> File: c:\temp\Source\fred.txt
> Content: Bad!
> File: d:\temp\Target\fred.txt
> Content: Good!
>
> Fire up a DOS box, set the API params correctly to watch the DOS process
> and children, then type
> c:\temp\source>notepad fred.txt
>
> notepad loads the file showing Good!
> Edit the file, adding Grief! and save. Have a look via Explorer,
> d:\temp\Target\fred.txt shows Good!Grief!
>
> My redirection code performs an update on the filename, either by using
> the same buffer if there’s enough space, or by freeing that buffer and
> providing a new non paged pool buffer. Apart from the file overwrite, the
> code performs
>
> {
> pData->IoStatus.Status = STATUS_REPARSE;
> pData->IoStatus.Information = IO_REPARSE;
> pData->Iopb->TargetFileObject->RelatedFileObject = NULL;
>
> FltSetCallbackDataDirty( pData );
>
> // I think that if you are setting STATUS_REPARSE then you are completing
> the
> // IRP and need to return FLT_PREOP_COMPLETE. The IO Manager will then
> start
> // all over with the new file name/path.
> // You have to return FLT_PREOP_COMPLETE. If you return
> // FLT_PREOP_SUCCESS_WITH_CALLBACK, the I/O operation won’t be restarted.
>
> return FLT_PREOP_COMPLETE;
> }
>
> Obviously the file overwrite is important. I have a whole slew of unit
> tests in a (simulated kernel) usermode sandbox for checking redirect file
> function, to test as many combinations as I can imagine. The results
> suggest the new pathname is formed correctly with all '' chars correctly
> maintained.
>
> However, all as indicated in the first post, the iop events registered on
> the file vc80.pdb are all
> IRP_MJ_NETWORK_QUERY_OPEN
> and hence currently have nothing to do with my redirect code, as the
> redirect code only gets called for IRP_MJ_CREATE. Granted the file
> redirect code might have some indirect effect perhaps?
>
> Cheers
>
> - Mike
>
>

Hi,

Shangwu:
I currently get the filepath from Data->Iopb->TargetFileObject. If there’s another one that I’ve
missed, then that’s no doubt an error.

Peter:
Sorry for the slow response. I’ve been trying to iron out what’s going on via long debug sessions.
Your suggestion of disallowing fastio is a good one. I was already doing that but only very
late on inside the MJ_CREATE handler when determining that I was actually about to re-direct the
io event, rather than blocking fast io for all events, which is obviously not a production thing.

But as you say, I’ll try to get a simple version working first then make it more sophisicated later.
So, for the moment, I’ve added a fastio trap at the top of my PreOp(). This does re-issue the
io event as non fast io event which is nice.

<…a lot of time passes…>
After 2 days of debugging, and reviewing quite a lot of things I thought might be a problem about
the file redirection code, I’ve managed to find and fix a problem in my process tracking code.
This meant that when a parent process died, and its children were promoted to siblings, my internal
tracking was not reflecting this change correctly, causing re-direction to be missed.
Fixing this simple error, and voila, suddenly all is well.

Thanks for your feedback!

Mike

>I currently get the filepath from Data->Iopb->TargetFileObject. If there’s

another one that I’ve
missed, then that’s no doubt an error.

You need to use FltGetFilenameInformation instead. Request the opened name if you do not care to normalize the name.

Sarosh
File System Filter Lead
Microsoft Corp

This posting is provided “AS IS” with no warranties, and confers no Rights

Hi Sarosh,

I’m not entirely sure I understand your point there. Are you saying it’s invalid to relocate a pData->Iopb->TargetFileObject.FileName, based on the filename in that field? i.e.

In FileName: \Temp\Source\Fred.txt
->
Out FileName: \Device\HarddiskVolume1\Temp\Target\Fred.txt

I can only assume therefore you mean, one should always call FltGetFilenameInformation()
e.g.

status = FltGetFileNameInformation( pData,
FLT_FILE_NAME_NORMALIZED |
FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP,
&pFileNameInformation );
#if IVFS_NOT_W2K
if (!NT_SUCCESS(status))
{
status = FltGetFileNameInformation( pData,
FLT_FILE_NAME_OPENED |
FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP,
&pFileNameInformation);
}
#endif

and use the returned filename, relocated, as a replacement in TargetFileObject.FileName? Is that what you meant? I assume I’m missing some very important filename mechanics using the raw FileName field?

Thanks for your comment

Mike

PS, further information about my tracking of VisualStudio and relocating builds. It turns out (obvious to those in the know of course), mspdbsrv.exe is causing *issues* with my simple (lets face it, naive) concept of tracking child processes of a root process id. It seems the .pdb server for VS2005 likes to hang around as a root process after the compile is complete. Running another compile will re-use the running pdb server (whose parent pid is now 0), and therefore it is not picked up as a process that requires it’s iop events to be relocated. Is there some form of open pipe that can be tracked at mini filter level to determin that work done by this server exe is connected with work done by child processes spawned by VcBuildHelper, cl, link or devenv.exe. I assume its link.exe which is talking to the already running pdb server. Anywayz, that’s why on occassions I still get vc80.pdb in Source rather than Target. I do not wish to add any special case code of course, as that certainly would be foolish.

Yes - your understanding is correct. You should use FltGetFileNameInformation to query for the file name as opposed to using the name directly in FILE_OBJECT::FileName.

status = FltGetFileNameInformation( Cbd,
FLT_FILE_NAME_OPENED |
FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP,
&nameInfo );

The API handles all the cases correctly for retrieving the name. For example, relative file opens.

In W7 and beyond, you may use a new API IoReplaceFileObjectName, to replace the name in the FILE_OBJECT without having verifier complain that you are leaking pool when you unload or freeing memory that you did not allocate.

Also have you considered using the reparse mechanism to redirect the name? To do this you replace the name in the FILE_OBJECT and then request IO manager to reparse to the new location.

//
// Reparse the open
//

Cbd->IoStatus.Status = STATUS_REPARSE;
Cbd->IoStatus.Information = IO_REPARSE;
callbackStatus = FLT_PREOP_COMPLETE;

The W7 WDK has a sample that demonstrates this. The sample will work downlevel on any platform that supports fltmgr.

Sarosh
File System Filter Lead
Microsoft Corp

This posting is provided “AS IS” with no warranties, and confers no Rights

Hi Sarosh,

Thanks for the info. I’ve upated my code now to use FltGetFilenameInformation, and FltParseFileNameInformation.

Also have you considered using the reparse mechanism to redirect the name?

Yes, (ref message 3 in this thread).
I also add

pData->Iopb->TargetFileObject->RelatedFileObject = NULL;

which is recommended in another thread on this site. I assume this is a sensible valid action.

Cheers

Mike