April 11th, 2024

Why do STANDARD_RIGHTS_READ, STANDARD_RIGHTS_WRITE, and STANDARD_RIGHTS_EXECUTE have the same values?

Windows defines values for the access rights STANDARD_RIGHTS_READ, STANDARD_RIGHTS_WRITE, and STANDARD_RIGHTS_EXECUTE. But if you look at their definitions, they are all defined to be the same thing, namely, READ_CONTROL. How can this possibly make sense? Certainly read, write, and execute rights should be different, shouldn’t they?

They should, but that’s not what the STANDARD_RIGHTS_* values are for.

What these values are trying to say is “Every securable object should include STANDARD_RIGHTS_READ in their generic read access mask, STANDARD_RIGHTS_WRITE in their generic write access mask, and STANDARD_RIGHTS_EXECUTE in their generic execute access mask.” Confusingly, STANDARD_RIGHTS_ALL is just a mask of all the standard rights, not the “mask that must be present in the generic all access mask.” It is STANDARD_RIGHTS_REQUIRED that you have to put in your generic all access mask.

For example, the file access rights are defined as

#define FILE_GENERIC_READ         (STANDARD_RIGHTS_READ     |\
                                   FILE_READ_DATA           |\
                                   FILE_READ_ATTRIBUTES     |\
                                   FILE_READ_EA             |\
                                   SYNCHRONIZE)


#define FILE_GENERIC_WRITE        (STANDARD_RIGHTS_WRITE    |\
                                   FILE_WRITE_DATA          |\
                                   FILE_WRITE_ATTRIBUTES    |\
                                   FILE_WRITE_EA            |\
                                   FILE_APPEND_DATA         |\
                                   SYNCHRONIZE)


#define FILE_GENERIC_EXECUTE      (STANDARD_RIGHTS_EXECUTE  |\
                                   FILE_READ_ATTRIBUTES     |\
                                   FILE_EXECUTE             |\
                                   SYNCHRONIZE)

#define FILE_ALL_ACCESS           (STANDARD_RIGHTS_REQUIRED |\
                                   SYNCHRONIZE              |\
                                   0x1FF)

const GENERIC_MAPPING FileGenericMapping =
{
    FILE_GENERIC_READ,
    FILE_GENERIC_WRITE,
    FILE_GENERIC_EXECUTE,
    FILE_ALL_ACCESS,
};

The “generic read” file access includes STANDARD_RIGHTS_READ, plus any other read rights specific to files. Similarly for “write”, “execute”, and “all” access.

Now, it so happens that the only mandatory access right for read, write, and execute is READ_CONTROL, so that’s why all three of the macros expand to the same underlying value.

But you weren’t supposed to care about that. Just include the corresponding standard rights in each of the four levels of access, and you’re all set.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

3 comments

Discussion is closed. Login to edit/delete existing comments.

  • Ian Boyd

    I was recently adding access controls to an application, and i was wrining my hands about whether or not users should be allowed to see the DACL.

    “If they see the DACL; then they could see the names of other users! Oh nose!”

    Then i calmed down; because if it’s good enough for Windows NT, and it’s C2 security rating, then it’s good enough for a LoB application.

  • Joshua Hudson

    For a fun time, set a deny ACL for SYNCHRONIZE for some file and watch things explode.

    It's very easy to do this by accident when trying to deny write permission to a file with a deny rule. Some of the builtin windows tools (either presently do or used to) do it by using the macros to construct the deny ACL and FILE_GENERIC_WRITE contains SYNCHRONIZE.

    If you don't have SYNCHRONIZE, some programs work opening the file for...

    Read more
    • Ian Boyd

      It probably fails for applications that try to wait on the file handle.