Thursday, June 21, 2012

The Flags of FILE_OBJECTs - Part III

This is the third part in the series about FILE_OBJECT flags. Hopefully the next one will be the last one, I didn't expect this would take this long. Anyway, here is the next set of FILE_OBJECT flags:

  • FO_DIRECT_DEVICE_OPEN - 0x00000800 - this flag indicates that this FILE_OBJECT was the result of a "direct device open". I have already explored this topic in my previous post on Opening Volume Handles in Minifilters. This means that the FILE_OBJECT is in fact a handle to the storage stack volume instead of the file system volume. Please note that this flag is not the same as the FO_VOLUME_OPEN flag (and in fact they're incompatible). This flag isn't really used by file systems at all since the target device is not a file system device but rather the actual storage underneath a file system. As such file system filters will also not be involved in processing FILE_OBJECTs that have this flag set.
  • FO_FILE_MODIFIED - 0x00001000 - this flag indicates that the FILE_OBJECT was used to modify the file. It is primarily used by the file system (to track handles that didn't modify the file or to figure out when it should flush things). As far as I can tell the IO manager doesn't really use it but it will set it. The FastFat sample in the WDK shows in great detail how FO_FILE_MODIFIED is used.
  • FO_FILE_SIZE_CHANGED - 0x00002000 - this flag indicates that the file size was changed using this FILE_OBJECT. This is also primarily used by the file system and the IO manager will only set it. This flag is used in conjunction with FO_FILE_MODIFIED and, like FO_FILE_MODIFIED, the FastFat sample is a great example of a file system uses it.
  • FO_CLEANUP_COMPLETE - 0x00004000 - this flag means that the file system has already processed an IRP_MJ_CLEANUP request on this FILE_OBJECT. There are certain restrictions on which operations are allowed on such FILE_OBJECTs, as can be seen in both the CDFS and FastFat samples. Windows actually uses such FILE_OBJECTs (that have been cleaned up) fairly frequently and thus filters might need to pay attention to this flag in order to be able to figure out which operations might be allowed on it.
  • FO_TEMPORARY_FILE - 0x00008000 - this flag indicates that the file was opened with the FILE_ATTRIBUTE_TEMPORARY. File systems don't seem to do much beyond setting the flag. The consumer of this information is the Cache Manager, that does more aggressive write caching for temporary files (since it's expected that the file will go away anyway and so there is no point in flushing data to disk; please note that memory pressure might require that data gets flushed, it's just that the caching is more aggressive). See the notes under "Caching Behavior" on the page for the CreateFile function.
  • FO_DELETE_ON_CLOSE - 0x00010000 - as noted in my previous post on Using FileModeInformation, I've never seen this flag used anywhere until I looked at the implementation of IopGetModeInformation. So as far as I can tell this flag really isn't used. In the current implementation however it can be read by a query for the FileModeInformation class.
  • FO_OPENED_CASE_SENSITIVE - 0x00020000 - this flag indicates whether name operations on the FILE_OBJECT should be performed in a case-sensitive way or not. This is very important for file system filters that deal with the namespace. This applies not only to filters that change the name space (name providers must know whether to process things in a case-sensitive or in a case-insensitive way) but also for filters that just look at file names and don't actually change anything. There is a related flag that is very important, the SL_CASE_SENSITIVE. I've written multiple posts that mention case sensitivity but the more interesting ones are the one on FILE_OBJECT Names in IRP_MJ_CREATE and the one on Names in Minifilters - Implementing Name Provider Callbacks.
  • FO_HANDLE_CREATED - 0x00040000 - this flag indicates that a handle has been created for the FILE_OBJECT. From the IO manager's perspective the CREATE operation has completed successfully (so it's too late to call FltCancelFileOpen or IoCancelFileOpen). The flag is set after the successful IRP_MJ_CREATE is completed back to the IO manager, in the IopParseDevice function. The documentation for ObOpenObjectByPointer implies that it's only safe to be called for FILE_OBJECTs that have this flag set. I should have mentioned this in my previous post on Duplicating User Mode Handles, but I can see I've only added an ASSERT but didn't explain it.