What’s the difference between PathIsSystemFolder and Protected Operating System Files?


The way to detect weird directories that should be excluded from the user interface is to check for the FILE_ATTRIBUTE_HIDDEN and FILE_ATTRIBUTE_SYSTEM attributes being set simultaneously. This is the mechanism used when you uncheck Hide protected operating system files in the Folder Options dialog. (Programmatically, you detect whether the user wants to see protected operating system files by checking the fShow­Super­Hidden member of the SHELL­STATE structure.)

Michael Dunn suggested using Path­Is­System­Folder to detect these special directories, but that is not quite right.

Path­Is­System­Folder is for marking a directory as "This directory has a nondefault UI behavior attached to it. Please consult the desktop.ini file for more information." You do this when your directory is, say, the root of a namespace extension, or it has been subjected to folder customization. Windows uses it to indicate that the directory has a localized name, as well as other funky internal state.

There are two ways to mark a folder as having nondefault UI. One is to set the FILE_ATTRIBUTE_READ­ONLY attribute, and the other is to set the FILE_ATTRIBUTE_SYSTEM attribute.

Either one works, and Path­Is­System­Folder checks for both, returning a nonzero value if either attribute is set.

In its default configuration, Windows uses the read-only flag to mark folders with nondefault UI. However, some applications mistakenly believe that if a directory is marked read-only, then files within the directory cannot be modified. As a result, these applications refuse to let you save your documents onto the desktop, for example. To work around this, you can use the Use­System­For­System­Folders to tell Windows to use the FILE_ATTRIBUTE_SYSTEM attribute instead. Of course, if you do that, you will run into problems with applications which mistakenly believe that if a directory is marked system, then the directory is inaccessible. So you get to pick your poison.

Programmers who wish to mark a folder as having nondefault UI should use the Path­Make­System­Folder function to set the appropriate attribute. That function consults the system policy and sets the attribute that the policy indicates should be used to mark folders with nondefault UI.

Going back to the original question, then: The difference between Path­Is­System­Folder and checking for folders that are marked hidden+system is that they check different things and have different purposes.

