Q24 How are file IDs and Object IDs used in the file systems? In my filter driver, how do I deal with them?
File IDs are a 64-bit identifier created by the file system to provide a volume-level unique identifier for a given file. The initial purpose behind creating such IDs was to allow certain types of applications (e.g., file servers) to associate a numeric identifier with the file. For example, the stateless NFS file system provides a handle to its clients. If the handle incorporates the file ID, it is possible for the file server to open the file at an arbitrary point in time by using the file ID, rather than by using a path to the file. In Windows 2000, Microsoft introduced the concept of an object ID. Object IDs are created by application programs and are optionally assigned to files by using the FSCTL_SET_OBJECT_ID, FSCTL_GET_OBJECT_ID, and FSCTL_DELETE_OBJECT_ID file system control operations.
To retrieve the file ID for a file, an application program can query the "internal ID" of the file. The application then opens the file using this ID by using the ZwCreateFile API. The Object Attributes structure must specify the handle of an existing (and open) file or directory handle on the volume where the file is located. The name of the file is then the file ID or Object ID and the FILE_OPEN_BY_FILE_ID option must be set. The file system can then use this ID to open the file.
However, not all file systems support opening a file using a file ID or object ID. For example, the FAT file system will generate and return a file ID, but it does not support "open by file ID":
//
// If this is an open by file ID operation, just fail it explicitly. FAT's
// source of fileids is not reversible for open operations.
//
if (BooleanFlagOn( Options, FILE_OPEN_BY_FILE_ID )) {
However, the CDFS example in the IFS Kit does support open by file ID, although it does not support object IDs:
//
// For the open by file ID case we verify the name really contains
// a 64 bit value.
//
} else {
//
// Check for validity of the buffer.
//
if (FileName->Length != sizeof( FILE_ID )) {
return STATUS_INVALID_PARAMETER;
}
}
And thus this will not work if the file ID is 128 bits rather than 64 bits. Only the NTFS file system supports opening a file using both its file ID and its object ID.
The most substantial impact of the use of file IDs for file system filter drivers is the inability to extract a name for the file. For CDFS, a filter can query the file system for the name of the file (using IRP_MJ_QUERY_INFORMATION or IoQueryInformationFile and querying the FileNameInformation attribute of the file) and the file system will always return a name. However, for NTFS there are certain cases when it cannot return a path to the file (where the caller that opened the file does not have traverse privileges, there is no mechanism for NTFS to determine if it is allowed to return the path to the file). Further, even in those cases where it does return a path to the file it is important to note that there may be multiple paths to the file (via hard links) and that the path name returned is only one of the possible names.