For some reason,
people call
the MapGenericMask
function
in order to calculate what access mask to pass to request
access to something.
That's not what
MapGenericMask
is for.
The
MapGenericMask
function is to assist
the server side of the access,
not the client side.
As the documentation says,
the MapGenericMask
function
maps the generic access rights in an access mask
to specific and standard access rights.
The function applies a mapping supplied
in a GENERIC_
structure.
This is further explained in the remarks:
After calling the MapGenericMask function, the access mask pointed to by the AccessMask parameter has none of its generic bits (GenericRead, GenericWrite, GenericExecute, or GenericAll) or undefined bits¹ 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.
What this function does is take the
AccessMask
parameter
and convert all of the GENERIC_*
bits into object-specific bits,
as defined by the
GENERIC_
.
In other words, the code for
the MapGenericMask
function
looks basically like this:
void MapGenericMask( PDWORD AccessMask, PGENERIC_MAPPING GenericMapping ) { if (*AccessMask & GENERIC_READ) *AccessMask |= GenericMapping->GenericRead; if (*AccessMask & GENERIC_WRITE) *AccessMask |= GenericMapping->GenericWrite; if (*AccessMask & GENERIC_EXECUTE) *AccessMask |= GenericMapping->GenericExecute; if (*AccessMask & GENERIC_ALL) *AccessMask |= GenericMapping->GenericAll; *AccessMask &= ~(GENERIC_READ | GENERIC_WRITE | GENERIC_WRITE | GENERIC_ALL); }
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
GenericMapping
parameter.
Note that this function doesn't tell you anything
you don't already know.
It'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
MapGenericAccess
to
convert all the generic access requests
into specific requests according to the
rules you specified in your
GENERIC_
,
and the rest of your code only needs to deal
with specific requests.
For example,
we saw some time ago that
a hypothetical Gizmo object
could map GENERIC_
to operations
that query information from a Gizmo without modifying it,
map GENERIC_
to operations
that alter the gizmo properties,
map GENERIC_
to operations
that enable or disable the Gizmo,
and
map GENERIC_
to include all
Gizmo operations.
And if you needed to do a security check on a Gizmo, you would do something like this:
BOOL IsGizmoAccessGranted( HTOKEN Token, PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD AccessDesired, PDWORD AccessAllowed) { MapGenericMask(&AccessDesired, &GizmoGenericMapping); BOOL AccessGranted = FALSE; PRIVILEGE_SET PrivilegeSet; DWORD PrivilegeSetSize = sizeof(PrivilegeSet); return AccessCheck(SecurityDescriptor, Token, AccessDesired, &GizmoGenericMapping, &PrivilegeSet, &PrivilegeSetSize, AccessAllowed, &AccessGranted) && AccessGranted; }
When somebody wants to access a Gizmo,
you use MapGenericMask
to convert all the
generic requests to specific requests.
You then pass that request to
AccessCheck
,
along with token for the user making the request
and the security descriptor for the widget.
The AccessCheck
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 Allow ACE,
and that none of the requested accesses have a
Deny ACE.
It also takes care of the
MAXIMMUM_
access request
by simply returning all the accesses that are
allowed and not denied.
The point of the
MapGenericMask
function is
to make life a little easier for the code that
enforces security.
On the other hand, the MapGenericMask
function is not particularly useful on the side that is
requesting access.
If you are requesting generic read access,
just pass GENERIC_
.
The code that does the security check will convert the
GENERIC_
into the access masks
that are specific to the object you are trying to access.
(And it will most likely use the
MapGenericMask
function to do it.)
¹ That extra phrase "or undefined bits" is contradicted by the subsequent sentence "If bits other than the generic bits are provided on input, the function does not clear them." The second sentence is correct; the extra phrase "or undefined bits" is incorrect and should be removed.