Override FileSystemName in FILE_FS_ATTRIBUTE_INFORMATION

I’m using the template mini-filter driver from Visual Studio 2013 to try and override the file system name of all mounted network drives.

The problem I am having is that the custom file system name I want to set is a different length to the original value (NTFS). E.g. If I set FileSystemName to ‘CUSTOM’, and set the length accordingly, Windows is displaying the result as ‘CUST??’, where the final two characters are rubbish that changes every time.

Below is the post-op callback for IRP_MJ_QUERY_VOLUME_INFORMATION:

FLT_POSTOP_CALLBACK_STATUS
CustomPostOpQueryVolumeInformation(
Inout PFLT_CALLBACK_DATA Data,
In PCFLT_RELATED_OBJECTS FltObjects,
In_opt PVOID CompletionContext,
In FLT_POST_OPERATION_FLAGS Flags
)
{
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
UNREFERENCED_PARAMETER(Flags);

switch (Data->Iopb->Parameters.QueryVolumeInformation.FsInformationClass)
{
case FileFsAttributeInformation:

CustomFsAttributeInformation(
Data->Iopb->Parameters.QueryVolumeInformation.Length,
Data->Iopb->Parameters.QueryVolumeInformation.VolumeBuffer,
Data->IoStatus);

FltSetCallbackDataDirty(Data);

break;

default:
break;
}

return FLT_POSTOP_FINISHED_PROCESSING;
}

And the method which is making the change:

NTSTATUS
CustomFsAttributeInformation(
ULONG VolumeBufferLength,
PVOID VolumeBuffer,
IO_STATUS_BLOCK IoStatus
)
{
PFILE_FS_ATTRIBUTE_INFORMATION SystemBuffer;
PFILE_FS_ATTRIBUTE_INFORMATION Buffer;
ULONG fsFlags;
LONG maxComponentLength;
ULONG RequiredLength;

SystemBuffer = (PFILE_FS_ATTRIBUTE_INFORMATION)VolumeBuffer;

fsFlags = SystemBuffer->FileSystemAttributes;
maxComponentLength = SystemBuffer->MaximumComponentNameLength;

RtlZeroMemory(VolumeBuffer, VolumeBufferLength);

if (VolumeBufferLength < sizeof(PFILE_FS_ATTRIBUTE_INFORMATION))
{
return STATUS_INFO_LENGTH_MISMATCH;
}

Buffer = (PFILE_FS_ATTRIBUTE_INFORMATION) VolumeBuffer;

Buffer->FileSystemAttributes = fsFlags;
Buffer->MaximumComponentNameLength = maxComponentLength;
Buffer->FileSystemNameLength = 12;

RequiredLength = sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 12 - sizeof(WCHAR);

if (VolumeBufferLength < RequiredLength) {
IoStatus.Information = sizeof(FILE_FS_ATTRIBUTE_INFORMATION);
return STATUS_BUFFER_OVERFLOW;
}

RtlCopyMemory(Buffer->FileSystemName, L"CUSTOM", 12);

IoStatus.Information = RequiredLength;

return STATUS_SUCCESS;
}

I’ve tried a couple of different approaches, with pre and post-op, and different methods of changing the FileSystemName value, but all end up with the same result, where only the first 4 characters are changed.

Am I on the right track here?

Cheers,
Matt

> I’ve tried a couple of different approaches, with pre and post-op, and different methods

of changing the FileSystemName value, but all end up with the same result, where only
the first 4 characters are changed.

Am I on the right track here?

yes, but

RtlZeroMemory(VolumeBuffer, VolumeBufferLength);

if (VolumeBufferLength < sizeof(PFILE_FS_ATTRIBUTE_INFORMATION))

Its usually considered polite to check the length of the output buffer before you scribble on it …

Also the test is wrong: you are measuring the length of the pointer (4 or 8 bytes) when you should be checking for
the length of the *structure* *PLUS* and space needed for the name (look at the structure definition)

if (VolumeBufferLength < (FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName) + 12)) {

(or “sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 12”, which is 2 bytes too longer but more obvious to understand.)

  1. You need to tell the upper layers how much valid buffer you have returned.

IoStatus.Information = sizeof(FILE_FS_ATTRIBUTE_INFORMATION)

That needs to be “(FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName) + 12))” (or the sizeof thing again - the returned space can be larger than the buffer, but not smaller)

Somebody once noticed that Windows shell has the hardcoded names for Windows FSs somewhere, and make some decisions based on this.


Maxim S. Shatskih
Microsoft MVP on File System And Storage
xxxxx@storagecraft.com
http://www.storagecraft.com