Function Test
Path­Is­System­Folder ReadOnly or System
path is protected operating system folder Hidden and System
Comments (17)
  1. Joshua says:

    > However, some applications mistakenly believe that if a directory is marked read-only, then files within the directory cannot be modified

    Turns out it's not so irrational. This was the behavior of older network servers. You got fed a folder listing w/ the RO bit set if you didn't have permission to write there.

  2. jgh says:

    Arrgh! I hate programs that impose their own expectations of what the underlying API is capable of. Things like "I think it is only possible to read the extent of a file, so I'm never going to pass on your call to write the extent of a file", "I think filenames will only ever have 0-9A-z characters in it, so will focibly prevent you using any other characters", "Full paths always start 'd:'", etc etc etc.

    Call The API And Respond To The Returned Status. Repeat while forcing programmer's head into desk in time to the cadence until it gets hammered in.

  3. jgh says:

    > > However, some applications mistakenly believe that if a directory is marked

    > > read-only, then files within the directory cannot be modified

    > Turns out it's not so irrational. This was the behavior of older network servers.

    > You got fed a folder listing w/ the RO bit set if you didn't have permission to

    > write there.

    No reason to prevent the user attempting to save there. Just b****y well do the operation, and display the resultant "directory is write protected" error (of whatever).

  4. JamesJohnston says:

    This smells of trying to reproduce the logic inside shell namespace and you'll never quite get it perfect, because you're not the shell.  What's the bigger picture here?  What is the practical use for this?  It seems to me that you're better off in many cases just using the shell API?

  5. bv1 says:

    Arghh, the just try it and see if you get away with is the source of a lot of issues that I had to deal with for the last 3 years.  The assumption of a network share acting as a safety net fails badly when you have Microsoft + Apple. Not only can other users store things that make it really hard for the other OS, but Macs can store files that will trash Macs. PC's can shoot themselves in the foot also.

    I just wished that each app had been checking itself to see if the name & path was valid as per the OS standards for their machine.  Then at least the issues would have been limited to when both MAC and PCs accessed the same area. That would have been a lot less effort to keep fixed and understandable as to why it was occurring in the first place.

  6. Joshua says:

    @bv1: oh yes the infamous in filename trick.

  7. Scott Brickey says:

    while I imagine that the attributes were reused for performance reasons… I have to wonder, since NTFS has alternate data streams, whether they could be used (with reasonably similar performance), thus eliminating the "magic values" that the attributes provide.

    [Good luck getting Windows 95 to support NTFS alternate data streams. Also, you are increasing an O(1) operation to an O(n) operation due to have to go back to the server to probe for the alternate data stream. -Raymond]
  8. Cesar says:

    @Scott Brickey: the Windows shell aka explorer.exe (which is what does all these "nondefault UI" trickery) already existed back on the Win95 days, which were FAT32 with LFN, so no extended attributes, ACLs or other trickery, and AFAIK no free bits in the directory entries either.

  9. DWalker says:

    @Cesar: "creating a file implies modifying the directory"  Wha?  No, it doesn't.  The directory is actually a file; it doesn't need to be modified in order to create a file "under" the directory.  I can understand the confusion, and it is weird, but that's why we are the elite.  :-)

  10. Erik F says:

    @dave and @Scott Brickey: See support.microsoft.com/…/en-us (from Raymond's last link, which indicates that this has been around since Windows 95); also, USB sticks often have FAT partitions and several NAS devices that I've had to use still pretend that they're FAT.

  11. dave says:

    > The directory is actually a file; it doesn't need to be modified in order to create a file "under" the directory.

    Is this a serious response?  A directory is a file containing a list of files.   You need to write to the directory file to change the list of files that the directory file contains.

    Or have I missed some joke?

  12. Cesar says:

    > However, some applications mistakenly believe that if a directory is marked read-only, then files within the directory cannot be modified. As a result, these applications refuse to let you save your documents onto the desktop, for example.

    Wait. You can *create* new files on a read-only directory??? That's… surprising, to say the least; creating a file implies modifying the directory, and the directory is read-only.

    If Windows really allows creating files on a read-only directory, you might once again have the "programmers raised on Unix being asked to create a Windows application" situation, because on Unix it (as one would expect) is not possible to create a file on a read-only directory:

    $ mkdir foo

    $ chmod -w foo

    $ touch foo/bar

    touch: cannot touch 'foo/bar': Permission denied

    I do agree with the "just try to do the operation and display the resulting error" approach, but it's not always so simple. Saving a file might mean calling third-party code which outputs a generic error message on failure; checking beforehand for common errors (like the target directory not having "create file here" permissions) can give the user a better error message.

    Story time: one program I worked on uses an embedded database engine. A common error on Windows (and only on Windows) is a sharing violation: the embedded database opens the database file exclusively, and fails if some other program (like an antivirus) is holding the file open. My solution: just before calling the embedded database to open the file, I make the program do a CreateFile with the "share nothing" and "open for read and write" flags. If the CreateFile call fails, I display the corresponding Win32 error message to the user.

    (I *also* do a SetFileAttributes beforehand, since we've had enough problems with the database file being read-only due to it being copied from a CD or something like that.)

  13. ch says:

    It's a bad idea to try to predict whether an operation will succeed or fail.

    It may fail for a reason you have not allowed for. For example, you find that a directory appears writable but it's shared from an operating system that has a more complex permissions system and you can't write to it.

    You may block an operation that would have succeeded. This was formerly quite common when programs checked the available disk space and mistakenly reported that there was not enough because there was so much it overflowed their integer representation. It could be that it is effectively impossible to predict such as when the filesystem does compression, whereby the reported free space is either an estmate based on average compression (so the prediction could err either way) or the space for compressed data (which may allow writing a file which is significantly bigger).

    A check creates a TOCTOU race – something may change so you still need to allow for failure even if you have checked perfectly. If you can cope with this, why bother trying to avoid it at all?

  14. Gabe says:

    ch: The reason to check beforehand is so you can get user input before it's too late. Typical code will open a dialog box to prompt a user for a filename. When the dialog box closes, the filename is passed to some function to perform the operation. When the operation fails, you can try to tell the user what happened, but by then it's too late to fix it because the dialog box has closed.

    So now you have to put up a message box and then re-open the file dialog, which is much uglier UI. And of course maybe you've spent some amount of time or resources performing an operation that you could have known ahead of time would not succeed.

  15. dave says:

    >You can *create* new files on a read-only directory??? That's… surprising, to say the least

    Indeed it is surprising.  I believe the true explanation is that there is no such thing as a read-only directory (from the ancient DOS attribute point of view).  That is, the R attribute simply did not apply to directories.

    If I had to characterize the mistake that Unix/Linux programmers (and I are one) make, it would be that they (we) suppose that DOS file attributes are some sort of form of file permissions. They are not.  FAT doesn't have file permissions, and NTFS has proper ACLs.  The R bit was a feature that I suppose prevented 'accidental' deletion of a file on FAT.

    If you don't want files created in your directory, change its ACL.

    Having said that, Explorer's repurposing of the R bit to mean 'special things be here' was a horrible horrible idea. Surely there were better ways?  Since the file system team seems to add bits with abandon(*), couldn't they have given Explorer a new bit?

    (*)Exaggerated for comic effect.

    [Windows 95 needed to run on a classic FAT drive with no long file names, and over existing networks. -Raymond]
  16. AndyCadley says:

    Gabe: But then what happens is you check, the OS says it's fine, some other program does something without your knowledge, you attempt the operation and it fails because of whatever happened in the mean time. So your check gains nothing in reality except making code more difficult to follow and the user interface occasionally doing weird things.

    @bv1: I'd say that's the fault of the server OS not knowing about invalid conditions and providing some sort of workaround for whatever protocol it's implementing if there are differences between it and the host OS's idea of a valid path.

  17. Anonymous Coward says:

    @dave: Linux permissions aren't much better. setuid, setgid, sticky, and the file type are not permissions.

    Also, setuid, setgid, sticky and executable have different meanings on directories than on files (just like read-only does in Windows)

Comments are closed.

Skip to main content