How to send FSCTL_GET_RETRIEVAL_POINTERS for NTFS metadata files ($Mft,$Bitmap,etc.)

I write a File System Minifilter Driver and during PreWrite callback I need to convert received “offset” value from file based to volume based. I need this conversion for subsequent entry to my volume log file. So I use FSCTL_GET_RETRIEVAL_POINTERS for this purposes:

FLT_PREOP_CALLBACK_STATUS
AAFsPreWrite(
__inout PFLT_CALLBACK_DATA Cbd,
__in PCFLT_RELATED_OBJECTS FltObjects,
__deref_out_opt PVOID* CompletionContext)
{

const PointersBufferSize = 1024;
PointersBuffer = ExAllocatePoolWithTag(PagedPool, PointersBufferSize, AAFS_TEMPORARY_POOL_TAG);
if (NULL == PointersBuffer)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
leave;
}

STARTING_VCN_INPUT_BUFFER StartingVcn = { 0 };
Status = FltFsControlFile(Cbd->Iopb->TargetInstance, Cbd->Iopb->TargetFileObject,
FSCTL_GET_RETRIEVAL_POINTERS, &StartingVcn, sizeof(StartingVcn), PointersBuffer, PointersBufferSize, NULL);

}

It works fine for any files but when I receive the write packet for metadata files like $Mft or $Bitmap I always got STATUS_INVALID_PARAMETER in FSCTL_GET_RETRIEVAL_POINTERS return value.
I’ve already read https://www.osronline.com/showthread.cfm?link=178462 and seems like FSCTL_GET_RETRIEVAL_POINTERS is the best way to get the LCN of NTFS metadata files, but what’s wrong in my case?

This FSCTL should work on metadata files. You can try it with the fsutil
command:

C:\WINDOWS\system32>fsutil file queryextents c:$mft
VCN: 0x0 Clusters: 0xc820 LCN: 0xc0000
VCN: 0xc820 Clusters: 0xc817 LCN: 0xd1e409
VCN: 0x19037 Clusters: 0xc80a LCN: 0x2adc376
VCN: 0x25841 Clusters: 0xcb2f LCN: 0x3368eb2
VCN: 0x32370 Clusters: 0xb092 LCN: 0x7b4b496
VCN: 0x3d402 Clusters: 0x69be LCN: 0x5d5db20

However, I’m not sure about your approach. You certainly are going to have
problems sending this in the paging I/O path. Even in the user path, writes
can extend so the target VCN might not have an LCN allocated for it yet.

If you need to track volume writes then you should be at the volume level.
In the past we have correlated the volume I/O to file I/O with an assist
from a file system filter.

-scott
OSR
@OSRDrivers

Thanks for response.

fsutil looks fine… could it use some another FSCTL for queryextents command?

Since my task is about to migrate from volume level to file filter level, maybe I should just find out the moment when VCN have LCN allocated for sure? For instance, in PostWrite callback or via some postponed workitem?

C:\WINDOWS\system32>fsutil file queryextents c:$mft
VCN: 0x0 Clusters: 0xc820 LCN: 0xc0000
VCN: 0xc820 Clusters: 0xc807 LCN: 0xa2e239
VCN: 0x19027 Clusters: 0xa3d9 LCN: 0x34cde3

C:\WINDOWS\system32>fsutil file queryextents c:$bitmap
Error: Access is denied.

C:\WINDOWS\system32>fsutil file queryextents c:$logfile
Error: Access is denied.

Seems like fsutil (run as Administrator) works not for all metadata files.

ProcMon will pretty much tell you how fsutil works.

It’s internal to the file system. I’m not sure that you could ever always
accurately track the blocks of the file unless you open it exclusive, mark
the file as immovable (FSCTL_MARK_HANDLE/MARK_HANDLE_PROTECT_CLUSTERS), and
then query.

-scott
OSR
@OSRDrivers

1 Like