VOID
SepAccessCheck(
  IN  PSECURITY_DESCRIPTOR SecurityDescriptor,
  IN  PSID PrincipalSelfSid,
  IN  PTOKEN PrimaryToken,
  IN  PTOKEN ClientToken OPTIONAL,
  IN  ACCESS_MASK DesiredAccess,
  IN  PIOBJECT_TYPE_LIST ObjectTypeList OPTIONAL,
  IN  ULONG ObjectTypeListLength,
  IN  PGENERIC_MAPPING GenericMapping,
  IN  ACCESS_MASK PreviouslyGrantedAccess,
  IN  KPROCESSOR_MODE PreviousMode,
  OUT PACCESS_MASK GrantedAccess,
  OUT PPRIVILEGE_SET *Privileges OPTIONAL,
  OUT PNTSTATUS AccessStatus,
  IN  BOOLEAN ReturnResultList,
  OUT PBOOLEAN ReturnSomeAccessGranted,
  OUT PBOOLEAN ReturnSomeAccessDenied
  );

Routine Description:

    Worker routine for SeAccessCheck and NtAccessCheck.  We actually do the
    access checking here.

    Whether or not we actually evaluate the DACL is based on the following
    interaction between the SE_DACL_PRESENT bit in the security descriptor
    and the value of the DACL pointer itself.


                          SE_DACL_PRESENT

                        SET          CLEAR

                   +-------------+-------------+
                   |             |             |
             NULL  |    GRANT    |    GRANT    |
                   |     ALL     |     ALL     |
     DACL          |             |             |
     Pointer       +-------------+-------------+
                   |             |             |
            !NULL  |  EVALUATE   |    GRANT    |
                   |    ACL      |     ALL     |
                   |             |             |
                   +-------------+-------------+

Arguments:

    SecurityDescriptor - Pointer to the security descriptor from the object
        being accessed.

    PrincipalSelfSid - If the object being access checked is an object which
        represents a principal (e.g., a user object), this parameter should
        be the SID of the object.  Any ACE containing the constant
        PRINCIPAL_SELF_SID is replaced by this SID.

        The parameter should be NULL if the object does not represent a principal.

    Token - Pointer to user's token object.

    TokenLocked - Boolean describing whether or not there is a read lock
        on the token.

    DesiredAccess - Access mask describing the user's desired access to the
        object.  This mask is assumed not to contain generic access types.

    ObjectTypeList - Supplies a list of GUIDs representing the object (and
        sub-objects) being accessed.  If no list is present, AccessCheckByType
        behaves identically to AccessCheck.

    ObjectTypeListLength - Specifies the number of elements in the ObjectTypeList.

    GenericMapping - Supplies a pointer to the generic mapping associated
        with this object type.

    PreviouslyGrantedAccess - Access mask indicating any access' that have
        already been granted by higher level routines

    PrivilgedAccessMask - Mask describing access types that may not be
        granted without a privilege.

    GrantedAccess - Returns an access mask describing all granted access',
        or NULL.

    Privileges - Optionally supplies a pointer in which will be returned
        any privileges that were used for the access.  If this is null,
        it will be assumed that privilege checks have been done already.

    AccessStatus - Returns STATUS_SUCCESS or other error code to be
        propogated back to the caller

    ReturnResultList - If true, GrantedAccess and AccessStatus is actually
        an array of entries ObjectTypeListLength elements long.

    ReturnSomeAccessGranted - Returns a value of TRUE to indicate that some access'
        were granted, FALSE otherwise.

    ReturnSomeAccessDenied - Returns a value of FALSE if some of the requested
        access was not granted.  This will alway be an inverse of SomeAccessGranted
        unless ReturnResultList is TRUE.  In that case,

Return Value:

    A value of TRUE indicates that some access' were granted, FALSE
    otherwise.