wrote in message news:xxxxx@ntfsd…
> I’m using the template mini-filter driver from Visual Studio 2013 to try and override the file system name of all mounted network drives.
>
> The problem I am having is that the custom file system name I want to set is a different length to the original value (NTFS). E.g. If I set FileSystemName to ‘CUSTOM’, and set the length accordingly, Windows is displaying the result as ‘CUST??’, where the final two characters are rubbish that changes every time.
>
> Below is the post-op callback for IRP_MJ_QUERY_VOLUME_INFORMATION:
>
>
> FLT_POSTOP_CALLBACK_STATUS
> CustomPostOpQueryVolumeInformation(
> Inout PFLT_CALLBACK_DATA Data,
> In PCFLT_RELATED_OBJECTS FltObjects,
> In_opt PVOID CompletionContext,
> In FLT_POST_OPERATION_FLAGS Flags
> )
> {
> UNREFERENCED_PARAMETER(FltObjects);
> UNREFERENCED_PARAMETER(CompletionContext);
> UNREFERENCED_PARAMETER(Flags);
>
> switch (Data->Iopb->Parameters.QueryVolumeInformation.FsInformationClass)
> {
> case FileFsAttributeInformation:
>
> CustomFsAttributeInformation(
> Data->Iopb->Parameters.QueryVolumeInformation.Length,
> Data->Iopb->Parameters.QueryVolumeInformation.VolumeBuffer,
> Data->IoStatus);
>
> FltSetCallbackDataDirty(Data);
>
> break;
>
> default:
> break;
> }
>
> return FLT_POSTOP_FINISHED_PROCESSING;
> }
>
>
> And the method which is making the change:
>
>
> NTSTATUS
> CustomFsAttributeInformation(
> ULONG VolumeBufferLength,
> PVOID VolumeBuffer,
> IO_STATUS_BLOCK IoStatus
> )
> {
> PFILE_FS_ATTRIBUTE_INFORMATION SystemBuffer;
> PFILE_FS_ATTRIBUTE_INFORMATION Buffer;
> ULONG fsFlags;
> LONG maxComponentLength;
> ULONG RequiredLength;
>
> SystemBuffer = (PFILE_FS_ATTRIBUTE_INFORMATION)VolumeBuffer;
>
> fsFlags = SystemBuffer->FileSystemAttributes;
> maxComponentLength = SystemBuffer->MaximumComponentNameLength;
>
> RtlZeroMemory(VolumeBuffer, VolumeBufferLength);
>
> if (VolumeBufferLength < sizeof(PFILE_FS_ATTRIBUTE_INFORMATION))
> {
> return STATUS_INFO_LENGTH_MISMATCH;
> }
>
> Buffer = (PFILE_FS_ATTRIBUTE_INFORMATION) VolumeBuffer;
>
> Buffer->FileSystemAttributes = fsFlags;
> Buffer->MaximumComponentNameLength = maxComponentLength;
> Buffer->FileSystemNameLength = 12;
>
> RequiredLength = sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 12 - sizeof(WCHAR);
>
> if (VolumeBufferLength < RequiredLength) {
> IoStatus.Information = sizeof(FILE_FS_ATTRIBUTE_INFORMATION);
> return STATUS_BUFFER_OVERFLOW;
> }
>
> RtlCopyMemory(Buffer->FileSystemName, L"CUSTOM", 12);
>
> IoStatus.Information = RequiredLength;
>
> return STATUS_SUCCESS;
> }
>
>
> I’ve tried a couple of different approaches, with pre and post-op, and different methods of changing the FileSystemName value, but all end up with the same result, where only the first 4 characters are changed.
>
> Am I on the right track here?
>
> Cheers,
> Matt
>

> Somebody once noticed that Windows shell has the hardcoded names for

Windows FSs somewhere, and make some decisions based on this.

Not just the windows shell. The world is littered with code which makes
such assumptions…

And it is MS who is to be blamed.

Why there is no “get FS capability flags” API?

“Rod Widdowson” wrote in message news:xxxxx@ntfsd…
>> Somebody once noticed that Windows shell has the hardcoded names for
>> Windows FSs somewhere, and make some decisions based on this.
>
> Not just the windows shell. The world is littered with code which makes
> such assumptions…
>
>

At one point, MSDN contained sample code that demonstrated exactly this technique - using names to determine the file system characteristics.

The worst part of this indignity is that for the file system *it’s the same exact call*. We return both the name of the file system and it’s characteristics in response to the call. Having the caller use the NAME to intuit the CHARACTERISTCS always makes me shake my head.

While the samples are gone and Microsoft has cleaned up many of their own cases (because other file systems support features like streams and security) it’s unlikely the issue will ever truly be eliminated.

Tony
OSR

Thanks Rod, the IoStatus.Information change worked. I’ve also tidied up the other checks as you suggested. Cheers :smiley: