/// <summary> /// Do an access check between a security descriptor and a token to determine the allowed access. /// </summary> /// <param name="sd">The security descriptor</param> /// <param name="token">The access token.</param> /// <param name="access_rights">The set of access rights to check against</param> /// <param name="principal">An optional principal SID used to replace the SELF SID in a security descriptor.</param> /// <param name="generic_mapping">The type specific generic mapping (get from corresponding NtType entry).</param> /// <returns>The allowed access mask as a unsigned integer.</returns> /// <exception cref="NtException">Thrown if an error occurred in the access check.</exception> public static AccessMask GetAllowedAccess(SecurityDescriptor sd, NtToken token, AccessMask access_rights, Sid principal, GenericMapping generic_mapping) { if (sd == null) { throw new ArgumentNullException("sd"); } if (token == null) { throw new ArgumentNullException("token"); } if (access_rights.IsEmpty) { return(AccessMask.Empty); } using (SafeBuffer sd_buffer = sd.ToSafeBuffer()) { using (NtToken imp_token = DuplicateForAccessCheck(token)) { using (var privs = new SafePrivilegeSetBuffer()) { int buffer_length = privs.Length; using (var self_sid = principal != null ? principal.ToSafeBuffer() : SafeSidBufferHandle.Null) { NtSystemCalls.NtAccessCheckByType(sd_buffer, self_sid, imp_token.Handle, access_rights, SafeHGlobalBuffer.Null, 0, ref generic_mapping, privs, ref buffer_length, out AccessMask granted_access, out NtStatus result_status).ToNtException(); if (result_status.IsSuccess()) { return(granted_access); } return(AccessMask.Empty); } } } } }