Cannot get the filename in pre-create on Win7 if the file is opened by ID

I am seeing a problem with FltGetFileNameInformation on Windows 7. I attempt to get the file name when the SearchIndexer is opening the file by ID (see stack below). In
pre-create I make the following call:

PFLT_FILE_NAME_INFORMATION pffniFileNameInfo = NULL;

ntStat = FltGetFileNameInformation(Data, FLT_FILE_NAME_OPENED|
FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP,
&pffniFileNameInfo);
if(!NT_SUCCESS(ntStat) || (NULL == pffniFileNameInfo))
{
NT_ASSERT(FALSE);//failed to get file name

If fails with STATUS_INVALID_PARAMETER. I have tried getting the normalized
name also and I get the same error.

fffff88001002027 : fffffa80023b10c0 fffff880022a75b8 fffff880022a7590
fffff8000284f888 : ssfmonm!FmonPreCreateCallback+0x2aa [c:\development\webroot\products\spysweeper\core\core++main\sys\fmonmini\fmfilter .c @ 448] fffff880010048ca : fffffa80024fa400 fffffa80024fa400 fffffa8000faf500 fffffa8000fb5800 : fltmgr!FltpPerformPreCallbacks+0x2f7
fffff880010222a3 : fffffa8002319590 fffffa8002319590 fffffa8002319590
fffffa806d4e6f49 : fltmgr!FltpPassThroughInternal+0x4a fffff800029c2477 : 0000000000000004 fffff800029e6080 fffffa8002320010 0000000000000000 : fltmgr!FltpCreate+0x293
fffff800029b850f : fffffa8000faf5a0 0000000000000000 fffffa800214b110
0000000002000001 : nt!IopParseDevice+0x5a7 fffff800029bd876 : fffffa800214b110 fffff880022a7a30 fffffa8000000040 fffffa8000d0bde0 : nt!ObpLookupObjectName+0x32f
fffff800029c4587 : fffffa8002319590 0000000000000001 fffffa80024f1d01
fffffa80024f2e20 : nt!ObOpenObjectByName+0x306 fffff800029ce198 : 000000000321e168 0000000000100080 fffffa8000000000 000000000321e110 : nt!IopCreateFile+0x2b7
fffff800026c1153 : 0000000000000000 fffff800029dbdfc fffff880022a7ca0
0000000000000000 : nt!NtCreateFile+0x78 00000000772f040a : 00000000770d08f8 0000000001641750 000007fef5ac1fce 000007fe00000000 : nt!KiSystemServiceCopyEnd+0x13
00000000770d08f8 : 0000000001641750 000007fef5ac1fce 000007fe00000000
000007fef5ac6f36 : ntdll!ZwCreateFile+0xa 000007fef5b0aa3c : 000000000321e830 0000000000000002 000000000321f860 000007fef5ac7e8f : kernel32!OpenFileById+0x158
000007fef5b0ab7b : 000000000321e5c0 0000000000000001 0000000000000001
00000000012a05c0 : MSSRCH!CFRNCache::_FRNToPath+0xa6 000007fef5b0b182 : 000000000167b350 0000000000000000 002f003a0043003a 0000000000bea670 : MSSRCH!CFRNCache::_CacheFromRecord+0x47
000007fef5ac9649 : 0000000000be9df0 00000000772f4e44 000000000321f860
00000000015f6e50 : MSSRCH!CFRNCache::Lookup+0x347 000007fef5ac9467 : 0000000002f6cc30 0000000000000000 00000000015f6db0 000000000321f860 : MSSRCH!CUsnMonitorNotifier::lokProcessUsnRecord+0x26f
000007fef5aeb0ec : 0000000000000000 0000000000bea490 0000000000000000
0000000000000000 : MSSRCH!CUsnMonitorNotifier::Thread+0xa60 000000007709f56d : 0000000000bea490 0000000000000000 0000000000000000 0000000000000000 : MSSRCH!CUsnMonitorNotifier::MonitorThreadStatic+0x30
00000000772d3281 : 0000000000000000 0000000000000000 0000000000000000
0000000000000000 : kernel32!BaseThreadInitThunk+0xd 0000000000000000 : 0000000000000000 0000000000000000 0000000000000000 0000000000000000 : ntdll!RtlUserThreadStart+0x1d

The most common thing where FltGetFileNameInformation returns STATUS_INVALID_PARAMETER is calling with the third parameter NULL. That’s not the case here however…

Unfortunately the stack below doesn’t help much to figure out what went wrong at that time… COuld you please run this on a checked build with verifier enabled for both filter manager and your minifilter, maybe something will show up ?

The only other thing I can think of is that if this happens only with the SearchIndexer, maybe it has something to do with oplocks. Did you try to see if the code works with defrag (which uses opens by ID but no oplocks as far as i know)?

Regards,
Alex.
This posting is provided “AS IS” with no warranties, and confers no rights.

When I run defrag it fails but with STATUS_ACCESS_DENIED rather than STATUS_INVALID_PARAMETER.

I can try to install a checked build of Windows 7 but I use a VM to debug with and I have not been able to get any checked build installed as a VM (VmWare) so far.

RetAddr : Args to Child : Call Site
fffff880010d9027 : fffffa80015703b0 fffff880042e05b8 fffff880042e0590 fffff80002854888 : ssfmonm!FmonPreCreateCallback+0x2aa [c:\development\webroot\products\spysweeper\core\core++main\sys\fmonmini\fmfilter.c @ 448] fffff880010db8ca : fffffa800152db00 fffffa800152db00 fffffa8000fd1100 fffffa8000fd3300 : fltmgr!FltpPerformPreCallbacks+0x2f7
fffff880010f92a3 : fffffa8001beac60 fffffa8001beac60 fffffa8001beac60 fffffa806d4e6f49 : fltmgr!FltpPassThroughInternal+0x4a fffff800029c7477 : 0000000000000004 fffff800029eb080 fffffa8002048810 0000000000000000 : fltmgr!FltpCreate+0x293
fffff800029bd50f : fffffa8000fd1180 0000000000000000 fffffa800207f8b0 fffffa80014c5101 : nt!IopParseDevice+0x5a7 fffff800029c2876 : fffffa800207f8b0 fffff880042e0a30 fffff8a000000040 fffffa8000d0bde0 : nt!ObpLookupObjectName+0x32f
fffff800029c9587 : 00000000000007ff 0000000000000001 fffffa8001be9701 0000000000000180 : nt!ObOpenObjectByName+0x306 fffff800029e22a4 : 000000000147e5c0 fffff8a000100080 fffff8a001efe670 000000000147e5e0 : nt!IopCreateFile+0x2b7
fffff800026c6153 : fffffa8001b90b30 0000000000000001 fffffa800207ab60 fffff800029da094 : nt!NtOpenFile+0x58 00000000771d01ea : 000007fef2c18970 0002000000000002 0000000000000188 000000000147e768 : nt!KiSystemServiceCopyEnd+0x13
000007fef2c18970 : 0002000000000002 0000000000000188 000000000147e768 0000000000010000 : ntdll!ZwOpenFile+0xa 000007fef2c19c3b : ffffffffffffffff 0000000001680060 000000000168007c 0000000000000000 : defragsvc!FsOpenFileByFileID+0x164
000007fef2c17923 : ffffffffffffffff ffffffffffffffff 0000000000000001 ffffffffffffffff : defragsvc!CNtfsVolume::_GetHandleToFile+0x23f 000007fef2c1619f : 000000000147e9f8 000000000147eb10 000000000147e9b8 000000000147e9f8 : defragsvc!CNtfsVolume::_GetFile+0x4b7
000007fef2c0a488 : 0000000000178a90 000000000017bbb0 0000000089000017 0000000000000000 : defragsvc!CNtfsVolume::GetNextFile+0xbb 000007fef2c08b09 : 0000000000000000 0000000000000000 0000000000000000 0000000000000001 : defragsvc!CRunAnalysis::RunOperation+0x954
000007fef2c0e154 : 0000000000000000 0000000000000000 0000000000178a90 000000000017bbb0 : defragsvc!CDefragOperation::Run+0x1d5 000007fef2c08b09 : 0000000000178680 0000000000178680 0000000000000000 0000000000000000 : defragsvc!CRunDefragFull::RunOperation+0x1e4
000007fef2bfb3c9 : 0000000000000000 0000000000000000 0000000000177d60 0000000000000000 : defragsvc!CDefragOperation::Run+0x1d5 000007fef2bfbcbb : 0000000000177d60 000007fef2bfbca4 000007fef2bfbca4 0000000000000000 : defragsvc!CDefragAsyncWorker::InvokeRunnable+0xc9

Since you are doing the name normalization in the context of the issuing thread and it is possible that it doesn’t have traverse privileges, you might get STATUS_ACCESS_DENIED for open-by-ID creates.

Quote from MSDN:
If the user opened the file by file ID but does not have traverse privileges for the entire path, FltGetFileNameInformation fails with this return value.
STATUS_ACCESS_DENIED is an error code.

Could you try something like querying on a different thread with traverse privileges or adding traverse privileges to the current thread (which is probably not a good idea in a product, but should be fine for testing only…) ? I would check if this works with SearchIndexer as well, just to make sure.

Would it be possible to query the name in postCreate for files opened by ID ? Not sure what the architecture of the application is but from a performance perspective this would be slightly better.

Regards,
Alex.
This posting is provided “AS IS” with no warranties, and confers no rights.

There are some cases where I need to have the name in post-create when the create failed. This is why I am getting the name in pre-create now. I may be able to massage to code to handle open by ID as a special case but it would be much better if getting the name in pre-create would work in this case.

I will try adding the traverse privilege when I get some time - it is not the highest priority for me right at the moment.

Another problem with getting the name in post-create has do do with redirection (like the simrep example). How can you redirect an open by ID if you cannot get the name in pre-create?

As I said before I’m not familiar with the architecture of your filter. There are filters where the name query can be performed in postCreate without any issues while this is not an option for others. If it works for you, then you get some perf back.

Simrep has numerous other issues, it was not intended as a working minifilter sample but rather as an example on how to return STATUS_REPARSE and how to use IoReplaceFileObjectName. Redirecting an open-by-ID might lead to many other issues, beyond the scope of SimRep.

On an unrelated note, we are constantly trying to figure out which approach to take. Should we write samples that are complete and that work well in all possible cases (which are basically products) or samples that just showcase some particular feature or behavior of the system, but do not handle all the possible cases ? The first approach has some major drawbacks: the code can become very complex and the message might get distorted while also requiring a lot of resources which means we would release such a sample every couple of years (not to mention what releasing what amounts to full product source code would do to the community). The second approach needs a lot less resources and might make things clear, but people that study it will undoubtedly find the problems that it doesn’t address.

It is clear to me that either choice will upset someone. We receive mails that complain either that fastfat is too complicated and it isn’t clear from it which things are important or that the samples are too simple and they never show any of the really hard stuff.

Regards,
Alex.
This posting is provided “AS IS” with no warranties, and confers no rights.