A customer wanted to know whether passing GENERIC_ALL as an access mask is effectively equivalent to passing GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE. Specifically, they were interested in the answer to this question with respect to the Create­File function.

Okay, first question first. Is GENERIC_ALL effectively equivalent to GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE?

The answer is "It depends."

Each object decides what these generic access masks mean. Now, the intended use is that GENERIC_READ correspond to whatever "read" access means for an object, GENERIC_WRITE correspond to whatever "write" access means for an object, and GENERIC_EXECUTE correspond to whatever "execute" access means for an object. It's also the intended use that GENERIC_ALL represent whatever access makes the most sense for "all access".

But that's just the intended use. There is nothing physically preventing an object from giving those four generic access masks nonsensical values. Because anybody can make up a generic mapping. Therefore, there's nothing you can guarantee about the relationship between the generic access masks beyond "they are what the object decides they are."

In practice, GENERIC_ALL is at least as big as GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE, but it can be bigger. For example, for files (which is probably what the customer is asking about when they talk about Create­File), the values are defined as follows, in winnt.h:

#define DELETE                           (0x00010000L)
#define READ_CONTROL                     (0x00020000L)
#define WRITE_DAC                        (0x00040000L)
#define WRITE_OWNER                      (0x00080000L)
#define SYNCHRONIZE                      (0x00100000L)

#define STANDARD_RIGHTS_REQUIRED         (0x000F0000L)


#define FILE_READ_DATA            ( 0x0001 )    // file & pipe
#define FILE_LIST_DIRECTORY       ( 0x0001 )    // directory

#define FILE_WRITE_DATA           ( 0x0002 )    // file & pipe
#define FILE_ADD_FILE             ( 0x0002 )    // directory

#define FILE_APPEND_DATA          ( 0x0004 )    // file
#define FILE_ADD_SUBDIRECTORY     ( 0x0004 )    // directory
#define FILE_CREATE_PIPE_INSTANCE ( 0x0004 )    // named pipe

#define FILE_READ_EA              ( 0x0008 )    // file & directory

#define FILE_WRITE_EA             ( 0x0010 )    // file & directory

#define FILE_EXECUTE              ( 0x0020 )    // file
#define FILE_TRAVERSE             ( 0x0020 )    // directory

#define FILE_DELETE_CHILD         ( 0x0040 )    // directory

#define FILE_READ_ATTRIBUTES      ( 0x0080 )    // all

#define FILE_WRITE_ATTRIBUTES     ( 0x0100 )    // all


                                   FILE_READ_DATA           |\
                                   FILE_READ_ATTRIBUTES     |\
                                   FILE_READ_EA             |\

                                   FILE_WRITE_DATA          |\
                                   FILE_WRITE_ATTRIBUTES    |\
                                   FILE_WRITE_EA            |\
                                   FILE_APPEND_DATA         |\

                                   FILE_READ_ATTRIBUTES     |\
                                   FILE_EXECUTE             |\

Right off the bat, you can see that of the standard rights, FILE_ALL_ACCESS includes STANDARD_RIGHTS_REQUIRED, whereas the FILE_GENERIC_* values include only STANDARD_RIGHTS_*, all of which are defined as READ_CONTROL. This means that FILE_ALL_ACCESS includes DELETE, WRITE_DAC, and WRITE_OWNER which are not included in any of the other generic access masks. (SYNCHRONIZE is explicitly added by all of the FILE_GENERIC_* access masks.)

If you study it a bit more, you'll see that FILE_ALL_ACCESS also includes FILE_DELETE_CHILD, which is not present in any of the other generic access masks.

So even in the specific case of file access, we see that GENERIC_ALL is not equivalent to GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE.

Comments (10)
  1. DWalker07 says:


    Is that a copy/paste error?

    1. DWalker07 says:

      Oh, I suppose not. Sorry.

      1. Darran Rowe says:

        I know, that is a bit funky. It made me think a lot about it when I first saw it too.

  2. Joshua says:

    Sometimes these really fine-grained security constraints are useless.

    If you give somebody SC_MANAGER_CREATE_SERVICE you gave away the farm.

  3. DSN says:

    #define STANDARD_RIGHTS_REQUIRED (0x000F0000L)

    Hidden commentary in the header file?

  4. Mark Ransom says:

    Raymond, please forgive me for abusing your comment system but it was the best way I knew to contact you about a problem with your blog.

    There’s a 10-year-old blog entry you wrote:

    The comments are still there, but the body text is missing. The posts around it appear to be fine.

      1. Mark Ransom says:

        Thanks! I figured the Wayback machine would have it, but I didn’t know the correct URL to search for.

  5. Medinoc says:

    It’s interesting that FILE_GENERIC_WRITE doesn’t include FILE_DELETE_CHILD, or DELETE.

    1. morlamweb says:

      That’s how file permissions work. Granting “Write” access on a file to a user or group grants the write data, append data, write attributes, and write extended attributes permissions. It does not grant the Delete permission on the file. Delete is the difference between the Write and Modify permissions.

Comments are closed.

Skip to main content