/// <summary>
        /// The constructor
        /// </summary>
        /// <param name="binary">The input binary</param>
        /// <param name="offset">The offset in the binary</param>
        public _NonObjectAce(byte[] binary, int offset) : base(binary, offset)
        {
            //The AceSize field
            aceSize = BitConverter.ToUInt16(binary, offset + 2);

            if (offset > binary.Length - aceSize)
            {
                throw new ArgumentException(nameof(offset));
            }

            if (aceSize < 8 + DtypUtility.MinLengthOfSecurityIdentifier)
            {
                throw new ArgumentException(nameof(aceSize));
            }

            _AccessMask         = BitConverter.ToInt32(binary, offset + DtypUtility.ACE_HEADER_LENGTH);
            _SecurityIdentifier = new _SID(binary, offset + DtypUtility.SHORT_FIXED_ACE_LENGTH);

            int dataLength = aceSize - (DtypUtility.SHORT_FIXED_ACE_LENGTH + _SecurityIdentifier.Size);

            if (dataLength > 0)// If there is still other application data exists
            {
                this.applicationData = new byte[dataLength];
                Array.Copy(binary, offset + DtypUtility.SHORT_FIXED_ACE_LENGTH + _SecurityIdentifier.Size, this.applicationData, 0, dataLength);
            }
        }
        /// <summary>
        /// Customized length calculator of ApplicationData, called by Channel.
        /// This method's name is written in ApplicationData's Size attribute.
        /// </summary>
        /// <param name="context">Channel's context.</param>
        /// <returns>ApplicationData's length.</returns>
        // this method is called by Channel.
        internal static int CalculateApplicationDataLength(IEvaluationContext context)
        {
            _ACE_HEADER header = (_ACE_HEADER)context.Variables["Header"];
            _SID        sid    = (_SID)context.Variables["Sid"];

            return(DtypUtility.CalculateApplicationDataLength(header, sid));
        }
