{"id":45591,"date":"2015-05-15T07:00:00","date_gmt":"2015-05-15T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20150515-00\/?p=45591\/"},"modified":"2019-03-13T12:15:27","modified_gmt":"2019-03-13T19:15:27","slug":"20150515-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20150515-00\/?p=45591","title":{"rendered":"MapGenericMask is just a convenience function for converting generic access to specific access, according to the instructions you provide"},"content":{"rendered":"<p>For some reason, people call the <code>Map&shy;Generic&shy;Mask<\/code> function in order to calculate what access mask to pass to request access to something. That&#8217;s not what <code>Map&shy;Generic&shy;Mask<\/code> is for. The <code>Map&shy;Generic&shy;Mask<\/code> function is to assist the server side of the access, not the client side. <\/p>\n<p>As the documentation says, the <code>Map&shy;Generic&shy;Mask<\/code> function <a HREF=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/aa379266(v=vs.85).aspx\">maps the generic access rights in an access mask to specific and standard access rights.  The function applies a mapping supplied in a <code>GENERIC_MAPPING<\/code> structure<\/a>. <\/p>\n<p>This is further explained in the remarks: <\/p>\n<blockquote CLASS=\"m\"><p>After calling the <b>Map&shy;Generic&shy;Mask<\/b> function, the access mask pointed to by the <i>Access&shy;Mask<\/i> parameter has none of its generic bits (GenericRead, GenericWrite, GenericExecute, or GenericAll) or undefined bits&sup1; set, although it can have other bits set. If bits other than the generic bits are provided on input, this function does not clear them. <\/p><\/blockquote>\n<p>What this function does is take the <code>Access&shy;Mask<\/code> parameter and convert all of the <code>GENERIC_*<\/code> bits into object-specific bits, as defined by the <code>GENERIC_MAPPING<\/code>. <\/p>\n<p>In other words, the code for the <code>Map&shy;Generic&shy;Mask<\/code> function looks basically like this: <\/p>\n<pre>\nvoid MapGenericMask(\n  PDWORD AccessMask,\n  PGENERIC_MAPPING GenericMapping\n)\n{\n if (*AccessMask &amp; GENERIC_READ)\n     *AccessMask |= GenericMapping-&gt;GenericRead;\n\n if (*AccessMask &amp; GENERIC_WRITE)\n     *AccessMask |= GenericMapping-&gt;GenericWrite;\n\n if (*AccessMask &amp; GENERIC_EXECUTE)\n     *AccessMask |= GenericMapping-&gt;GenericExecute;\n\n if (*AccessMask &amp; GENERIC_ALL)\n     *AccessMask |= GenericMapping-&gt;GenericAll;\n\n *AccessMask &amp;= ~(GENERIC_READ | GENERIC_WRITE |\n                  GENERIC_WRITE | GENERIC_ALL);\n}\n<\/pre>\n<p>The function takes the access mask and sees if any of the generic access bits are set. If so, then it replaces them with the corresponding specific access bits provided by the <code>Generic&shy;Mapping<\/code> parameter. <\/p>\n<p>Note that this function doesn&#8217;t tell you anything you don&#8217;t already know. It&#8217;s just a helper function to make access checks easier to implement: If you are a component that manages an object and you need to perform an access check, you use <code>Map&shy;Generic&shy;Access<\/code> to convert all the generic access requests into specific requests according to the rules you specified in your <code>GENERIC_MAPPING<\/code>, and the rest of your code only needs to deal with specific requests. <\/p>\n<p>For example, we saw some time ago that <a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2008\/09\/29\/8966821.aspx\">a hypothetical Gizmo object<\/a> could map <code>GENERIC_READ<\/code> to operations that query information from a Gizmo without modifying it, map <code>GENERIC_WRITE<\/code> to operations that alter the gizmo properties, map <code>GENERIC_EXECUTE<\/code> to operations that enable or disable the Gizmo, and map <code>GENERIC_ALL<\/code> to include all Gizmo operations. <\/p>\n<p>And if you needed to do a security check on a Gizmo, you would do something like this: <\/p>\n<pre>\nBOOL IsGizmoAccessGranted(\n HTOKEN Token,\n PSECURITY_DESCRIPTOR SecurityDescriptor,\n DWORD AccessDesired,\n PDWORD AccessAllowed)\n{\n MapGenericMask(&amp;AccessDesired, &amp;GizmoGenericMapping);\n\n BOOL AccessGranted = FALSE;\n PRIVILEGE_SET PrivilegeSet;\n DWORD PrivilegeSetSize = sizeof(PrivilegeSet);\n\n return AccessCheck(SecurityDescriptor,\n            Token,\n            AccessDesired,\n            &amp;GizmoGenericMapping,\n            &amp;PrivilegeSet,\n            &amp;PrivilegeSetSize,\n            AccessAllowed,\n            &amp;AccessGranted) &amp;&amp; AccessGranted;\n}\n<\/pre>\n<p>When somebody wants to access a Gizmo, you use <code>Map&shy;Generic&shy;Mask<\/code> to convert all the generic requests to specific requests. You then pass that request to <code>Access&shy;Check<\/code>, along with token for the user making the request and the security descriptor for the widget. The <code>Access&shy;Check<\/code> function does the heavy lifting of seeing which ACEs apply to the user specified by the token, then verifying that all the requested accesses have an <i>Allow<\/i> ACE, and that none of the requested accesses have a <i>Deny<\/i> ACE. It also takes care of the <code>MAXIMMUM_ALLOWED<\/code> access request by simply returning all the accesses that are allowed and not denied. <\/p>\n<p>The point of the <code>Map&shy;Generic&shy;Mask<\/code> function is to make life a little easier for the code that enforces security. <\/p>\n<p>On the other hand, the <code>Map&shy;Generic&shy;Mask<\/code> function is not particularly useful on the side that is requesting access. If you are requesting generic read access, just pass <code>GENERIC_READ<\/code>. The code that does the security check will convert the <code>GENERIC_READ<\/code> into the access masks that are specific to the object you are trying to access. (And it will most likely use the <code>Map&shy;Generic&shy;Mask<\/code> function to do it.) <\/p>\n<p>&sup1; That extra phrase &#8220;or undefined bits&#8221; is contradicted by the subsequent sentence &#8220;If bits other than the generic bits are provided on input, the function does not clear them.&#8221; The second sentence is correct; the extra phrase &#8220;or undefined bits&#8221; is incorrect and should be removed. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>It&#8217;s useful on the server side, not the client side.<\/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-45591","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>It&#8217;s useful on the server side, not the client side.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/45591","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=45591"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/45591\/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=45591"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=45591"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=45591"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}