{"id":95705,"date":"2017-03-10T07:00:00","date_gmt":"2017-03-10T22:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=95705"},"modified":"2019-03-13T01:07:51","modified_gmt":"2019-03-13T08:07:51","slug":"20170310-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20170310-00\/?p=95705","title":{"rendered":"Is GENERIC_ALL equivalent to GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE?"},"content":{"rendered":"<p>A customer wanted to know whether passing <code>GENERIC_ALL<\/code> as an access mask is effectively equivalent to passing <code>GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE<\/code>. Specifically, they were interested in the answer to this question with respect to the <code>Create&shy;File<\/code> function. <\/p>\n<p>Okay, first question first. Is <code>GENERIC_ALL<\/code> effectively equivalent to <code>GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE<\/code>? <\/p>\n<p>The answer is &#8220;It depends.&#8221; <\/p>\n<p>Each object decides what these generic access masks mean. Now, the intended use is that <code>GENERIC_READ<\/code> correspond to whatever &#8220;read&#8221; access means for an object, <code>GENERIC_WRITE<\/code> correspond to whatever &#8220;write&#8221; access means for an object, and <code>GENERIC_EXECUTE<\/code> correspond to whatever &#8220;execute&#8221; access means for an object. It&#8217;s also the intended use that <code>GENERIC_ALL<\/code> represent whatever access makes the most sense for &#8220;all access&#8221;. <\/p>\n<p>But that&#8217;s just the intended use. There is nothing physically preventing an object from giving those four generic access masks nonsensical values. Because <a HREF=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=20733\">anybody can make up a generic mapping<\/a>. Therefore, there&#8217;s nothing you can guarantee about the relationship between the generic access masks beyond &#8220;they are what the object decides they are.&#8221; <\/p>\n<p>In practice, <code>GENERIC_ALL<\/code> is at least as big as <code>GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE<\/code>, but it can be bigger. For example, for files (which is probably what the customer is asking about when they talk about <code>Create&shy;File<\/code>), the values are defined as follows, in <code>winnt.h<\/code>: <\/p>\n<pre>\n#define DELETE                           (0x00010000L)\n#define READ_CONTROL                     (0x00020000L)\n#define WRITE_DAC                        (0x00040000L)\n#define WRITE_OWNER                      (0x00080000L)\n#define SYNCHRONIZE                      (0x00100000L)\n\n#define STANDARD_RIGHTS_REQUIRED         (0x000F0000L)\n\n#define STANDARD_RIGHTS_READ             (READ_CONTROL)\n#define STANDARD_RIGHTS_WRITE            (READ_CONTROL)\n#define STANDARD_RIGHTS_EXECUTE          (READ_CONTROL)\n\n#define FILE_READ_DATA            ( 0x0001 )    \/\/ file &amp; pipe\n#define FILE_LIST_DIRECTORY       ( 0x0001 )    \/\/ directory\n\n#define FILE_WRITE_DATA           ( 0x0002 )    \/\/ file &amp; pipe\n#define FILE_ADD_FILE             ( 0x0002 )    \/\/ directory\n\n#define FILE_APPEND_DATA          ( 0x0004 )    \/\/ file\n#define FILE_ADD_SUBDIRECTORY     ( 0x0004 )    \/\/ directory\n#define FILE_CREATE_PIPE_INSTANCE ( 0x0004 )    \/\/ named pipe\n\n\n#define FILE_READ_EA              ( 0x0008 )    \/\/ file &amp; directory\n\n#define FILE_WRITE_EA             ( 0x0010 )    \/\/ file &amp; directory\n\n#define FILE_EXECUTE              ( 0x0020 )    \/\/ file\n#define FILE_TRAVERSE             ( 0x0020 )    \/\/ directory\n\n#define FILE_DELETE_CHILD         ( 0x0040 )    \/\/ directory\n\n#define FILE_READ_ATTRIBUTES      ( 0x0080 )    \/\/ all\n\n#define FILE_WRITE_ATTRIBUTES     ( 0x0100 )    \/\/ all\n\n#define FILE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF)\n\n#define FILE_GENERIC_READ         (STANDARD_RIGHTS_READ     |\\\n                                   FILE_READ_DATA           |\\\n                                   FILE_READ_ATTRIBUTES     |\\\n                                   FILE_READ_EA             |\\\n                                   SYNCHRONIZE)\n\n#define FILE_GENERIC_WRITE        (STANDARD_RIGHTS_WRITE    |\\\n                                   FILE_WRITE_DATA          |\\\n                                   FILE_WRITE_ATTRIBUTES    |\\\n                                   FILE_WRITE_EA            |\\\n                                   FILE_APPEND_DATA         |\\\n                                   SYNCHRONIZE)\n\n#define FILE_GENERIC_EXECUTE      (STANDARD_RIGHTS_EXECUTE  |\\\n                                   FILE_READ_ATTRIBUTES     |\\\n                                   FILE_EXECUTE             |\\\n                                   SYNCHRONIZE)\n<\/pre>\n<p>Right off the bat, you can see that of the standard rights, <code>FILE_ALL_ACCESS<\/code> includes <code>STANDARD_RIGHTS_REQUIRED<\/code>, whereas the <code>FILE_GENERIC_*<\/code> values include only <code>STANDARD_RIGHTS_*<\/code>, all of which are defined as <code>READ_CONTROL<\/code>. This means that <code>FILE_ALL_ACCESS<\/code> includes <code>DELETE<\/code>, <code>WRITE_DAC<\/code>, and <code>WRITE_OWNER<\/code> which are not included in any of the other generic access masks. (<code>SYNCHRONIZE<\/code> is explicitly added by all of the <code>FILE_GENERIC_*<\/code> access masks.) <\/p>\n<p>If you study it a bit more, you&#8217;ll see that <code>FILE_ALL_ACCESS<\/code> also includes <code>FILE_DELETE_CHILD<\/code>, which is not present in any of the other generic access masks. <\/p>\n<p>So even in the specific case of file access, we see that <code>GENERIC_ALL<\/code> is not equivalent to <code>GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE<\/code>. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Only if the object says so.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-95705","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Only if the object says so.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/95705","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=95705"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/95705\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=95705"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=95705"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=95705"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}