Beispiel #3
0
        public string GetSddlForm()
        {
            StringBuilder result = new StringBuilder();
            _SID          sid    = TypeMarshal.ToStruct <_SID>(buffer);
            string        sddl   = DtypUtility.ToSddlString(sid);

            result.AppendFormat(CultureInfo.InvariantCulture, "O:{0}", sddl);

            return(result.ToString());
        }
        /// <summary>
        /// The constructor
        /// </summary>
        /// <param name="binary">The input binary</param>
        /// <param name="offset">The offset in the binary</param>
        public _ObjectAce(byte[] binary, int offset) : base(binary, offset)
        {
            int length = BitConverter.ToUInt16(binary, offset + 2);

            if (offset > binary.Length - length)
            {
                throw new ArgumentException(nameof(offset));
            }

            _AccessMask = BitConverter.ToInt32(binary, offset + DtypUtility.ACE_HEADER_LENGTH);
            ObjectFlags = (_ObjectAceFlags)BitConverter.ToInt32(binary, offset + DtypUtility.SHORT_FIXED_ACE_LENGTH);

            int pointer = DtypUtility.ACE_HEADER_LENGTH + DtypUtility.SHORT_FIXED_ACE_LENGTH;

            if (ObjectFlags.HasFlag(_ObjectAceFlags.ObjectAceTypePresent))
            {
                ObjectType = DtypUtility.ReadGuid(binary, offset + pointer);
                pointer   += 16;
            }
            if (ObjectFlags.HasFlag(_ObjectAceFlags.InheritedObjectAceTypePresent))
            {
                InheritedObjectType = DtypUtility.ReadGuid(binary, offset + pointer);
                pointer            += 16;
            }

            _SecurityIdentifier = new _SID(binary, offset + pointer);
            pointer            += _SecurityIdentifier.Size;

            int appDataLength = length - pointer;

            if (appDataLength > 0)
            {
                this.applicationData = new byte[appDataLength];
                Array.Copy(binary, offset + pointer, this.applicationData, 0, appDataLength);
            }
        }
        /// <summary>
        /// A support function, SidInToken, takes the authorization context, 
        /// a SID (referenced below as the SidToTest parameter), and an optional 
        /// PrincipalSelfSubstitute parameter, and returns TRUE if the SidToTest 
        /// is present in the authorization context; otherwise, it returns FALSE. 
        /// The well-known SID PRINCIPAL_SELF, if passed as SidToTest, is replaced 
        /// by the PrincipalSelfSubstitute SID prior to the examination of the 
        /// authorization context. MS-DTYP section 2.5.4.1
        /// </summary>
        /// <param name="token">
        /// Token is an authorization context containing all SIDs 
        /// that represent the security principal
        /// </param>
        /// <param name="sidToTest">
        /// The SID for which to search in Token
        /// </param>
        /// <param name="principalSelfSubstitute">
        /// a SID with which SidToTest may be replaced
        /// </param>
        /// <returns>
        /// Returns TRUE if the SidToTest is present in the authorization context; 
        /// otherwise, it returns FALSE. 
        /// </returns>
        /// <exception cref="ArgumentException">
        /// Thrown when the well-known SID PRINCIPAL_SELF, if passed as SidToTest, but 
        /// principalSelfSubstitute does't exist.
        /// </exception>
        public static bool SidInToken(
            Token token,
            _SID sidToTest,
            _SID? principalSelfSubstitute)
        {
            //
            //Pseudocode syntax
            //
            //--
            //-- On entry
            //-- Token is an authorization context containing all SIDs
            //-- that represent the security principal
            //-- SidToTest, the SID for which to search in Token
            //-- PrincipalSelfSubstitute, a SID with which SidToTest may be
            //-- replaced
            //IF SidToTest is the Well Known SID PRINCIPAL_SELF THEN
            //set SidToTest to be PrincipalSelfSubstitute
            //END IF
            //FOR EACH SID s in Token DO
            //IF s equals SidToTest THEN
            //return TRUE
            //END IF
            //END FOR
            //Return FALSE
            //END-SUBROUTINE

            if (ObjectUtility.DeepCompare(GetWellKnownSid(WellKnownSid.PRINCIPAL_SELF, null), sidToTest))
            {
                if (principalSelfSubstitute != null)
                {
                    sidToTest = (_SID)principalSelfSubstitute;
                }
                else
                {
                    throw new ArgumentException("The principalSelfSubstitute doesn't exist", "principalSelfSubstitute");
                }
            }
            if (token.Sids != null)
            {
                foreach (_SID sid in token.Sids)
                {
                    if (ObjectUtility.DeepCompare(sid, sidToTest))
                    {
                        return true;
                    }
                }
            }

            return false;
        }
        /// <summary>
        /// A support function, SidDominates, compares the mandatory integrity levels expressed in two SIDs.
        /// This function can be used only on SIDs that encode integrity levels (the SID_IDENTIFIER_AUTHORITY
        /// field is SECURITY_MANDATORY_LABEL_AUTHORITY); any other use is unsupported.
        /// </summary>
        /// <param name="sid1">first sid in dominance calculation</param>
        /// <param name="sid2">second sid in dominance calculation</param>
        /// <returns>
        /// The function returns TRUE if the first SID dominates the second SID or is equal to the second SID, 
        /// or FALSE if the first SID is subordinate to the second SID.
        /// </returns>
        public static bool SidDominates(_SID sid1, _SID sid2)
        {
            //Described in MS-DTYP Section 2.5.3.1.2 SidDominates:
            //
            //IF sid1 equals sid2 THEN
            //    Return TRUE
            //END IF
            //-- If Sid2 has more SubAuthorities than Sid1, Sid1 cannot dominate.
            //IF sid2.SubAuthorityCount GREATER THAN sid1.SubAuthorityCount THEN
            //    Return FALSE
            //END IF
            //--on entry, index is zero and is incremented for each iteration of the loop.
            //FOR each SubAuthority in sid1
            //    IF sid1.SubAuthority[ index ] GREATER THAN or EQUAL TO sid2.SubAuthority[ index ] THEN
            //        Return TRUE
            //    END IF
            //END FOR
            //Return FALSE

            if (ObjectUtility.DeepCompare(sid1, sid2) == true)
            {
                return true;
            }

            if (sid2.SubAuthorityCount > sid1.SubAuthorityCount)
            {
                return false;
            }

            for (int i = 0; i < sid1.SubAuthorityCount; i++)
            {
                if (i >= sid2.SubAuthorityCount)
                {
                    break;
                }
                if (sid1.SubAuthority[i] >= sid2.SubAuthority[i])
                {
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// PostProcessACL. MS-DTYP section 2.5.4.9
        /// </summary>
        /// <param name="acl">ACL on which to substitute SIDs.</param>
        /// <param name="copyFilter">The filter for post-processing the ACL.</param>
        /// <param name="owner">Owner to use in substituting the CreatorOwner SID.</param>
        /// <param name="group">Group to use in substituting the CreatorGroup SID.</param>
        /// <param name="genericMapping">
        /// Mapping of generic permissions to resource manager-specific 
        /// permissions supplied by the caller.
        /// </param>
        /// <returns>
        /// The computed ACL with the SID substitutions performed.
        /// </returns>
        public static _ACL PostProcessACL(
            _ACL acl,
            CopyFilter copyFilter,
            _SID owner,
            _SID group,
            GenericMapping genericMapping)
        {
            #region Pseudocode  v20110329

            //// Substitute CreatorOwner and CreatorGroup SIDs and do GenericMapping in ACL

            //Initialize NewACL to Empty ACL

            //FOR each ACE in ACL DO

            //    // Determine if this ACE passes the filter to be copied to the new ACL

            //    SET CopyThisAce = FALSE

            //    CASE CopyFilter OF

            //        CopyAllAces:
            //            BEGIN
            //                SET CopyThisAce = TRUE
            //            END

            //        CopyInheritedAces:
            //            BEGIN
            //                IF (ACE.AceFlags contains INHERITED_ACE) THEN
            //                    SET CopyThisAce = TRUE
            //                ENDIF
            //            END

            //        CopyExplicitAces:
            //            BEGIN
            //                IF (ACE.AceFlags does not contain INHERITED_ACE) THEN
            //                   SET CopyThisAce = TRUE
            //                ENDIF
            //            END

            //    ENDCASE

            //    Set NewACE to ACE

            //    IF (CopyThisAce) THEN

            //        CASE ACE.Sid OF

            //            CREATOR_OWNER:
            //                NewACE.Sid = Owner

            //            CREATOR_GROUP:
            //                NewACE.Sid = Group
            //        ENDCASE

            //        IF (ACE.Mask contains GENERIC_READ) THEN
            //            Add GenericMapping.GenericRead to NewACE.Mask
            //        ENDIF

            //        IF (ACE.Mask contains GENERIC_WRITE) THEN
            //            Add GenericMapping.GenericWrite to NewACE.Mask
            //        ENDIF

            //        IF (ACE.Mask contains GENERIC_EXECUTE) THEN
            //            Add GenericMapping.GenericExecute to NewACE.Mask
            //        ENDIF

            //        Append NewACE to NewACL
            //    ENDIF

            //END FOR

            //RETURN NewACL
            //// END PostProcessACL

            #endregion

            _ACL newAcl = new _ACL();
            newAcl.AclRevision = acl.AclRevision;
            newAcl.Aces = new object[] { };
            List<object> newAces = new List<object>();

            if (acl.Aces != null)
            {
                foreach (object ace in acl.Aces)
                {
                    object newAce = ObjectUtility.DeepClone(ace);
                    _ACE_HEADER header = (_ACE_HEADER)ObjectUtility.GetFieldValue(newAce, "Header");

                    bool copyThisAce = false;
                    switch (copyFilter)
                    {
                        case CopyFilter.CopyAllAces:
                            copyThisAce = true;
                            break;
                        case CopyFilter.CopyInheritedAces:
                            if ((header.AceFlags & ACE_FLAGS.INHERITED_ACE) == ACE_FLAGS.INHERITED_ACE)
                            {
                                copyThisAce = true;
                            }
                            break;
                        case CopyFilter.CopyExplicitAces:
                            if ((header.AceFlags & ACE_FLAGS.INHERITED_ACE) == ACE_FLAGS.None)
                            {
                                copyThisAce = true;
                            }
                            break;
                    }

                    if (copyThisAce)
                    {
                        #region Substitute CreatorOwner and CreatorGroup SIDs in ACL

                        _SID sid = (_SID)ObjectUtility.GetFieldValue(newAce, "Sid");
                        if (ObjectUtility.DeepCompare(sid, GetWellKnownSid(WellKnownSid.CREATOR_OWNER, null)))
                        {
                            ObjectUtility.SetFieldValue(newAce, "Sid", owner);
                            header.AceSize = (ushort)(header.AceSize
                                - (sid.SubAuthorityCount - owner.SubAuthorityCount) * sizeof(uint));
                            ObjectUtility.SetFieldValue(newAce, "Header", header);

                        }
                        else if (ObjectUtility.DeepCompare(sid, GetWellKnownSid(WellKnownSid.CREATOR_GROUP, null)))
                        {
                            ObjectUtility.SetFieldValue(newAce, "Sid", group);
                            header.AceSize = (ushort)(header.AceSize
                                - (sid.SubAuthorityCount - group.SubAuthorityCount) * sizeof(uint));
                            ObjectUtility.SetFieldValue(newAce, "Header", header);
                        }
                        #endregion

                        #region Do GenericMapping in ACL

                        uint mask = (uint)ObjectUtility.GetFieldValue(newAce, "Mask");

                        if ((mask & ACCESS_MASK_GENERIC_READ) == ACCESS_MASK_GENERIC_READ)
                        {
                            mask = mask | genericMapping.GenericRead;
                            ObjectUtility.SetFieldValue(newAce, "Mask", mask);
                        }
                        if ((mask & ACCESS_MASK_GENERIC_WRITE) == ACCESS_MASK_GENERIC_WRITE)
                        {
                            mask = mask | genericMapping.GenericWrite;
                            ObjectUtility.SetFieldValue(newAce, "Mask", mask);
                        }
                        if ((mask & ACCESS_MASK_GENERIC_EXECUTE) == ACCESS_MASK_GENERIC_EXECUTE)
                        {
                            mask = mask | genericMapping.GenericExecute;
                            ObjectUtility.SetFieldValue(newAce, "Mask", mask);
                        }
                        #endregion

                        //Append NewACE to NewACL
                        newAces.Add(newAce);
                    }
                }
            }
            newAcl.Aces = newAces.ToArray();
            newAcl.AceCount = (ushort)newAcl.Aces.Length;
            newAcl.AclSize = DtypUtility.CalculateAclSize(newAcl);

            return newAcl;
        }
        /// <summary>
        /// MandatoryIntegrityCheck. MS-DTYP section 2.5.4.1
        /// </summary>
        /// <param name="tokenIntegritySID">
        /// Mandatory Integrity SID in the Token
        /// </param>
        /// <param name="aceIntegritySID">
        /// Mandatory Integrity label SID in the Security descriptor of the object
        /// </param>
        /// <param name="mandatoryInformation">
        /// Output of the function describing the allowable bits for the caller
        /// </param>
        /// <param name="token">
        /// Authorization context
        /// </param>
        /// <param name="objectSecurityDescriptor">
        /// SECURITY_DESCRIPTOR structure that is assigned to the object
        /// </param>
        /// <returns>True if check is done successfully; otherwise, false</returns>
        public static bool MandatoryIntegrityCheck(
            _SID tokenIntegritySID,
            _SID aceIntegritySID,
            out uint mandatoryInformation,
            Token token,
            _SECURITY_DESCRIPTOR objectSecurityDescriptor)
        {
            //Set TokenPolicy to Token MandatoryPolicy field
            //Set ObjectIntegrityACE to SecurityDescriptor ObjectIntegrity ACE field
            //Set ObjectIntegrityAceMask to SecurityDescriptor ObjectIntegrity Accessmask field
            //
            //IF TokenPolicy.Policy EQUAL TOKEN_MANDATORY_POLICY_OFF OR
            //TokenPolicy.Policy EQUAL TOKEN_MANDATORY_POLICY_NEW_PROCESS_MIN THEN
            //Set MandatoryInformation.AllowedAccess to GENERIC_ALL
            //Return success
            //END IF
            //
            //IF ObjectIntegrityACE.AceFlag NOT EQUAL INHERIT_ONLY_ACE THEN
            //Set AceMask to ObjectIintegrityACE.AccessMask
            //Set AceIntegritysid to ObjectIntegrityACE.TrusteeSid
            //ELSE
            //Set AceMask to SYSTEM_MANDATORY_LABEL_NO_WRITE_UP
            //--The DefaultMandatorySid is derived from policy managed in an
            //--implementation specific manner. The SID for ML_MEDIUM is used by
            //--Windows.
            //Set AceIntegritysid to DefaultMandatorySid
            //END IF

            TokenMandatoryPolicyValue tokenPolicy = token.MandatoryPolicy;
            _SYSTEM_MANDATORY_LABEL_ACE? objectIntegrityACE = null;
            mandatoryInformation = 0;
            bool tokenDominates;

            if (tokenPolicy == TokenMandatoryPolicyValue.TOKEN_MANDATORY_POLICY_OFF
                || tokenPolicy == TokenMandatoryPolicyValue.TOKEN_MANDATORY_POLICY_NEW_PROCESS_MIN)
            {
                mandatoryInformation = ACCESS_MASK_GENERIC_ALL;
                return true;
            }

            if ((objectSecurityDescriptor.Control & SECURITY_DESCRIPTOR_Control.SACLPresent)
                    == SECURITY_DESCRIPTOR_Control.SACLPresent
                && objectSecurityDescriptor.Sacl != null)
            {
                if (objectSecurityDescriptor.Sacl.Value.Aces != null)
                {
                    foreach (object ace in objectSecurityDescriptor.Sacl.Value.Aces)
                    {
                        _SID sid = (_SID)ObjectUtility.GetFieldValue(ace, "Sid");
                        if (ObjectUtility.DeepCompare(sid, aceIntegritySID))
                        {
                            objectIntegrityACE = (_SYSTEM_MANDATORY_LABEL_ACE)ace;
                        }
                    }
                }
            }

            SYSTEM_MANDATORY_LABEL_ACE_Mask objectIntegrityAceMask;
            _SID aceIntegritySid;

            if (objectIntegrityACE != null && objectIntegrityACE.Value.Header.AceFlags != ACE_FLAGS.INHERIT_ONLY_ACE)
            {
                objectIntegrityAceMask = objectIntegrityACE.Value.Mask;
                aceIntegritySid = objectIntegrityACE.Value.Sid;
            }
            else
            {
                objectIntegrityAceMask = SYSTEM_MANDATORY_LABEL_ACE_Mask.SYSTEM_MANDATORY_LABEL_NO_WRITE_UP;
                //The DefaultMandatorySid is derived from policy managed in an
                //implementation specific manner. The SID for ML_MEDIUM is used by
                //Windows.
                aceIntegritySid = GetWellKnownSid(WellKnownSid.ML_MEDIUM, null);
            }
            //
            //Note:SidDominates is removed from the current function, because it's declared but not used.
            //
            //CALL sidEqual(AceIntegritysid, TokenIntegritysid)
            //IF AceIntegritySid EQUALS Token.MandatoryIntegritySid THEN
            //Set TokenDominates to TRUE
            //Set ObjectDominates to TRUE
            //ELSE
            //CALL SidDominates (Token.MandatoryIntegritySid, AceIntegritysid)
            //IF SidDominates returns TRUE THEN
            //Set TokenDominates to TRUE
            //ELSE
            //Set TokenDominates to FALSE
            //END IF
            //Set ObjectDominates to NOT(TokenDominates)
            //END IF

            tokenDominates = SidDominates((_SID)token.IntegrityLevelSid, aceIntegritySid);

            //IF TokenPolicy EQUAL TOKEN_MANDATORY_POLICY_NO_WRITE_UP THEN
            //Add READ to MandatoryInformation.AllowedAccess
            //Add EXECUTE to MandatoryInformation.AllowedAccess
            //IF TokenDominates is TRUE THEN
            //Add WRITE to MandatoryInformation.AllowedAccess
            //END IF
            //END IF
            //
            //IF TokenDominates is FALSE THEN
            //IF ObjectIntegrityAceMask & SYSTEM_MANDATORY_LABEL_NO_READ_UP THEN
            //Remove READ from MandatoryInformation.AllowedAccess
            //END IF
            //IF ObjectIntegrityAceMask & SYSTEM_MANDATORY_LABEL_NO_WRITE_UP THEN
            //Remove WRITE from MandatoryInformation.AllowedAccess
            //END IF
            //IF ObjectIntegrityAceMask & SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP THEN
            //Remove EXECUTE from MandatoryInformation.AllowedAccess
            //END IF
            //END IF
            //
            //IF Token.Privileges contains SeRelabelPrivilegeTHEN
            //Add WRITE_OWNER to MandatoryInformation.AllowedAccess
            //END IF

            if (tokenPolicy == TokenMandatoryPolicyValue.TOKEN_MANDATORY_POLICY_NO_WRITE_UP)
            {
                mandatoryInformation |= ACCESS_MASK_GENERIC_READ;
                mandatoryInformation |= ACCESS_MASK_GENERIC_EXECUTE;
                if (tokenDominates)
                {
                    mandatoryInformation |= ACCESS_MASK_GENERIC_WRITE;
                }
            }

            if (!tokenDominates)
            {
                if ((objectIntegrityAceMask
                    & SYSTEM_MANDATORY_LABEL_ACE_Mask.SYSTEM_MANDATORY_LABEL_NO_READ_UP)
                    == SYSTEM_MANDATORY_LABEL_ACE_Mask.SYSTEM_MANDATORY_LABEL_NO_READ_UP)
                {
                    mandatoryInformation &= ~ACCESS_MASK_GENERIC_READ;
                }
                if ((objectIntegrityAceMask
                    & SYSTEM_MANDATORY_LABEL_ACE_Mask.SYSTEM_MANDATORY_LABEL_NO_WRITE_UP)
                    == SYSTEM_MANDATORY_LABEL_ACE_Mask.SYSTEM_MANDATORY_LABEL_NO_WRITE_UP)
                {
                    mandatoryInformation &= ~ACCESS_MASK_GENERIC_WRITE;
                }
                if ((objectIntegrityAceMask
                    & SYSTEM_MANDATORY_LABEL_ACE_Mask.SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP)
                    == SYSTEM_MANDATORY_LABEL_ACE_Mask.SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP)
                {
                    mandatoryInformation &= ~ACCESS_MASK_GENERIC_EXECUTE;
                }
            }

            if (token.Privileges != null)
            {
                foreach (_LUID privilege in token.Privileges)
                {
                    if (ObjectUtility.DeepCompare(privilege, GetPrivilegeLuid(PrivilegeName.SE_RELABEL_NAME)))
                    {
                        mandatoryInformation |= ACCESS_MASK_WRITE_OWNER;
                    }
                }
            }
            return true;
        }
        /// <summary>
        /// Create a SYSTEM_SCOPED_POLICY_ID_ACE with specified SID and optional ACE_FLAGS.
        /// </summary>
        /// <param name="sid">A SID that identifies a central access policy.</param>
        /// <param name="flags">An unsigned 8-bit integer that specifies a set of ACE type-specific control flags. </param>
        /// <returns>Return the ACE.</returns>
        public static _SYSTEM_SCOPED_POLICY_ID_ACE CreateSystemScopedPolicyIdAce(_SID sid,
            ACE_FLAGS flags = ACE_FLAGS.OBJECT_INHERIT_ACE | ACE_FLAGS.CONTAINER_INHERIT_ACE)
        {
            _ACE_HEADER aceHeader = new _ACE_HEADER
            {
                AceFlags = flags,
                AceType = ACE_TYPE.SYSTEM_SCOPED_POLICY_ID_ACE_TYPE,
                // Header (4 bytes) + Mask (4 bytes) + SID length;
                // For details, please refer to MS-DTYP.
                AceSize = (ushort)(4 + 4 + DtypUtility.SidLength(sid)),
            };

            _SYSTEM_SCOPED_POLICY_ID_ACE ace = new _SYSTEM_SCOPED_POLICY_ID_ACE
            {
                Header = aceHeader,
                Mask = 0, // An ACCESS_MASK that MUST be set to zero.
                Sid = sid,
            };
            return ace;
        }
Beispiel #10
0
        public _SecurityIdentifier(string sddl)
        {
            _SID sid = DtypUtility.ToSid(sddl);

            this.buffer = TypeMarshal.ToBytes <_SID>(sid);
        }
        /// <summary>
        /// Calculate the length of the ApplicationData byte array according to the specified ace header.
        /// </summary>
        /// <param name="header">The specified ace header.</param>
        /// <param name="sid">The sid of the specified ace.</param>
        /// <returns>The calculated length.</returns>
        /// <exception cref="ArgumentOutOfRangeException">Throw when the ace type is invalid.</exception> 
        internal static int CalculateApplicationDataLength(_ACE_HEADER header, _SID sid)
        {
            int applicationDataLength = 0;
            switch (header.AceType)
            {
                case ACE_TYPE.ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
                case ACE_TYPE.ACCESS_DENIED_CALLBACK_ACE_TYPE:
                case ACE_TYPE.SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
                    //The AceSize contains the following parts:
                    //_ACE_HEADER Header,(4 bytes)
                    //uint Mask,(4 bytes)
                    //_SID Sid;(variable length)
                    //byte[] ApplicationData,(variable length)
                    applicationDataLength =
                        header.AceSize - SHORT_FIXED_ACE_LENGTH - TypeMarshal.ToBytes<_SID>(sid).GetLength(0);
                    break;

                case ACE_TYPE.ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
                case ACE_TYPE.ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
                case ACE_TYPE.SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
                    //The AceSize contains the following parts:
                    //_ACE_HEADER Header,(4 bytes)
                    //uint Mask,(4 bytes)
                    //uint Flags,(4 bytes)
                    //Guid ObjectType,(16 bytes)
                    //Guid InheritedObjectType,(16 bytes)
                    //_SID Sid;(variable length)
                    //byte[] ApplicationData,(variable length)
                    applicationDataLength =
                        header.AceSize - LONG_FIXED_ACE_LENGTH - TypeMarshal.ToBytes<_SID>(sid).GetLength(0);
                    break;

                default:
                    throw new ArgumentOutOfRangeException("header", "The ace type is invalid.");
            }
            return applicationDataLength > 0 ? applicationDataLength : 0;
        }
        /// <summary>
        /// Create an ACCESS_DENIED_ACE by using specific SID, access mask and optional ace flags.
        /// </summary>
        /// <param name="sid">The SID of the trustee.</param>
        /// <param name="mask">An ACCESS_MASK that specifies the user rights denied by this ACE.</param>
        /// <param name="flags">ACE type-specific control flags in the ACE header.</param>
        /// <returns>The constructed ACCESS_DENIED_ACE structure</returns>
        public static _ACCESS_DENIED_ACE CreateAccessDeniedAce(_SID sid, uint mask, ACE_FLAGS flags = ACE_FLAGS.None)
        {
            _ACE_HEADER aceHeader = new _ACE_HEADER
            {
                AceFlags = flags,
                AceType = ACE_TYPE.ACCESS_DENIED_ACE_TYPE,
                // Header (4 bytes) + Mask (4 bytes) + SID length;
                // For details, please refer to MS-DTYP.
                AceSize = (ushort)(4 + 4 + DtypUtility.SidLength(sid)),
            };

            _ACCESS_DENIED_ACE ace = new _ACCESS_DENIED_ACE
            {
                Header = aceHeader,
                Mask = mask,
                Sid = sid,
            };
            return ace;
        }
        /// <summary>
        /// ComputeACL. MS-DTYP section 2.5.4.4
        /// </summary>
        /// <param name="computeType">Enumeration of COMPUTE_DACL and COMPUTE_SACL.</param>
        /// <param name="parentAcl">ACL from the parent security descriptor.</param>
        /// <param name="parentControl">Control flags from the parent security descriptor.</param>
        /// <param name="creatorAcl">ACL supplied in the security descriptor by the creator.</param>
        /// <param name="creatorControl">Control flags supplied in the security descriptor by the creator.</param>
        /// <param name="isContainerObject">TRUE if the object is a container; otherwise, FALSE.</param>
        /// <param name="objectTypes">Array of GUIDs for the object type being created.</param>
        /// <param name="autoInheritFlags">
        /// A set of bit flags that control how access control entries (ACEs) are 
        /// inherited from ParentDescriptor.
        /// </param>
        /// <param name="genericMapping">
        /// Mapping of generic permissions to resource manager-specific permissions supplied by the caller.
        /// </param>
        /// <param name="owner">Owner to use in substituting the CreatorOwner SID.</param>
        /// <param name="group">Group to use in substituting the CreatorGroup SID.</param>
        /// <param name="token">Token for default values.</param>
        /// <param name="computedControl">ComputedControl</param>
        /// <returns>Computed ACL</returns>
        public static _ACL? ComputeACL(
            AclComputeType computeType,
            _ACL? parentAcl,
            SECURITY_DESCRIPTOR_Control parentControl,
            _ACL? creatorAcl,
            SECURITY_DESCRIPTOR_Control creatorControl,
            bool isContainerObject,
            Guid[] objectTypes,
            SecurityDescriptorAutoInheritFlags autoInheritFlags,
            GenericMapping genericMapping,
            _SID owner,
            _SID group,
            Token token,
            out SECURITY_DESCRIPTOR_Control computedControl)
        {
            #region Pseudocode  v20110329

            //// The details of the algorithm to merge the parent ACL and the supplied ACL.
            //// The Control flags computed are slightly different based on whether it is the
            //// ACL in the DACL or the SACL field of the descriptor.
            //// The caller specifies whether it is a DACL or a SACL using the parameter,
            //// ComputeType.
            //Set ComputedACL to NULL
            //Set ComputedControl to NULL

            //CALL ContainsInheritableACEs WITH ParentACL RETURNING ParentHasInheritableACEs

            //IF ParentHasInheritableACEs = TRUE THEN

            //    // The Parent ACL has inheritable ACEs. The Parent ACL should be used if no Creator
            //    // ACL is supplied, or if the Creator ACL was supplied AND it is a default ACL based
            //    // on object type information

            //    IF(CreatorACL is not present) OR
            //      ((CreatorACL is present) AND
            //      (AutoInheritFlags contains DEFAULT_DESCRIPTOR_FOR_OBJECT))
            //    THEN
            //        // Use only the inherited ACEs from the parent.  First compute the ACL from the
            //        // parent ACL, then clean it up by resolving the generic mappings etc.

            //        CALL ComputeInheritedACLFromParent WITH
            //          ACL set to ParentACL,
            //          IsContainerObject set to IsContainerObject,
            //          ObjectTypes set to ObjectTypes

            //        RETURNING NextACL
            //        CALL PostProcessACL WITH
            //          ACL set to NextACL,
            //          CopyFilter set to CopyInheritedAces,
            //          Owner set to Owner,
            //          Group set to Group,
            //          GenericMapping set to GenericMapping

            //        RETURNING FinalACL

            //        Set ComputedACL to FinalACL
            //        RETURN
            //    ENDIF

            //IF ((CreatorACL is present) AND
            //  (AutoInheritFlags does not contain DEFAULT_DESCRIPTOR_FOR_OBJECT))
            //THEN
            //    // Since a creator ACL is present, and we’re not defaulting the
            //    // descriptor, determine which ACEs are inherited and compute the new ACL
            //    CALL PreProcessACLFromCreator WITH
            //       ACL set to CreatorACL
            //    RETURNING PreACL

            //    CALL ComputeInheritedACLFromCreator WITH
            //       ACL set to PreACL,
            //       IsContainerObject set to IsContainerObject,
            //       ObjectTypes set to ObjectTypes
            //    RETURNING TmpACL

            //    //  Special handling for DACL types of ACLs

            //    IF (ComputeType = DACL_COMPUTE) THEN

            //        // DACL-specific operations

            //        IF (CreatorControl does not have DACL_PROTECTED flag set) AND
            //           (AutoInheritFlags contains DACL_AUTO_INHERIT)
            //        THEN

            //            //  We’re not working from a protected DACL, and we’re supposed to
            //            //  allow automatic inheritance.  Compute the inherited ACEs from
            //            //  Parent ACL this time, and append that to the ACL that we’re building

            //            CALL ComputeInheritedACLFromParent WITH
            //              ACL set to ParentACL,
            //              IsContainerObject set to IsContainerObject,
            //              ObjectTypes set to ObjectTypes
            //            RETURNING InheritedParentACL

            //            Append InheritedParentACL.ACEs to TmpACL.ACE
            //            Set DACL_AUTO_INHERITED flag in ComputedControl

            //        ENDIF

            //    ENDIF  // DACL-Specific behavior
            //    IF (ComputeType = SACL_COMPUTE) THEN

            //        // Similar to the above, perform SACL-specific operations

            //        IF (CreatorControl does not have SACL_PROTECTED flag set) AND
            //           (AutoInheritFlags contains SACL_AUTO_INHERIT flag)
            //        THEN

            //            //  We’re not working from a protected SACL, and we’re supposed to
            //            //  allow automatic inheritance.  Compute the inherited ACEs from
            //            //  Parent ACL this time, and append that to the ACL that we’re building

            //            CALL ComputeInheritedACLFromParent WITH
            //              ACL set to ParentACL,
            //              IsContainerObject set to IsContainerObject,
            //              ObjectTypes set to ObjectTypes
            //            RETURNING InheritedParentACL

            //            Append InheritedParentACL.ACEs to TmpACL.ACE
            //            Set SACL_AUTO_INHERITED flag in ComputedControl

            //        ENDIF

            //    ENDIF  // SACL-Specific behavior

            //    CALL PostProcessACL WITH
            //      ACL set to TmpACL,
            //      CopyFilter set to CopyInheritedAces,
            //      Owner set to Owner,
            //      Group set to Group,
            //      GenericMapping set to GenericMapping
            //    RETURNING ProcessedACL

            //    Set ComputedACL to ProcessedACL
            //    RETURN
            //ENDIF  // CreatorACL is present

            //ELSE // ParentACL does not contain inheritable ACEs

            //    IF CreatorACL = NULL THEN
            //        // No ACL supplied for the object
            //        IF (ComputeType = DACL_COMPUTE) THEN
            //            Set TmpACL to Token.DefaultDACL
            //        ELSE
            //            // No default for SACL; left as NULL
            //        ENDIF

            //    ELSE
            //        // Explicit ACL was supplied for the object - either default or not.
            //        // In either case, use it for the object, since there are no inherited ACEs.
            //        CALL PreProcessACLFromCreator WITH CreatorACL
            //        RETURNING TmpACL
            //    ENDIF

            //    CALL PostProcessACL WITH
            //      ACL set to TmpACL,
            //      CopyFilter set to CopyAllAces,
            //      Owner set to Owner,
            //      Group set to Group,
            //      GenericMapping set to GenericMapping

            //        RETURNING ProcessedACL
            //        Set ComputedACL to ProcessedACL

            //ENDIF
            //// END ComputeACL

            #endregion

            _ACL? computedACL = null;
            computedControl = SECURITY_DESCRIPTOR_Control.None;
            _ACL tmpAcl = new _ACL();
            _ACL preAcl = new _ACL();

            if (parentAcl != null && ContainsInheritableACEs(parentAcl.Value))
            {
                // ParentACL contains inheritable ACEs
                if ((creatorAcl == null) || ((creatorAcl != null) && (autoInheritFlags
                    & SecurityDescriptorAutoInheritFlags.DEFAULT_DESCRIPTOR_FOR_OBJECT)
                    == SecurityDescriptorAutoInheritFlags.DEFAULT_DESCRIPTOR_FOR_OBJECT))
                {
                    // Use only the inherited ACEs from the parent
                    _ACL nextAcl = ComputeInheritedACLfromParent(parentAcl.Value, isContainerObject, objectTypes);
                    _ACL finalAcl = PostProcessACL(nextAcl, CopyFilter.CopyInheritedAces, owner, group, genericMapping);
                    computedACL = finalAcl;
                }
                else
                {
                    preAcl = PreProcessACLfromCreator(creatorAcl.Value);
                    tmpAcl = ComputeInheritedACLfromCreator(preAcl, isContainerObject, objectTypes);

                    _ACL? inheritedAcl = null;
                    if ((computeType == AclComputeType.COMPUTE_DACL)
                        && (creatorControl & SECURITY_DESCRIPTOR_Control.DACLProtected)
                            == SECURITY_DESCRIPTOR_Control.None
                        && (autoInheritFlags & SecurityDescriptorAutoInheritFlags.DACL_AUTO_INHERIT)
                            == SecurityDescriptorAutoInheritFlags.DACL_AUTO_INHERIT)
                    {
                        // Compute the inherited ACEs from the parent
                        inheritedAcl = ComputeInheritedACLfromParent(
                            parentAcl.Value,
                            isContainerObject,
                            objectTypes);

                        computedControl |= SECURITY_DESCRIPTOR_Control.DACLAutoInherited;
                    }
                    else if ((computeType == AclComputeType.COMPUTE_SACL)
                        && (creatorControl & SECURITY_DESCRIPTOR_Control.SACLProtected)
                            == SECURITY_DESCRIPTOR_Control.None
                        && (autoInheritFlags & SecurityDescriptorAutoInheritFlags.SACL_AUTO_INHERIT)
                            == SecurityDescriptorAutoInheritFlags.SACL_AUTO_INHERIT)
                    {
                        // Compute the inherited ACEs from the parent
                        inheritedAcl = ComputeInheritedACLfromParent(
                            parentAcl.Value,
                            isContainerObject,
                            objectTypes);

                        computedControl |= SECURITY_DESCRIPTOR_Control.SACLAutoInherited;
                    }
                    if (inheritedAcl != null)
                    {
                        List<object> tmpAces = new List<object>();
                        tmpAces.AddRange(tmpAcl.Aces);
                        tmpAces.AddRange(inheritedAcl.Value.Aces);
                        tmpAcl.Aces = tmpAces.ToArray();
                        tmpAcl.AceCount = (ushort)tmpAcl.Aces.Length;
                        tmpAcl.AclSize = DtypUtility.CalculateAclSize(tmpAcl);
                    }

                    computedACL = PostProcessACL(tmpAcl, CopyFilter.CopyInheritedAces, owner, group, genericMapping);
                }
            }
            else
            {
                // ParentACL does not contain inheritable ACEs
                if (creatorAcl == null)
                {
                    if (computeType == AclComputeType.COMPUTE_DACL)
                    {
                        tmpAcl = token.DefaultDACL;
                    }
                    else
                    {
                        //No default for SACL;left as NULL
                        return null;
                    }
                }
                else
                {
                    // Explicit ACL was supplied for the object - either default or not.
                    // In either case, use it for the object, since there are no inherited ACEs.
                    tmpAcl = PreProcessACLfromCreator(creatorAcl.Value);
                }
                computedACL = PostProcessACL(tmpAcl, CopyFilter.CopyAllAces, owner, group, genericMapping);
            }

            if (computedACL != null)
            {
                computedControl |= ((computeType == AclComputeType.COMPUTE_DACL)
                    ? SECURITY_DESCRIPTOR_Control.DACLPresent
                    : SECURITY_DESCRIPTOR_Control.SACLPresent);
            }
            return computedACL;
        }
        private SystemResourceAttributeAce(string attributeName)
        {
            if (attributeName.Length < 2)
            {
                throw new ArgumentException("attributeName must be at least 4 bytes in length.");
            }

            AttributeName = attributeName;
            Sid = DtypUtility.GetWellKnownSid(WellKnownSid.EVERYONE, null);
            AttributeData.Flags = CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1.FlagEnum.CLAIM_SECURITY_ATTRIBUTE_MANDATORY
                | CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1.FlagEnum.FCI_CLAIM_SECURITY_ATTRIBUTE_MANUAL;
            Mask = 0;
            Header = new _ACE_HEADER
            {
                AceFlags = ACE_FLAGS.CONTAINER_INHERIT_ACE | ACE_FLAGS.OBJECT_INHERIT_ACE,
                AceType = ACE_TYPE.SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE,
                // Size would be filled later
            };
        }
 /// <summary>
 /// This algorithm returns the size, in bytes, of SID. This is equal to the number of bytes occupied by the Revision, 
 /// SubAuthorityCount, and IdentifierAuthorityCount fields of a SID. Added to this is the size of a SubAuthority field 
 /// of a SID times SID.SubAuthorityCount.
 /// </summary>
 /// <param name="sid">The SID to be calculated.</param>
 /// <returns>The length of the specified SID.</returns>
 public static int SidLength(_SID sid)
 {
     return (8 + (4 * sid.SubAuthorityCount));
 }
        /// <summary>
        /// Convert SID to SDDL string.
        /// </summary>
        /// <param name="sid">SID to convert.</param>
        /// <returns>SDDL string.</returns>
        /// <exception cref="ArgumentException">
        /// Thrown when the Revision field of sid is invalid. 
        /// Thrown when the length of identifierAuthority is not 6 bytes.
        /// Thrown when the IdentifierAuthority field of sid is null.
        /// </exception>
        public static string ToSddlString(_SID sid)
        {
            //
            //SID String Format Syntax
            //
            //SID= "S-1-" IdentifierAuthority 1*SubAuthority
            //IdentifierAuthority= IdentifierAuthorityDec / IdentifierAuthorityHex
            //; If the identifier authority is < 2^32, the
            //; identifier authority is represented as a decimal
            //; number
            //; If the identifier authority is >= 2^32,
            //; the identifier authority is represented in
            //; hexadecimal
            //IdentifierAuthorityDec = 1*10DIGIT
            //; IdentifierAuthorityDec, top level authority of a
            //; security identifier is represented as a decimal number
            //IdentifierAuthorityHex = "0x" 12HEXDIG
            //; IdentifierAuthorityHex, the top-level authority of a
            //; security identifier is represented as a hexadecimal number
            //SubAuthority= "-" 1*10DIGIT
            //; Sub-Authority is always represented as a decimal number
            //; No leading "0" characters are allowed when IdentifierAuthority
            //; or SubAuthority is represented as a decimal number
            //; All hexadecimal digits must be output in string format,
            //; pre-pended by "0x"

            if (sid.Revision != 1)
            {
                throw new ArgumentException("The Revision field of sid is invalid.", "sid");
            }

            //S-1: Indicates a revision or version 1 SID.
            string sddlString = "S-1-";

            if (sid.IdentifierAuthority == null)
            {
                throw new ArgumentException("The IdentifierAuthority field of sid is null.", "sid");
            }
            if (sid.IdentifierAuthority.Length != SID_AUTHORITY_LENGTH)
            {
                throw new ArgumentException("Incorrect size of identifierAuthority field.", "sid");
            }

            ulong identifierAuthority = 0;
            for (int i = 0; i < sid.IdentifierAuthority.Length; i++)
            {
                identifierAuthority = (identifierAuthority << 8) + sid.IdentifierAuthority[i];
            }
            if ((sid.IdentifierAuthority[0] == 0) && (sid.IdentifierAuthority[1] == 0))
            {
                sddlString += string.Format(CultureInfo.InvariantCulture, "{0:D}", identifierAuthority);
            }
            else
            {
                sddlString += string.Format(CultureInfo.InvariantCulture, "0x{0:X12}", identifierAuthority);
            }

            for (int i = 0; i < sid.SubAuthorityCount; i++)
            {
                sddlString += string.Format(CultureInfo.InvariantCulture, "-{0:D}", sid.SubAuthority[i]);
            }

            return sddlString;
        }
        /// <summary>
        /// Create a _SECURITY_DESCRIPTOR structure in self-relative format.
        /// </summary>
        /// <param name="control">An unsigned 16-bit field that specifies control access bit flags.</param>
        /// <param name="ownerSid">The SID of the owner of the object</param>
        /// <param name="groupSid">The SID of the group of the object.</param>
        /// <param name="sacl">The SACL of the object.</param>
        /// <param name="dacl">The DACL of the object.</param>
        /// <returns> Output security descriptor for the object.</returns>
        public static _SECURITY_DESCRIPTOR CreateSecurityDescriptor(
            SECURITY_DESCRIPTOR_Control control,
            _SID? ownerSid,
            _SID? groupSid,
            _ACL? sacl,
            _ACL? dacl)
        {
            RawAcl sRawAcl = null;
            RawAcl dRawAcl = null;
            SecurityIdentifier rawOwnerSid = null;
            SecurityIdentifier rawGroupSid = null;
            if (ownerSid != null)
            {
                rawOwnerSid = new SecurityIdentifier(TypeMarshal.ToBytes(ownerSid.Value), 0);
            }
            if (groupSid != null)
            {
                rawGroupSid = new SecurityIdentifier(TypeMarshal.ToBytes(groupSid.Value), 0);
            }
            if (sacl != null)
            {
                sRawAcl = new RawAcl(DtypUtility.EncodeAcl(sacl.Value), 0);
            }
            if (dacl != null)
            {
                dRawAcl = new RawAcl(DtypUtility.EncodeAcl(dacl.Value), 0);
            }
            RawSecurityDescriptor rawSecurityDescriptor = new RawSecurityDescriptor(
                (ControlFlags)control,
                rawOwnerSid,
                rawGroupSid,
                sRawAcl,
                dRawAcl);
            byte[] rawSecurityDescriptorBytes = new byte[rawSecurityDescriptor.BinaryLength];
            rawSecurityDescriptor.GetBinaryForm(rawSecurityDescriptorBytes, 0);

            return DtypUtility.DecodeSecurityDescriptor(rawSecurityDescriptorBytes);
        }
        /// <summary>
        /// Access Check Algorithm. MS-DTYP section 2.5.4.1
        /// </summary>
        /// <param name="securityDescriptor">
        /// SECURITY_DESCRIPTOR structure that is assigned to the object.
        /// </param>
        /// <param name="token">
        /// Token is an authorization context containing all SIDs 
        /// that represent the security principal
        /// </param>
        /// <param name="accessRequestMask">
        /// Set of permissions requested on the object.
        /// </param>
        /// <param name="objectTree">
        /// A tree representation of the hierarchy of objects for which 
        /// to check access. Each node represents an object with two values. 
        /// A GUID that represents the object itself and a value called 
        /// Remaining, which indicates the user rights request for that 
        /// node that have not yet been satisfied. It can be null.
        /// </param>
        /// <param name="principalSelfSubstitudeSid">
        /// A SID that logically replaces the SID in any ACE that contains 
        /// the well-known PRINCIPAL_SELF SID. It can be null.
        /// </param>
        /// <returns>
        /// Returns TRUE if access is allowed. Otherwise, it returns FALSE if access is denied. 
        /// </returns>
        /// <exception cref="ArgumentException">
        /// Thrown when the Dacl field of securityDescriptor doesn't exist, but the DACLPresent flag is set.
        /// Thrown when the Revision field of securityDescriptor is invalid
        /// </exception>
        public static bool AccessCheck(
            _SECURITY_DESCRIPTOR securityDescriptor,
            Token token,
            uint accessRequestMask,
            AccessCheckObjectTree objectTree,
            _SID? principalSelfSubstitudeSid)
        {
            //MS-ADTS Section 5.1.3.3.1 Null vs. Empty DACLs
            //The presence of a NULL DACL in the nTSecurityDescriptor attribute of an object grants full
            //access to the object to any principal that requests it; normal access checks are not performed
            //with respect to the object.

            if (securityDescriptor.Revision != 0x1)
            {
                throw new ArgumentException("The Revision field is invalid.", "securityDescriptor");
            }

            if ((securityDescriptor.Control & SECURITY_DESCRIPTOR_Control.DACLPresent)
                == SECURITY_DESCRIPTOR_Control.None)
            {
                return true;
            }
            else if (securityDescriptor.Dacl == null)
            {
                throw new ArgumentException(
                    "The Dacl field of securityDescriptor doesn't exist, but the DACLPresent flag is set.", "securityDescriptor");
            }

            //Pscudocode
            //
            //Set DACL to SecurityDescriptor Dacl field
            //Set RemainingAccess to Access Request mask
            //
            //IF RemainingAccess contains ACCESS_SYSTEM_SECURITY access flag THEN
            //IF Token.Privileges contains SeSecurityPrivilege THEN
            //Remove ACCESS_SYSTEM_SECURITY access bit from RemainingAccess
            //END IF
            //END IF
            //
            //IF RemainingAccess contains WRITE_OWNER access bit THEN
            //IF Token.Privileges contains SeTakeOwnershipPrivilege THEN
            //Remove WRITE_OWNER access bit from RemainingAccess
            //END IF
            //END IF
            //-- the owner of an object is always granted READ_CONTROL and WRITE_DAC.
            //CALL SidInToken( Token, SecurityDescriptor.Owner, PrincipalSelfSubst)
            //IF SidInToken returns True THEN
            //Remove READ_CONTROL and WRITE_DAC from RemainingAccess
            //END IF

            _ACL? dacl = securityDescriptor.Dacl;
            uint remainingAccess = accessRequestMask;
            AccessCheckObjectTree localTree = new AccessCheckObjectTree();
            Guid[] allNodes = new Guid[] { };

            if ((remainingAccess & ACCESS_MASK_ACCESS_SYSTEM_SECURITY) != 0 && token.Privileges != null)
            {
                foreach (_LUID privilege in token.Privileges)
                {
                    if (ObjectUtility.DeepCompare(privilege, GetPrivilegeLuid(PrivilegeName.SE_SECURITY_NAME)))
                    {
                        remainingAccess &= ~ACCESS_MASK_ACCESS_SYSTEM_SECURITY;
                    }
                }
            }
            if ((remainingAccess & ACCESS_MASK_WRITE_OWNER) != 0 && token.Privileges != null)
            {
                foreach (_LUID privilege in token.Privileges)
                {
                    if (ObjectUtility.DeepCompare(privilege, GetPrivilegeLuid(PrivilegeName.SE_TAKE_OWNERSHIP_NAME)))
                    {
                        remainingAccess &= ~ACCESS_MASK_WRITE_OWNER;
                    }
                }
            }
            if (securityDescriptor.OwnerSid != null
                && SidInToken(token, securityDescriptor.OwnerSid.Value, principalSelfSubstitudeSid))
            {
                remainingAccess &= ~(uint)(ACCESS_MASK_READ_CONTROL | ACCESS_MASK_WRITE_DAC);
            }

            //IF Object Tree is not NULL THEN
            //Set LocalTree to Object Tree
            //FOR each node in LocalTree DO
            //Set node.Remaining to RemainingAccess
            //END FOR
            //END IF

            if (objectTree != null && objectTree.Root != null)
            {
                localTree = (AccessCheckObjectTree)ObjectUtility.DeepClone(objectTree);
                List<Guid> tmpList = new List<Guid>();
                tmpList.Add(localTree.Root.Value);
                tmpList.AddRange(localTree.GetDescendentNodes(localTree.Root.Value));
                allNodes = tmpList.ToArray();
                foreach (Guid node in allNodes)
                {
                    localTree.SetTreeNodeData(node, remainingAccess);
                }
            }

            //FOR each ACE in DACL DO
            //IF ACE.flag does not contain INHERIT_ONLY_ACE THEN
            //CASE ACE.Type OF
            //CASE Allow Access:
            //CALL SidInToken( Token, ACE.Sid, and PrincipalSelfSubst )
            //IF SidInToken returns True THEN
            //    Remove ACE.AccessMask from RemainingAccess
            //    FOR each node in LocalTree DO
            //    Remove ACE.AccessMask from node.Remaining
            //END FOR
            //END IF
            //CASE Deny Access:
            //CALL SidInToken( Token, ACE.Sid, PrincipalSelfSubst )
            //IF SidInToken returns True THEN
            //    IF any bit of RemainingAccess is in ACE.AccessMask THEN
            //    Return access_denied
            //END IF
            //END IF
            //CASE Object Allow Access:
            //CALL SidInToken( Token, ACE.Sid, PrincipalSelfSubst )
            //IF SidInToken returns True THEN
            //    IF ACE.Object is contained in LocalTree THEN
            //    Locate node n in LocalTree such that
            //    n.GUID is the same as ACE.Object
            //    Remove ACE.AccessMask from n.Remaining
            //    FOR each node ns such that ns is a descendent of n DO
            //    Remove ACE.AccessMask from ns.Remaining
            //    END FOR
            //    FOR each node np such that np is an ancestor of n DO
            //    Set np.Remaining = np.Remaining or np-1.Remaining
            //END FOR
            //END IF
            //END IF
            //CASE Object Deny Access:
            //CALL SidInToken( Token, ACE.Sid, PrincipalSelfSubst )
            //IF SidInToken returns True THEN
            //    Locate node n in LocalTree such that
            //    n.GUID is the same as ACE.Object
            //    IF n exists THEN
            //    If any bit of n.Remaining is in ACE.AccessMask THEN
            //    Return access_denied
            //END IF
            //END IF
            //END IF
            //END CASE
            //END IF
            //END FOR

            if (dacl.Value.Aces != null)
            {
                foreach (object ace in dacl.Value.Aces)
                {
                    _ACE_HEADER header = (_ACE_HEADER)ObjectUtility.GetFieldValue(ace, "Header");
                    _SID sid = (_SID)ObjectUtility.GetFieldValue(ace, "Sid");

                    if ((header.AceFlags & ACE_FLAGS.INHERIT_ONLY_ACE) == ACE_FLAGS.INHERIT_ONLY_ACE
                        || !SidInToken(token, sid, principalSelfSubstitudeSid))
                    {
                        continue;
                    }

                    bool ret = DtypUtility.AceAccessCheck(ace, ref remainingAccess, ref localTree, allNodes);
                    if (ret == false)
                    {
                        return false;
                    }
                }
            }

            //IF RemainingAccess = 0 THEN
            //Return success
            //Else
            //Return access_denied
            //END IF

            bool status;
            if (objectTree != null && objectTree.Root != null)
            {
                status = (localTree.GetTreeNodeData(localTree.Root.Value) == 0);
            }
            else
            {
                status = (remainingAccess == 0);
            }
            return status;
        }
        /// <summary>
        /// Create an instance of SID.
        /// </summary>
        /// <param name="identifierAuthority">
        /// Six element arrays of 8-bit unsigned integers that specify 
        /// the top-level authority of a RPC_SID.
        /// </param>
        /// <param name="subAuthorities">
        /// A variable length array of unsigned 32-bit integers that 
        /// uniquely identifies a principal relative to the IdentifierAuthority.
        /// </param>
        /// <returns>Created SID structure.</returns>
        /// <exception cref="ArgumentNullException">
        /// Thrown when identifierAuthority or subAuthorities is null.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// Thrown when length of identifierAuthority is not 6 bytes.
        /// </exception>
        public static _SID CreateSid(
            byte[] identifierAuthority,
            params uint[] subAuthorities)
        {
            if (identifierAuthority == null)
            {
                throw new ArgumentNullException("identifierAuthority");
            }
            if (identifierAuthority.Length != SID_AUTHORITY_LENGTH)
            {
                throw new ArgumentException("Incorrect size of identifierAuthority.", "identifierAuthority");
            }
            if (subAuthorities == null)
            {
                throw new ArgumentNullException("subAuthorities");
            }

            const byte DEFAULT_REVISION = 1;

            _SID sid = new _SID();
            sid.Revision = DEFAULT_REVISION;
            sid.SubAuthorityCount = (byte)subAuthorities.Length;
            sid.IdentifierAuthority = identifierAuthority;
            sid.SubAuthority = subAuthorities;
            return sid;
        }