Thursday, March 22, 2012

Some Limitations Using Files Opened By ID

The ability to open files by ID is a pretty nice feature of certain file systems, especially from the perspective of filters. The fact that file IDs are small and fixed in size makes them very suitable for things like storing in fixed-size records or allocating them from lookaside lists. Unfortunately the semantics for files opened by ID are a bit different from the semantics of the same files if they would have been opened by name.

As you can see we again end up talking about names. What is the relationship between a file and it's name ? Technically both the file's ID and a file's name are identifiers for the file. However, they belong to different namespaces, with different rules. The rules can be different between file systems and to keep things simple for the rest of this post I'll stick to talking about NTFS. The file name namespace for example allows multiple names for a file (hardlinks) while the ID namespace does not.

So let's get straight to the interesting bits. The different semantics of the different namespaces can make it so that some operations don't make sense. For example because NTFS allows multiple names for a file if the file is opened by ID and an operation that changes the namespace is attempted, which name should be affected ? To make this very clear, if file \Foo\f.txt and file \Bar\b.txt are hardlinks to the same file and I open the file by ID and I try to rename it, which name should change ? How about if I try a delete ?

Naturally NTFS will return some status codes that hardly describe what is going on and I've spent many hours reviewing code to figure out what I may have done wrong before figuring out that I'm working on a file that was opened by ID and that the particular operation wasn't supported. So here are some operations that I've found to not work when files are opened by ID:

I'm sure the list is not complete and if you have more examples please contribute them through comments and I'll update the list.

Anyway, the main point of this post is to remind (myself mostly :)) that if a request fails in an unexpected way (most likely with STATUS_INVALID_PARAMETER) even though it's working in a lot cases and after you've validated that the parameters are actually good then check if the file might have been opened by ID and if so verify if the operation makes sense on a file opened by ID.

In closing I'll show you how I quickly check that (and showcase the FileTest tool which is simply awesome!):

  1. First create a file (since you can't create a new file by ID) and then close it.
  2. Then get the file ID and click on the "Use" button.
  3. Then just open the file by ID (make sure to change DesiredAccess to match what you're trying to do).
  4. And then finally just try the operation to see if it can work on files opened by ID.