SID.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / clr / src / BCL / System / Security / Principal / SID.cs / 1 / SID.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 

using Microsoft.Win32; 
using Microsoft.Win32.SafeHandles; 
using System;
using System.Security.Permissions; 
using System.Text;
using System.Runtime.InteropServices;
using System.Globalization;
 
namespace System.Security.Principal
{ 
    // 
    // Identifier authorities
    // 

    internal enum IdentifierAuthority : long
    {
        NullAuthority                            = 0, 
        WorldAuthority                           = 1,
        LocalAuthority                           = 2, 
        CreatorAuthority                         = 3, 
        NonUniqueAuthority                       = 4,
        NTAuthority                              = 5, 
        SiteServerAuthority                      = 6,
        InternetSiteAuthority                    = 7,
        ExchangeAuthority                        = 8,
        ResourceManagerAuthority                 = 9, 
    }
 
    // 
    // SID name usage
    // 

    internal enum SidNameUse
    {
        User                              = 1, 
        Group                             = 2,
        Domain                            = 3, 
        Alias                             = 4, 
        WellKnownGroup                    = 5,
        DeletedAccount                    = 6, 
        Invalid                           = 7,
        Unknown                           = 8,
        Computer                          = 9,
    } 

    // 
    // Well-known SID types 
    //
 
[System.Runtime.InteropServices.ComVisible(false)]
    public enum WellKnownSidType
    {
        NullSid                                  = 0, 
        WorldSid                                 = 1,
        LocalSid                                 = 2, 
        CreatorOwnerSid                          = 3, 
        CreatorGroupSid                          = 4,
        CreatorOwnerServerSid                    = 5, 
        CreatorGroupServerSid                    = 6,
        NTAuthoritySid                           = 7,
        DialupSid                                = 8,
        NetworkSid                               = 9, 
        BatchSid                                 = 10,
        InteractiveSid                           = 11, 
        ServiceSid                               = 12, 
        AnonymousSid                             = 13,
        ProxySid                                 = 14, 
        EnterpriseControllersSid                 = 15,
        SelfSid                                  = 16,
        AuthenticatedUserSid                     = 17,
        RestrictedCodeSid                        = 18, 
        TerminalServerSid                        = 19,
        RemoteLogonIdSid                         = 20, 
        LogonIdsSid                              = 21, 
        LocalSystemSid                           = 22,
        LocalServiceSid                          = 23, 
        NetworkServiceSid                        = 24,
        BuiltinDomainSid                         = 25,
        BuiltinAdministratorsSid                 = 26,
        BuiltinUsersSid                          = 27, 
        BuiltinGuestsSid                         = 28,
        BuiltinPowerUsersSid                     = 29, 
        BuiltinAccountOperatorsSid               = 30, 
        BuiltinSystemOperatorsSid                = 31,
        BuiltinPrintOperatorsSid                 = 32, 
        BuiltinBackupOperatorsSid                = 33,
        BuiltinReplicatorSid                     = 34,
        BuiltinPreWindows2000CompatibleAccessSid = 35,
        BuiltinRemoteDesktopUsersSid             = 36, 
        BuiltinNetworkConfigurationOperatorsSid  = 37,
        AccountAdministratorSid                  = 38, 
        AccountGuestSid                          = 39, 
        AccountKrbtgtSid                         = 40,
        AccountDomainAdminsSid                   = 41, 
        AccountDomainUsersSid                    = 42,
        AccountDomainGuestsSid                   = 43,
        AccountComputersSid                      = 44,
        AccountControllersSid                    = 45, 
        AccountCertAdminsSid                     = 46,
        AccountSchemaAdminsSid                   = 47, 
        AccountEnterpriseAdminsSid               = 48, 
        AccountPolicyAdminsSid                   = 49,
        AccountRasAndIasServersSid               = 50, 
        NtlmAuthenticationSid                    = 51,
        DigestAuthenticationSid                  = 52,
        SChannelAuthenticationSid                = 53,
        ThisOrganizationSid                      = 54, 
        OtherOrganizationSid                     = 55,
        BuiltinIncomingForestTrustBuildersSid    = 56, 
        BuiltinPerformanceMonitoringUsersSid     = 57, 
        BuiltinPerformanceLoggingUsersSid        = 58,
        BuiltinAuthorizationAccessSid            = 59, 
        WinBuiltinTerminalServerLicenseServersSid= 60,
        MaxDefined = WinBuiltinTerminalServerLicenseServersSid,
    }
 
    //
    // This class implements revision 1 SIDs 
    // NOTE: The SecurityIdentifier class is immutable and must remain this way 
    //
 
[System.Runtime.InteropServices.ComVisible(false)]
    public sealed class SecurityIdentifier : IdentityReference, IComparable
    {
        #region Public Constants 

        // 
        // Identifier authority must be at most six bytes long 
        //
 
        internal static readonly long MaxIdentifierAuthority = 0xFFFFFFFFFFFF;

        //
        // Maximum number of subauthorities in a SID 
        //
 
        internal static readonly byte MaxSubAuthorities = 15; 

        // 
        // Minimum length of a binary representation of a SID
        //

        public static readonly int MinBinaryLength = 1 + 1 + 6; // Revision (1) + subauth count (1) + identifier authority (6) 

        // 
        // Maximum length of a binary representation of a SID 
        //
 
        public static readonly int MaxBinaryLength = 1 + 1 + 6 + MaxSubAuthorities * 4; // 4 bytes for each subauth

        #endregion
 
        #region Private Members
 
        // 
        // Immutable properties of a SID
        // 

        private IdentifierAuthority _IdentifierAuthority;
        private int[] _SubAuthorities;
        private byte[] _BinaryForm; 
        private SecurityIdentifier _AccountDomainSid;
        bool _AccountDomainSidInitialized = false; 
 
        //
        // Computed attributes of a SID 
        //

        private string _SddlForm = null;
 
        #endregion
 
        #region Constructors 

        // 
        // Shared constructor logic
        // NOTE: subauthorities are really unsigned integers, but due to CLS
        //       lack of support for unsigned integers the caller must perform
        //       the typecast 
        //
 
        private void CreateFromParts( IdentifierAuthority identifierAuthority, int[] subAuthorities ) 
        {
            if ( subAuthorities == null ) 
            {
                throw new ArgumentNullException( "subAuthorities" );
            }
 

            // 
            // Check the number of subauthorities passed in 
            //
 
            if ( subAuthorities.Length > MaxSubAuthorities )
            {
                throw new ArgumentOutOfRangeException(
                    "subAuthorities.Length", 
                    subAuthorities.Length,
                    Environment.GetResourceString( "IdentityReference_InvalidNumberOfSubauthorities",  MaxSubAuthorities)); 
            } 

            // 
            // Identifier authority is atmost 6 bytes long
            //

            if ( identifierAuthority < 0  || 
                (long) identifierAuthority > MaxIdentifierAuthority )
            { 
                throw new ArgumentOutOfRangeException( 
                    "identifierAuthority",
                    identifierAuthority, 
                    Environment.GetResourceString( "IdentityReference_IdentifierAuthorityTooLarge" ));
            }

            // 
            // Create a local copy of the data passed in
            // 
 
            _IdentifierAuthority = identifierAuthority;
            _SubAuthorities = new int[ subAuthorities.Length ]; 
            subAuthorities.CopyTo( _SubAuthorities, 0 );

            //
            // Compute and store the binary form 
            //
            // typedef struct _SID { 
            //     UCHAR Revision; 
            //     UCHAR SubAuthorityCount;
            //     SID_IDENTIFIER_AUTHORITY IdentifierAuthority; 
            //     ULONG SubAuthority[ANYSIZE_ARRAY]
            // } SID, *PISID;
            //
 
            byte i;
            _BinaryForm = new byte[1 + 1 + 6 + 4 * this.SubAuthorityCount]; 
 
            //
            // First two bytes contain revision and subauthority count 
            //

            _BinaryForm[0] = Revision;
            _BinaryForm[1] = ( byte )this.SubAuthorityCount; 

            // 
            // Identifier authority takes up 6 bytes 
            //
 
            for ( i = 0; i < 6; i++ )
            {
                _BinaryForm[2+i] = ( byte )(((( ulong )this._IdentifierAuthority ) >> (( 5 - i ) * 8 )) & 0xFF ) ;
            } 

            // 
            // Subauthorities go last, preserving big-endian representation 
            //
 
            for ( i = 0; i < this.SubAuthorityCount; i++ )
            {
                byte shift;
                for ( shift = 0; shift < 4; shift += 1 ) 
                {
                    _BinaryForm[8 + 4*i + shift] = ( byte )((( ulong )_SubAuthorities[i] ) >> ( shift * 8 )); 
                } 
            }
        } 

        private void CreateFromBinaryForm( byte[] binaryForm, int offset )
        {
            IdentifierAuthority Authority; 
            int[] SubAuthorities;
 
            // 
            // Give us something to work with
            // 

            if ( binaryForm == null )
            {
                throw new ArgumentNullException( "binaryForm" ); 
            }
 
            // 
            // Negative offsets are not allowed
            // 

            if ( offset < 0 )
            {
                throw new ArgumentOutOfRangeException( 
                    "offset",
                    offset, 
                    Environment.GetResourceString( "ArgumentOutOfRange_NeedNonNegNum" )); 
            }
 
            //
            // At least a minimum-size SID should fit in the buffer
            //
 
            if ( binaryForm.Length - offset < SecurityIdentifier.MinBinaryLength )
            { 
                throw new ArgumentOutOfRangeException( 
                    "binaryForm",
                    Environment.GetResourceString( "ArgumentOutOfRange_ArrayTooSmall" )); 
            }

            //
            // Extract the elements of a SID 
            //
 
            if ( binaryForm[offset] != Revision ) 
            {
                // 
                // Revision is incorrect
                //

                throw new ArgumentException( 
                    Environment.GetResourceString( "IdentityReference_InvalidSidRevision" ),
                    "binaryForm" ); 
            } 

            // 
            // Insist on the correct number of subauthorities
            //

            if ( binaryForm[offset + 1] > MaxSubAuthorities ) 
            {
                throw new ArgumentException( 
                    Environment.GetResourceString( "IdentityReference_InvalidNumberOfSubauthorities", MaxSubAuthorities ), 
                    "binaryForm" );
            } 

            //
            // Make sure the buffer is big enough
            // 

            int Length = 1 + 1 + 6 + 4 * binaryForm[offset + 1]; 
 
            if ( binaryForm.Length - offset < Length )
            { 
                throw new ArgumentException(
                    Environment.GetResourceString( "ArgumentOutOfRange_ArrayTooSmall" ),
                    "binaryForm" );
            } 

            Authority = 
                ( IdentifierAuthority )( 
                ((( long )binaryForm[offset + 2]) << 40 ) +
                ((( long )binaryForm[offset + 3]) << 32 ) + 
                ((( long )binaryForm[offset + 4]) << 24 ) +
                ((( long )binaryForm[offset + 5]) << 16 ) +
                ((( long )binaryForm[offset + 6]) << 8 ) +
                ((( long )binaryForm[offset + 7]) )); 

            SubAuthorities = new int[binaryForm[offset + 1]]; 
 
            //
            // Subauthorities are represented in big-endian format 
            //

            for ( byte i = 0; i < binaryForm[offset + 1]; i++ )
            { 
                SubAuthorities[i] =
                    ( int )( 
                    ((( uint )binaryForm[offset + 8 + 4*i + 0]) << 0 ) + 
                    ((( uint )binaryForm[offset + 8 + 4*i + 1]) << 8 ) +
                    ((( uint )binaryForm[offset + 8 + 4*i + 2]) << 16 ) + 
                    ((( uint )binaryForm[offset + 8 + 4*i + 3]) << 24 ));
            }

            CreateFromParts( Authority, SubAuthorities ); 

            return; 
 
        }
 
        //
        // Constructs a SecurityIdentifier object from its string representation
        // Returns 'null' if string passed in is not a valid SID
        // NOTE: although there is a P/Invoke call involved in the implementation of this method, 
        //       there is no security risk involved, so no security demand is being made.
        // 
 
        public SecurityIdentifier( string sddlForm )
        { 
            byte[] resultSid;

            //
            // Give us something to work with 
            //
 
            if ( sddlForm == null ) 
            {
                throw new ArgumentNullException( "sddlForm" ); 
            }

            //
            // Call into the underlying O/S conversion routine 
            //
 
            int Error = Win32.CreateSidFromString( sddlForm, out resultSid ); 

            if ( Error == Win32Native.ERROR_INVALID_SID ) 
            {
                throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidValue" ), "sddlForm" );
            }
            else if ( Error == Win32Native.ERROR_NOT_ENOUGH_MEMORY ) 
            {
            	  throw new OutOfMemoryException(); 
            } 
            else if ( Error != Win32Native.ERROR_SUCCESS )
            { 
                BCLDebug.Assert( false, string.Format( CultureInfo.InvariantCulture, "Win32.CreateSidFromString returned unrecognized error {0}", Error ));
                throw new SystemException(Win32Native.GetMessage(Error));
            }
 
            CreateFromBinaryForm( resultSid, 0 );
        } 
 
        //
        // Constructs a SecurityIdentifier object from its binary representation 
        //

        public SecurityIdentifier( byte[] binaryForm, int offset )
        { 
            CreateFromBinaryForm( binaryForm, offset );
        } 
 
        //
        // Constructs a SecurityIdentifier object from an IntPtr 
        //
        [SecurityPermission(SecurityAction.Demand, UnmanagedCode=true)]
        public SecurityIdentifier( IntPtr binaryForm )
            : this( binaryForm, true ) 
        {
        } 
 
        internal SecurityIdentifier( IntPtr binaryForm, bool noDemand )
            : this( Win32.ConvertIntPtrSidToByteArraySid( binaryForm ), 0 ) 
        {
        }

        // 
        // Constructs a well-known SID
        // The 'domainSid' parameter is optional and only used 
        // by the well-known types that require it 
        // NOTE: although there is a P/Invoke call involved in the implementation of this constructor,
        //       there is no security risk involved, so no security demand is being made. 
        //

        public SecurityIdentifier( WellKnownSidType sidType, SecurityIdentifier domainSid )
        { 
            byte[] resultSid;
            int Error; 
 
            //
            // Check if well known sids are supported on this platform 
            //
            if (!Win32.WellKnownSidApisSupported) {
                throw new PlatformNotSupportedException( Environment.GetResourceString( "PlatformNotSupported_RequiresW2kSP3" ));
            } 

            // 
            // sidType must not be equal to LogonIdsSid 
            //
 
            if (sidType == WellKnownSidType.LogonIdsSid)
            {
                throw new ArgumentException( Environment.GetResourceString( "IdentityReference_CannotCreateLogonIdsSid" ), "sidType" );
            } 

            // 
            // sidType should not exceed the max defined value 
            //
 
            if ((sidType < WellKnownSidType.NullSid) || (sidType > WellKnownSidType.MaxDefined))
            {
                throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidValue" ), "sidType" );
            } 

            // 
            // for sidType between 38 to 50, the domainSid parameter must be specified 
            //
 
            if ((sidType >= WellKnownSidType.AccountAdministratorSid) && (sidType <= WellKnownSidType.AccountRasAndIasServersSid))
            {
                if (domainSid == null) {
                    throw new ArgumentNullException( "domainSid", Environment.GetResourceString( "IdentityReference_DomainSidRequired", sidType) ); 
                }
 
                // 
                // verify that the domain sid is a valid windows domain sid
                // to do that we call GetAccountDomainSid and the return value should be the same as the domainSid 
                //

                SecurityIdentifier resultDomainSid;
                int ErrorCode; 

                ErrorCode = Win32.GetWindowsAccountDomainSid( domainSid, out resultDomainSid ); 
 
                if ( ErrorCode == Win32Native.ERROR_INSUFFICIENT_BUFFER ) {
                    throw new OutOfMemoryException(); 
                }
                else if ( ErrorCode == Win32Native.ERROR_NON_ACCOUNT_SID )
                {
                    // this means that the domain sid is not valid 
                    throw new ArgumentException( Environment.GetResourceString( "IdentityReference_NotAWindowsDomain" ), "domainSid" );
                } 
                else if ( ErrorCode != Win32Native.ERROR_SUCCESS ) 
                {
                    BCLDebug.Assert( false, string.Format( CultureInfo.InvariantCulture, "Win32.GetWindowsAccountDomainSid returned unrecognized error {0}", ErrorCode) ); 
                    throw new SystemException(Win32Native.GetMessage(ErrorCode));
                }

                // 
                // if domainSid is passed in as S-1-5-21-3-4-5-6,  the above api will return S-1-5-21-3-4-5 as the domainSid
                // Since these do not match S-1-5-21-3-4-5-6 is not a valid domainSid (wrong number of subauthorities) 
                // 
                if (resultDomainSid != domainSid) {
                    throw new ArgumentException( Environment.GetResourceString( "IdentityReference_NotAWindowsDomain" ), "domainSid" ); 
                }

            }
 

            Error = Win32.CreateWellKnownSid( sidType, domainSid, out resultSid ); 
 
            if ( Error == Win32Native.ERROR_INVALID_PARAMETER )
            { 
                throw new ArgumentException( Win32Native.GetMessage(Error), "sidType/domainSid" );
            }
            else if ( Error != Win32Native.ERROR_SUCCESS )
            { 
                BCLDebug.Assert( false, string.Format( CultureInfo.InvariantCulture, "Win32.CreateWellKnownSid returned unrecognized error {0}", Error ));
                throw new SystemException( Win32Native.GetMessage( Error )); 
            } 

            CreateFromBinaryForm( resultSid, 0 ); 
        }

        internal SecurityIdentifier( SecurityIdentifier domainSid, uint rid )
        { 
            int i;
            int[] SubAuthorities = new int[ domainSid.SubAuthorityCount + 1 ]; 
 
            for ( i = 0; i < domainSid.SubAuthorityCount; i++ )
            { 
                SubAuthorities[i] = domainSid.GetSubAuthority( i );
            }

            SubAuthorities[i] = ( int )rid; 

            CreateFromParts( domainSid.IdentifierAuthority, SubAuthorities ); 
        } 

        internal SecurityIdentifier( IdentifierAuthority identifierAuthority, int[] subAuthorities ) 
        {
            CreateFromParts( identifierAuthority, subAuthorities );
        }
 
        #endregion
 
        #region Static Properties 

        // 
        // Revision is always '1'
        //

        internal static byte Revision 
        {
            get { return 1; } 
        } 

        #endregion 

        #region Non-static Properties

        // 
        // This is for internal consumption only, hence it is marked 'internal'
        // Making this call public would require a deep copy of the data to 
        // prevent the caller from messing with the internal representation. 
        //
 
        internal byte[] BinaryForm
        {
            get { return _BinaryForm; }
        } 

        internal IdentifierAuthority IdentifierAuthority 
        { 
            get { return _IdentifierAuthority; }
        } 

        internal int SubAuthorityCount
        {
            get { return _SubAuthorities.Length; } 
        }
 
        public int BinaryLength 
        {
            get 
            {
                return _BinaryForm.Length;
            }
        } 

        // 
        // Returns the domain portion of a SID or null if the specified 
        // SID is not an account SID
        // NOTE: although there is a P/Invoke call involved in the implementation of this method, 
        //       there is no security risk involved, so no security demand is being made.
        //

        public SecurityIdentifier AccountDomainSid 
        {
            get 
            { 
                if ( !_AccountDomainSidInitialized )
                { 
                    _AccountDomainSid = GetAccountDomainSid();
                    _AccountDomainSidInitialized = true;
                }
 
                return _AccountDomainSid;
            } 
        } 

        #endregion 

        #region Inherited properties and methods

        public override bool Equals( object o ) 
        {
            if ( o == null ) 
            { 
                return false;
            } 

            SecurityIdentifier sid = o as SecurityIdentifier;

            if ( sid == null ) 
            {
                return false; 
            } 

            return ( this == sid ); // invokes operator== 
        }

        public bool Equals( SecurityIdentifier sid )
        { 
            if ( sid == null )
            { 
                return false; 
            }
 
            return ( this == sid ); // invokes operator==
        }

        public override int GetHashCode() { 
            int hashCode = ((long)this.IdentifierAuthority).GetHashCode();
            for(int i = 0; i < SubAuthorityCount; i++) { 
                hashCode ^= this.GetSubAuthority(i); 
            }
            return hashCode; 
        }

        public override string ToString()
        { 
            if ( _SddlForm == null )
            { 
                StringBuilder result = new StringBuilder(); 

                // 
                // Typecasting of _IdentifierAuthority to a long below is important, since
                // otherwise you would see this: "S-1-NTAuthority-32-544"
                //
 
                result.AppendFormat( "S-1-{0}", ( long )_IdentifierAuthority );
 
                for ( int i = 0; i < SubAuthorityCount; i++ ) 
                {
                    result.AppendFormat( "-{0}", ( uint )( _SubAuthorities[i] )); 
                }

                _SddlForm = result.ToString();
            } 

            return _SddlForm; 
        } 
#if false
        public override string Scheme 
        {
            get { return "ms-sid"; }
        }
#endif 
        public override string Value
        { 
            get { return ToString().ToUpper(CultureInfo.InvariantCulture); } 
        }
 
        internal static bool IsValidTargetTypeStatic( Type targetType )
       {
            if ( targetType == typeof( NTAccount ))
            { 
                return true;
            } 
            else if ( targetType == typeof( SecurityIdentifier )) 
            {
                return true; 
            }
            else
            {
                return false; 
            }
        } 
 
        public override bool IsValidTargetType( Type targetType )
        { 
            return IsValidTargetTypeStatic( targetType );
        }

 
        internal SecurityIdentifier GetAccountDomainSid()
        { 
            SecurityIdentifier ResultSid; 
            int Error;
 
            Error = Win32.GetWindowsAccountDomainSid( this, out ResultSid );

            if ( Error == Win32Native.ERROR_INSUFFICIENT_BUFFER )
            { 
                throw new OutOfMemoryException();
            } 
            else if ( Error == Win32Native.ERROR_NON_ACCOUNT_SID ) 
            {
                ResultSid = null; 
            }
            else if ( Error != Win32Native.ERROR_SUCCESS )
            {
                BCLDebug.Assert( false, string.Format( CultureInfo.InvariantCulture, "Win32.GetWindowsAccountDomainSid returned unrecognized error {0}", Error) ); 
                throw new SystemException(Win32Native.GetMessage(Error));
            } 
            return ResultSid; 
        }
 
        public bool IsAccountSid() {

            if ( !_AccountDomainSidInitialized )
            { 
                    _AccountDomainSid = GetAccountDomainSid();
                    _AccountDomainSidInitialized = true; 
            } 

            if (_AccountDomainSid == null) { 
                return false;
            }

            return true; 
        }
 
        public override IdentityReference Translate( Type targetType ) 
        {
            if ( targetType == null ) 
            {
                throw new ArgumentNullException( "targetType" );
            }
 
            if ( targetType == typeof( SecurityIdentifier ))
            { 
                return this; // assumes SecurityIdentifier objects are immutable 
            }
            else if ( targetType == typeof( NTAccount )) 
            {
                IdentityReferenceCollection irSource = new IdentityReferenceCollection( 1 );
                irSource.Add( this );
                IdentityReferenceCollection irTarget; 

                irTarget = SecurityIdentifier.Translate( irSource, targetType, true ); 
 
                return irTarget[0];
            } 
            else
            {
                throw new ArgumentException( Environment.GetResourceString( "IdentityReference_MustBeIdentityReference" ), "targetType" );
            } 
        }
 
        #endregion 

        #region Operators 

        public static bool operator== ( SecurityIdentifier left, SecurityIdentifier right )
        {
            object l = left; 
            object r = right;
 
            if ( l == null && r == null ) 
            {
                return true; 
            }
            else if ( l == null || r == null )
            {
                return false; 
            }
            else 
            { 
                return ( left.CompareTo( right ) == 0 );
            } 
        }

        public static bool operator!= ( SecurityIdentifier left, SecurityIdentifier right )
        { 
            return !( left == right );
        } 
 
        #endregion
 
        #region IComparable implementation

        public int CompareTo( SecurityIdentifier sid )
        { 
            if ( sid == null )
            { 
                throw new ArgumentNullException( "sid" ); 
            }
 
            if ( this.IdentifierAuthority < sid.IdentifierAuthority )
            {
                return -1;
            } 

            if ( this.IdentifierAuthority > sid.IdentifierAuthority ) 
            { 
                return 1;
            } 

            if ( this.SubAuthorityCount < sid.SubAuthorityCount )
            {
                return -1; 
            }
 
            if ( this.SubAuthorityCount > sid.SubAuthorityCount ) 
            {
                return 1; 
            }

            for ( int i = 0; i < this.SubAuthorityCount; i++ )
            { 
                int diff = this.GetSubAuthority( i ) - sid.GetSubAuthority( i );
 
                if ( diff != 0 ) 
                {
                    return diff; 
                }
            }

            return 0; 
        }
 
        #endregion 

        #region Public Methods 

        internal int GetSubAuthority( int index )
        {
            return this._SubAuthorities[ index ]; 
        }
 
        // 
        // Determines whether this SID is a well known SID of the specified type
        // 
        // NOTE: although there is a P/Invoke call involved in the implementation of this method,
        //       there is no security risk involved, so no security demand is being made.
        //
 
        public bool IsWellKnown( WellKnownSidType type )
        { 
            return Win32.IsWellKnownSid( this, type ); 
        }
 
        public void GetBinaryForm( byte[] binaryForm, int offset )
        {
            _BinaryForm.CopyTo( binaryForm, offset );
        } 

        // 
        // NOTE: although there is a P/Invoke call involved in the implementation of this method, 
        //       there is no security risk involved, so no security demand is being made.
        // 

        public bool IsEqualDomainSid( SecurityIdentifier sid )
        {
            return Win32.IsEqualDomainSid( this, sid ); 
        }
 
        private static IdentityReferenceCollection TranslateToNTAccounts( IdentityReferenceCollection sourceSids, out bool someFailed ) 
        {
 
            //
            // Check if the lsa api is supported
            //
            if (!Win32.LsaApisSupported) { 
                throw new PlatformNotSupportedException( Environment.GetResourceString( "PlatformNotSupported_Win9x" ));
            } 
 
            IntPtr[] SidArrayPtr = new IntPtr[ sourceSids.Count ];
            GCHandle[] HandleArray = new GCHandle[ sourceSids.Count ]; 
            SafeLsaPolicyHandle LsaHandle = SafeLsaPolicyHandle.InvalidHandle;
            SafeLsaMemoryHandle ReferencedDomainsPtr = SafeLsaMemoryHandle.InvalidHandle;
            SafeLsaMemoryHandle NamesPtr = SafeLsaMemoryHandle.InvalidHandle;
            int i = 0; 

            if ( sourceSids == null ) 
            { 
                throw new ArgumentNullException( "sourceSids" );
            } 

            if ( sourceSids.Count == 0 )
            {
                throw new ArgumentException( Environment.GetResourceString( "Arg_EmptyCollection" ), "sourceSids" ); 
            }
 
            try 
            {
                // 
                // Pin all elements in the array of SIDs
                //

                foreach ( IdentityReference id in sourceSids ) 
                {
                    SecurityIdentifier sid = id as SecurityIdentifier; 
 
                    if ( sid == null )
                    { 
                        throw new ArgumentException( Environment.GetResourceString( "Argument_ImproperType" ), "sourceSids" );
                    }

                    HandleArray[i] = GCHandle.Alloc( sid.BinaryForm, GCHandleType.Pinned ); 
                    SidArrayPtr[i] = HandleArray[i].AddrOfPinnedObject();
                    i++; 
                } 

                // 
                // Open LSA policy (for lookup requires it)
                //

                LsaHandle = Win32.LsaOpenPolicy( null, PolicyRights.POLICY_LOOKUP_NAMES ); 

                // 
                // Perform the actual lookup 
                //
 
                someFailed = false;
                uint ReturnCode;
                ReturnCode = Win32Native.LsaLookupSids( LsaHandle, sourceSids.Count, SidArrayPtr, ref ReferencedDomainsPtr, ref NamesPtr );
 
                //
                // Make a decision regarding whether it makes sense to proceed 
                // based on the return code and the value of the forceSuccess argument 
                //
 
                if ( ReturnCode == Win32Native.STATUS_NO_MEMORY ||
                    ReturnCode == Win32Native.STATUS_INSUFFICIENT_RESOURCES )
                {
                    throw new OutOfMemoryException(); 
                }
 		  else  if ( ReturnCode == Win32Native.STATUS_ACCESS_DENIED ) 
                { 
                    throw new UnauthorizedAccessException();
                } 
                else if ( ReturnCode == Win32Native.STATUS_NONE_MAPPED ||
                    ReturnCode == Win32Native.STATUS_SOME_NOT_MAPPED )
                {
                    someFailed = true; 
                }
                else if ( ReturnCode != 0 ) 
                { 
                    int win32ErrorCode = Win32Native.LsaNtStatusToWinError(unchecked((int)ReturnCode));
 
                    BCLDebug.Assert( false, string.Format( CultureInfo.InvariantCulture, "Win32Native.LsaLookupSids returned {0}", win32ErrorCode));
                    throw new SystemException(Win32Native.GetMessage(win32ErrorCode));
                }
 
                //
                // Interpret the results and generate NTAccount objects 
                // 

                IdentityReferenceCollection Result = new IdentityReferenceCollection( sourceSids.Count ); 

                if ( ReturnCode == 0 || ReturnCode == Win32Native.STATUS_SOME_NOT_MAPPED )
                {
                    // 
                    // Interpret the results and generate NT Account objects
                    // 
 
                    Win32Native.LSA_REFERENCED_DOMAIN_LIST rdl = ( Win32Native.LSA_REFERENCED_DOMAIN_LIST )Marshal.PtrToStructure( ReferencedDomainsPtr.DangerousGetHandle(), typeof( Win32Native.LSA_REFERENCED_DOMAIN_LIST ));
                    string[] ReferencedDomains = new string[ rdl.Entries ]; 

                    for ( i = 0; i < rdl.Entries; i++ )
                    {
                        Win32Native.LSA_TRUST_INFORMATION ti = ( Win32Native.LSA_TRUST_INFORMATION )Marshal.PtrToStructure( new IntPtr(( long )rdl.Domains + i * Marshal.SizeOf( typeof( Win32Native.LSA_TRUST_INFORMATION ))), typeof( Win32Native.LSA_TRUST_INFORMATION )); 

                        ReferencedDomains[i] = Marshal.PtrToStringUni( ti.Name.Buffer, ti.Name.Length/2 ); 
                    } 

                    for ( i = 0; i < sourceSids.Count; i++ ) 
                    {
                        Win32Native.LSA_TRANSLATED_NAME Ltn;
                        SidNameUse Use;
                        string Account; 
                        string Domain;
 
                        Ltn = ( Win32Native.LSA_TRANSLATED_NAME )Marshal.PtrToStructure( new IntPtr(( long )NamesPtr.DangerousGetHandle() + i * Marshal.SizeOf( typeof( Win32Native.LSA_TRANSLATED_NAME ))), typeof( Win32Native.LSA_TRANSLATED_NAME )); 

                        Use = ( SidNameUse )Ltn.Use; 

                        switch ( Use )
                        {
                            case SidNameUse.User: 
                                goto case SidNameUse.WellKnownGroup;
 
                            case SidNameUse.Group: 
                                goto case SidNameUse.WellKnownGroup;
 
                            case SidNameUse.Alias:
                                goto case SidNameUse.WellKnownGroup;

                            case SidNameUse.Computer: 
                                goto case SidNameUse.WellKnownGroup;
 
                            case SidNameUse.WellKnownGroup: 

                                Account = Marshal.PtrToStringUni( Ltn.Name.Buffer, Ltn.Name.Length/2 ); 
                                Domain = ReferencedDomains[ Ltn.DomainIndex ];
                                Result.Add( new NTAccount( Domain, Account ));
                                break;
 
                            default:
 
                                someFailed = true; 
                                Result.Add( sourceSids[i] );
                                break; 

                        }
                    }
                } 
                else
                { 
                    for ( i = 0; i < sourceSids.Count; i++ ) 
                    {
                        Result.Add( sourceSids[i] ); 
                    }
                }

                return Result; 
            }
            finally 
            { 
                for ( i = 0; i < sourceSids.Count; i++ )
                { 
                    if ( HandleArray[i].IsAllocated )
                    {
                        HandleArray[i].Free();
                    } 
                }
 
                LsaHandle.Dispose(); 
                ReferencedDomainsPtr.Dispose();
                NamesPtr.Dispose(); 
            }
        }

        internal static IdentityReferenceCollection Translate( IdentityReferenceCollection sourceSids, Type targetType, bool forceSuccess) 
        {
            bool SomeFailed = false; 
            IdentityReferenceCollection Result; 

 
            Result = Translate( sourceSids, targetType, out SomeFailed );

            if (forceSuccess && SomeFailed) {
 
                IdentityReferenceCollection UnmappedIdentities = new IdentityReferenceCollection();
 
                foreach (IdentityReference id in Result) 
                {
                    if (id.GetType() != targetType) 
                    {
                        UnmappedIdentities.Add(id);
                    }
                } 

                throw new IdentityNotMappedException(Environment.GetResourceString("IdentityReference_IdentityNotMapped"), UnmappedIdentities); 
 
            }
 
            return Result;
        }

        internal static IdentityReferenceCollection Translate( IdentityReferenceCollection sourceSids, Type targetType, out bool someFailed ) 
        {
            if ( sourceSids == null ) 
            { 
                throw new ArgumentNullException( "sourceSids" );
            } 

            if ( targetType == typeof( NTAccount ))
            {
                return TranslateToNTAccounts( sourceSids, out someFailed ); 
            }
 
            throw new ArgumentException( Environment.GetResourceString( "IdentityReference_MustBeIdentityReference" ), "targetType" ); 
        }
 
        #endregion
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 

using Microsoft.Win32; 
using Microsoft.Win32.SafeHandles; 
using System;
using System.Security.Permissions; 
using System.Text;
using System.Runtime.InteropServices;
using System.Globalization;
 
namespace System.Security.Principal
{ 
    // 
    // Identifier authorities
    // 

    internal enum IdentifierAuthority : long
    {
        NullAuthority                            = 0, 
        WorldAuthority                           = 1,
        LocalAuthority                           = 2, 
        CreatorAuthority                         = 3, 
        NonUniqueAuthority                       = 4,
        NTAuthority                              = 5, 
        SiteServerAuthority                      = 6,
        InternetSiteAuthority                    = 7,
        ExchangeAuthority                        = 8,
        ResourceManagerAuthority                 = 9, 
    }
 
    // 
    // SID name usage
    // 

    internal enum SidNameUse
    {
        User                              = 1, 
        Group                             = 2,
        Domain                            = 3, 
        Alias                             = 4, 
        WellKnownGroup                    = 5,
        DeletedAccount                    = 6, 
        Invalid                           = 7,
        Unknown                           = 8,
        Computer                          = 9,
    } 

    // 
    // Well-known SID types 
    //
 
[System.Runtime.InteropServices.ComVisible(false)]
    public enum WellKnownSidType
    {
        NullSid                                  = 0, 
        WorldSid                                 = 1,
        LocalSid                                 = 2, 
        CreatorOwnerSid                          = 3, 
        CreatorGroupSid                          = 4,
        CreatorOwnerServerSid                    = 5, 
        CreatorGroupServerSid                    = 6,
        NTAuthoritySid                           = 7,
        DialupSid                                = 8,
        NetworkSid                               = 9, 
        BatchSid                                 = 10,
        InteractiveSid                           = 11, 
        ServiceSid                               = 12, 
        AnonymousSid                             = 13,
        ProxySid                                 = 14, 
        EnterpriseControllersSid                 = 15,
        SelfSid                                  = 16,
        AuthenticatedUserSid                     = 17,
        RestrictedCodeSid                        = 18, 
        TerminalServerSid                        = 19,
        RemoteLogonIdSid                         = 20, 
        LogonIdsSid                              = 21, 
        LocalSystemSid                           = 22,
        LocalServiceSid                          = 23, 
        NetworkServiceSid                        = 24,
        BuiltinDomainSid                         = 25,
        BuiltinAdministratorsSid                 = 26,
        BuiltinUsersSid                          = 27, 
        BuiltinGuestsSid                         = 28,
        BuiltinPowerUsersSid                     = 29, 
        BuiltinAccountOperatorsSid               = 30, 
        BuiltinSystemOperatorsSid                = 31,
        BuiltinPrintOperatorsSid                 = 32, 
        BuiltinBackupOperatorsSid                = 33,
        BuiltinReplicatorSid                     = 34,
        BuiltinPreWindows2000CompatibleAccessSid = 35,
        BuiltinRemoteDesktopUsersSid             = 36, 
        BuiltinNetworkConfigurationOperatorsSid  = 37,
        AccountAdministratorSid                  = 38, 
        AccountGuestSid                          = 39, 
        AccountKrbtgtSid                         = 40,
        AccountDomainAdminsSid                   = 41, 
        AccountDomainUsersSid                    = 42,
        AccountDomainGuestsSid                   = 43,
        AccountComputersSid                      = 44,
        AccountControllersSid                    = 45, 
        AccountCertAdminsSid                     = 46,
        AccountSchemaAdminsSid                   = 47, 
        AccountEnterpriseAdminsSid               = 48, 
        AccountPolicyAdminsSid                   = 49,
        AccountRasAndIasServersSid               = 50, 
        NtlmAuthenticationSid                    = 51,
        DigestAuthenticationSid                  = 52,
        SChannelAuthenticationSid                = 53,
        ThisOrganizationSid                      = 54, 
        OtherOrganizationSid                     = 55,
        BuiltinIncomingForestTrustBuildersSid    = 56, 
        BuiltinPerformanceMonitoringUsersSid     = 57, 
        BuiltinPerformanceLoggingUsersSid        = 58,
        BuiltinAuthorizationAccessSid            = 59, 
        WinBuiltinTerminalServerLicenseServersSid= 60,
        MaxDefined = WinBuiltinTerminalServerLicenseServersSid,
    }
 
    //
    // This class implements revision 1 SIDs 
    // NOTE: The SecurityIdentifier class is immutable and must remain this way 
    //
 
[System.Runtime.InteropServices.ComVisible(false)]
    public sealed class SecurityIdentifier : IdentityReference, IComparable
    {
        #region Public Constants 

        // 
        // Identifier authority must be at most six bytes long 
        //
 
        internal static readonly long MaxIdentifierAuthority = 0xFFFFFFFFFFFF;

        //
        // Maximum number of subauthorities in a SID 
        //
 
        internal static readonly byte MaxSubAuthorities = 15; 

        // 
        // Minimum length of a binary representation of a SID
        //

        public static readonly int MinBinaryLength = 1 + 1 + 6; // Revision (1) + subauth count (1) + identifier authority (6) 

        // 
        // Maximum length of a binary representation of a SID 
        //
 
        public static readonly int MaxBinaryLength = 1 + 1 + 6 + MaxSubAuthorities * 4; // 4 bytes for each subauth

        #endregion
 
        #region Private Members
 
        // 
        // Immutable properties of a SID
        // 

        private IdentifierAuthority _IdentifierAuthority;
        private int[] _SubAuthorities;
        private byte[] _BinaryForm; 
        private SecurityIdentifier _AccountDomainSid;
        bool _AccountDomainSidInitialized = false; 
 
        //
        // Computed attributes of a SID 
        //

        private string _SddlForm = null;
 
        #endregion
 
        #region Constructors 

        // 
        // Shared constructor logic
        // NOTE: subauthorities are really unsigned integers, but due to CLS
        //       lack of support for unsigned integers the caller must perform
        //       the typecast 
        //
 
        private void CreateFromParts( IdentifierAuthority identifierAuthority, int[] subAuthorities ) 
        {
            if ( subAuthorities == null ) 
            {
                throw new ArgumentNullException( "subAuthorities" );
            }
 

            // 
            // Check the number of subauthorities passed in 
            //
 
            if ( subAuthorities.Length > MaxSubAuthorities )
            {
                throw new ArgumentOutOfRangeException(
                    "subAuthorities.Length", 
                    subAuthorities.Length,
                    Environment.GetResourceString( "IdentityReference_InvalidNumberOfSubauthorities",  MaxSubAuthorities)); 
            } 

            // 
            // Identifier authority is atmost 6 bytes long
            //

            if ( identifierAuthority < 0  || 
                (long) identifierAuthority > MaxIdentifierAuthority )
            { 
                throw new ArgumentOutOfRangeException( 
                    "identifierAuthority",
                    identifierAuthority, 
                    Environment.GetResourceString( "IdentityReference_IdentifierAuthorityTooLarge" ));
            }

            // 
            // Create a local copy of the data passed in
            // 
 
            _IdentifierAuthority = identifierAuthority;
            _SubAuthorities = new int[ subAuthorities.Length ]; 
            subAuthorities.CopyTo( _SubAuthorities, 0 );

            //
            // Compute and store the binary form 
            //
            // typedef struct _SID { 
            //     UCHAR Revision; 
            //     UCHAR SubAuthorityCount;
            //     SID_IDENTIFIER_AUTHORITY IdentifierAuthority; 
            //     ULONG SubAuthority[ANYSIZE_ARRAY]
            // } SID, *PISID;
            //
 
            byte i;
            _BinaryForm = new byte[1 + 1 + 6 + 4 * this.SubAuthorityCount]; 
 
            //
            // First two bytes contain revision and subauthority count 
            //

            _BinaryForm[0] = Revision;
            _BinaryForm[1] = ( byte )this.SubAuthorityCount; 

            // 
            // Identifier authority takes up 6 bytes 
            //
 
            for ( i = 0; i < 6; i++ )
            {
                _BinaryForm[2+i] = ( byte )(((( ulong )this._IdentifierAuthority ) >> (( 5 - i ) * 8 )) & 0xFF ) ;
            } 

            // 
            // Subauthorities go last, preserving big-endian representation 
            //
 
            for ( i = 0; i < this.SubAuthorityCount; i++ )
            {
                byte shift;
                for ( shift = 0; shift < 4; shift += 1 ) 
                {
                    _BinaryForm[8 + 4*i + shift] = ( byte )((( ulong )_SubAuthorities[i] ) >> ( shift * 8 )); 
                } 
            }
        } 

        private void CreateFromBinaryForm( byte[] binaryForm, int offset )
        {
            IdentifierAuthority Authority; 
            int[] SubAuthorities;
 
            // 
            // Give us something to work with
            // 

            if ( binaryForm == null )
            {
                throw new ArgumentNullException( "binaryForm" ); 
            }
 
            // 
            // Negative offsets are not allowed
            // 

            if ( offset < 0 )
            {
                throw new ArgumentOutOfRangeException( 
                    "offset",
                    offset, 
                    Environment.GetResourceString( "ArgumentOutOfRange_NeedNonNegNum" )); 
            }
 
            //
            // At least a minimum-size SID should fit in the buffer
            //
 
            if ( binaryForm.Length - offset < SecurityIdentifier.MinBinaryLength )
            { 
                throw new ArgumentOutOfRangeException( 
                    "binaryForm",
                    Environment.GetResourceString( "ArgumentOutOfRange_ArrayTooSmall" )); 
            }

            //
            // Extract the elements of a SID 
            //
 
            if ( binaryForm[offset] != Revision ) 
            {
                // 
                // Revision is incorrect
                //

                throw new ArgumentException( 
                    Environment.GetResourceString( "IdentityReference_InvalidSidRevision" ),
                    "binaryForm" ); 
            } 

            // 
            // Insist on the correct number of subauthorities
            //

            if ( binaryForm[offset + 1] > MaxSubAuthorities ) 
            {
                throw new ArgumentException( 
                    Environment.GetResourceString( "IdentityReference_InvalidNumberOfSubauthorities", MaxSubAuthorities ), 
                    "binaryForm" );
            } 

            //
            // Make sure the buffer is big enough
            // 

            int Length = 1 + 1 + 6 + 4 * binaryForm[offset + 1]; 
 
            if ( binaryForm.Length - offset < Length )
            { 
                throw new ArgumentException(
                    Environment.GetResourceString( "ArgumentOutOfRange_ArrayTooSmall" ),
                    "binaryForm" );
            } 

            Authority = 
                ( IdentifierAuthority )( 
                ((( long )binaryForm[offset + 2]) << 40 ) +
                ((( long )binaryForm[offset + 3]) << 32 ) + 
                ((( long )binaryForm[offset + 4]) << 24 ) +
                ((( long )binaryForm[offset + 5]) << 16 ) +
                ((( long )binaryForm[offset + 6]) << 8 ) +
                ((( long )binaryForm[offset + 7]) )); 

            SubAuthorities = new int[binaryForm[offset + 1]]; 
 
            //
            // Subauthorities are represented in big-endian format 
            //

            for ( byte i = 0; i < binaryForm[offset + 1]; i++ )
            { 
                SubAuthorities[i] =
                    ( int )( 
                    ((( uint )binaryForm[offset + 8 + 4*i + 0]) << 0 ) + 
                    ((( uint )binaryForm[offset + 8 + 4*i + 1]) << 8 ) +
                    ((( uint )binaryForm[offset + 8 + 4*i + 2]) << 16 ) + 
                    ((( uint )binaryForm[offset + 8 + 4*i + 3]) << 24 ));
            }

            CreateFromParts( Authority, SubAuthorities ); 

            return; 
 
        }
 
        //
        // Constructs a SecurityIdentifier object from its string representation
        // Returns 'null' if string passed in is not a valid SID
        // NOTE: although there is a P/Invoke call involved in the implementation of this method, 
        //       there is no security risk involved, so no security demand is being made.
        // 
 
        public SecurityIdentifier( string sddlForm )
        { 
            byte[] resultSid;

            //
            // Give us something to work with 
            //
 
            if ( sddlForm == null ) 
            {
                throw new ArgumentNullException( "sddlForm" ); 
            }

            //
            // Call into the underlying O/S conversion routine 
            //
 
            int Error = Win32.CreateSidFromString( sddlForm, out resultSid ); 

            if ( Error == Win32Native.ERROR_INVALID_SID ) 
            {
                throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidValue" ), "sddlForm" );
            }
            else if ( Error == Win32Native.ERROR_NOT_ENOUGH_MEMORY ) 
            {
            	  throw new OutOfMemoryException(); 
            } 
            else if ( Error != Win32Native.ERROR_SUCCESS )
            { 
                BCLDebug.Assert( false, string.Format( CultureInfo.InvariantCulture, "Win32.CreateSidFromString returned unrecognized error {0}", Error ));
                throw new SystemException(Win32Native.GetMessage(Error));
            }
 
            CreateFromBinaryForm( resultSid, 0 );
        } 
 
        //
        // Constructs a SecurityIdentifier object from its binary representation 
        //

        public SecurityIdentifier( byte[] binaryForm, int offset )
        { 
            CreateFromBinaryForm( binaryForm, offset );
        } 
 
        //
        // Constructs a SecurityIdentifier object from an IntPtr 
        //
        [SecurityPermission(SecurityAction.Demand, UnmanagedCode=true)]
        public SecurityIdentifier( IntPtr binaryForm )
            : this( binaryForm, true ) 
        {
        } 
 
        internal SecurityIdentifier( IntPtr binaryForm, bool noDemand )
            : this( Win32.ConvertIntPtrSidToByteArraySid( binaryForm ), 0 ) 
        {
        }

        // 
        // Constructs a well-known SID
        // The 'domainSid' parameter is optional and only used 
        // by the well-known types that require it 
        // NOTE: although there is a P/Invoke call involved in the implementation of this constructor,
        //       there is no security risk involved, so no security demand is being made. 
        //

        public SecurityIdentifier( WellKnownSidType sidType, SecurityIdentifier domainSid )
        { 
            byte[] resultSid;
            int Error; 
 
            //
            // Check if well known sids are supported on this platform 
            //
            if (!Win32.WellKnownSidApisSupported) {
                throw new PlatformNotSupportedException( Environment.GetResourceString( "PlatformNotSupported_RequiresW2kSP3" ));
            } 

            // 
            // sidType must not be equal to LogonIdsSid 
            //
 
            if (sidType == WellKnownSidType.LogonIdsSid)
            {
                throw new ArgumentException( Environment.GetResourceString( "IdentityReference_CannotCreateLogonIdsSid" ), "sidType" );
            } 

            // 
            // sidType should not exceed the max defined value 
            //
 
            if ((sidType < WellKnownSidType.NullSid) || (sidType > WellKnownSidType.MaxDefined))
            {
                throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidValue" ), "sidType" );
            } 

            // 
            // for sidType between 38 to 50, the domainSid parameter must be specified 
            //
 
            if ((sidType >= WellKnownSidType.AccountAdministratorSid) && (sidType <= WellKnownSidType.AccountRasAndIasServersSid))
            {
                if (domainSid == null) {
                    throw new ArgumentNullException( "domainSid", Environment.GetResourceString( "IdentityReference_DomainSidRequired", sidType) ); 
                }
 
                // 
                // verify that the domain sid is a valid windows domain sid
                // to do that we call GetAccountDomainSid and the return value should be the same as the domainSid 
                //

                SecurityIdentifier resultDomainSid;
                int ErrorCode; 

                ErrorCode = Win32.GetWindowsAccountDomainSid( domainSid, out resultDomainSid ); 
 
                if ( ErrorCode == Win32Native.ERROR_INSUFFICIENT_BUFFER ) {
                    throw new OutOfMemoryException(); 
                }
                else if ( ErrorCode == Win32Native.ERROR_NON_ACCOUNT_SID )
                {
                    // this means that the domain sid is not valid 
                    throw new ArgumentException( Environment.GetResourceString( "IdentityReference_NotAWindowsDomain" ), "domainSid" );
                } 
                else if ( ErrorCode != Win32Native.ERROR_SUCCESS ) 
                {
                    BCLDebug.Assert( false, string.Format( CultureInfo.InvariantCulture, "Win32.GetWindowsAccountDomainSid returned unrecognized error {0}", ErrorCode) ); 
                    throw new SystemException(Win32Native.GetMessage(ErrorCode));
                }

                // 
                // if domainSid is passed in as S-1-5-21-3-4-5-6,  the above api will return S-1-5-21-3-4-5 as the domainSid
                // Since these do not match S-1-5-21-3-4-5-6 is not a valid domainSid (wrong number of subauthorities) 
                // 
                if (resultDomainSid != domainSid) {
                    throw new ArgumentException( Environment.GetResourceString( "IdentityReference_NotAWindowsDomain" ), "domainSid" ); 
                }

            }
 

            Error = Win32.CreateWellKnownSid( sidType, domainSid, out resultSid ); 
 
            if ( Error == Win32Native.ERROR_INVALID_PARAMETER )
            { 
                throw new ArgumentException( Win32Native.GetMessage(Error), "sidType/domainSid" );
            }
            else if ( Error != Win32Native.ERROR_SUCCESS )
            { 
                BCLDebug.Assert( false, string.Format( CultureInfo.InvariantCulture, "Win32.CreateWellKnownSid returned unrecognized error {0}", Error ));
                throw new SystemException( Win32Native.GetMessage( Error )); 
            } 

            CreateFromBinaryForm( resultSid, 0 ); 
        }

        internal SecurityIdentifier( SecurityIdentifier domainSid, uint rid )
        { 
            int i;
            int[] SubAuthorities = new int[ domainSid.SubAuthorityCount + 1 ]; 
 
            for ( i = 0; i < domainSid.SubAuthorityCount; i++ )
            { 
                SubAuthorities[i] = domainSid.GetSubAuthority( i );
            }

            SubAuthorities[i] = ( int )rid; 

            CreateFromParts( domainSid.IdentifierAuthority, SubAuthorities ); 
        } 

        internal SecurityIdentifier( IdentifierAuthority identifierAuthority, int[] subAuthorities ) 
        {
            CreateFromParts( identifierAuthority, subAuthorities );
        }
 
        #endregion
 
        #region Static Properties 

        // 
        // Revision is always '1'
        //

        internal static byte Revision 
        {
            get { return 1; } 
        } 

        #endregion 

        #region Non-static Properties

        // 
        // This is for internal consumption only, hence it is marked 'internal'
        // Making this call public would require a deep copy of the data to 
        // prevent the caller from messing with the internal representation. 
        //
 
        internal byte[] BinaryForm
        {
            get { return _BinaryForm; }
        } 

        internal IdentifierAuthority IdentifierAuthority 
        { 
            get { return _IdentifierAuthority; }
        } 

        internal int SubAuthorityCount
        {
            get { return _SubAuthorities.Length; } 
        }
 
        public int BinaryLength 
        {
            get 
            {
                return _BinaryForm.Length;
            }
        } 

        // 
        // Returns the domain portion of a SID or null if the specified 
        // SID is not an account SID
        // NOTE: although there is a P/Invoke call involved in the implementation of this method, 
        //       there is no security risk involved, so no security demand is being made.
        //

        public SecurityIdentifier AccountDomainSid 
        {
            get 
            { 
                if ( !_AccountDomainSidInitialized )
                { 
                    _AccountDomainSid = GetAccountDomainSid();
                    _AccountDomainSidInitialized = true;
                }
 
                return _AccountDomainSid;
            } 
        } 

        #endregion 

        #region Inherited properties and methods

        public override bool Equals( object o ) 
        {
            if ( o == null ) 
            { 
                return false;
            } 

            SecurityIdentifier sid = o as SecurityIdentifier;

            if ( sid == null ) 
            {
                return false; 
            } 

            return ( this == sid ); // invokes operator== 
        }

        public bool Equals( SecurityIdentifier sid )
        { 
            if ( sid == null )
            { 
                return false; 
            }
 
            return ( this == sid ); // invokes operator==
        }

        public override int GetHashCode() { 
            int hashCode = ((long)this.IdentifierAuthority).GetHashCode();
            for(int i = 0; i < SubAuthorityCount; i++) { 
                hashCode ^= this.GetSubAuthority(i); 
            }
            return hashCode; 
        }

        public override string ToString()
        { 
            if ( _SddlForm == null )
            { 
                StringBuilder result = new StringBuilder(); 

                // 
                // Typecasting of _IdentifierAuthority to a long below is important, since
                // otherwise you would see this: "S-1-NTAuthority-32-544"
                //
 
                result.AppendFormat( "S-1-{0}", ( long )_IdentifierAuthority );
 
                for ( int i = 0; i < SubAuthorityCount; i++ ) 
                {
                    result.AppendFormat( "-{0}", ( uint )( _SubAuthorities[i] )); 
                }

                _SddlForm = result.ToString();
            } 

            return _SddlForm; 
        } 
#if false
        public override string Scheme 
        {
            get { return "ms-sid"; }
        }
#endif 
        public override string Value
        { 
            get { return ToString().ToUpper(CultureInfo.InvariantCulture); } 
        }
 
        internal static bool IsValidTargetTypeStatic( Type targetType )
       {
            if ( targetType == typeof( NTAccount ))
            { 
                return true;
            } 
            else if ( targetType == typeof( SecurityIdentifier )) 
            {
                return true; 
            }
            else
            {
                return false; 
            }
        } 
 
        public override bool IsValidTargetType( Type targetType )
        { 
            return IsValidTargetTypeStatic( targetType );
        }

 
        internal SecurityIdentifier GetAccountDomainSid()
        { 
            SecurityIdentifier ResultSid; 
            int Error;
 
            Error = Win32.GetWindowsAccountDomainSid( this, out ResultSid );

            if ( Error == Win32Native.ERROR_INSUFFICIENT_BUFFER )
            { 
                throw new OutOfMemoryException();
            } 
            else if ( Error == Win32Native.ERROR_NON_ACCOUNT_SID ) 
            {
                ResultSid = null; 
            }
            else if ( Error != Win32Native.ERROR_SUCCESS )
            {
                BCLDebug.Assert( false, string.Format( CultureInfo.InvariantCulture, "Win32.GetWindowsAccountDomainSid returned unrecognized error {0}", Error) ); 
                throw new SystemException(Win32Native.GetMessage(Error));
            } 
            return ResultSid; 
        }
 
        public bool IsAccountSid() {

            if ( !_AccountDomainSidInitialized )
            { 
                    _AccountDomainSid = GetAccountDomainSid();
                    _AccountDomainSidInitialized = true; 
            } 

            if (_AccountDomainSid == null) { 
                return false;
            }

            return true; 
        }
 
        public override IdentityReference Translate( Type targetType ) 
        {
            if ( targetType == null ) 
            {
                throw new ArgumentNullException( "targetType" );
            }
 
            if ( targetType == typeof( SecurityIdentifier ))
            { 
                return this; // assumes SecurityIdentifier objects are immutable 
            }
            else if ( targetType == typeof( NTAccount )) 
            {
                IdentityReferenceCollection irSource = new IdentityReferenceCollection( 1 );
                irSource.Add( this );
                IdentityReferenceCollection irTarget; 

                irTarget = SecurityIdentifier.Translate( irSource, targetType, true ); 
 
                return irTarget[0];
            } 
            else
            {
                throw new ArgumentException( Environment.GetResourceString( "IdentityReference_MustBeIdentityReference" ), "targetType" );
            } 
        }
 
        #endregion 

        #region Operators 

        public static bool operator== ( SecurityIdentifier left, SecurityIdentifier right )
        {
            object l = left; 
            object r = right;
 
            if ( l == null && r == null ) 
            {
                return true; 
            }
            else if ( l == null || r == null )
            {
                return false; 
            }
            else 
            { 
                return ( left.CompareTo( right ) == 0 );
            } 
        }

        public static bool operator!= ( SecurityIdentifier left, SecurityIdentifier right )
        { 
            return !( left == right );
        } 
 
        #endregion
 
        #region IComparable implementation

        public int CompareTo( SecurityIdentifier sid )
        { 
            if ( sid == null )
            { 
                throw new ArgumentNullException( "sid" ); 
            }
 
            if ( this.IdentifierAuthority < sid.IdentifierAuthority )
            {
                return -1;
            } 

            if ( this.IdentifierAuthority > sid.IdentifierAuthority ) 
            { 
                return 1;
            } 

            if ( this.SubAuthorityCount < sid.SubAuthorityCount )
            {
                return -1; 
            }
 
            if ( this.SubAuthorityCount > sid.SubAuthorityCount ) 
            {
                return 1; 
            }

            for ( int i = 0; i < this.SubAuthorityCount; i++ )
            { 
                int diff = this.GetSubAuthority( i ) - sid.GetSubAuthority( i );
 
                if ( diff != 0 ) 
                {
                    return diff; 
                }
            }

            return 0; 
        }
 
        #endregion 

        #region Public Methods 

        internal int GetSubAuthority( int index )
        {
            return this._SubAuthorities[ index ]; 
        }
 
        // 
        // Determines whether this SID is a well known SID of the specified type
        // 
        // NOTE: although there is a P/Invoke call involved in the implementation of this method,
        //       there is no security risk involved, so no security demand is being made.
        //
 
        public bool IsWellKnown( WellKnownSidType type )
        { 
            return Win32.IsWellKnownSid( this, type ); 
        }
 
        public void GetBinaryForm( byte[] binaryForm, int offset )
        {
            _BinaryForm.CopyTo( binaryForm, offset );
        } 

        // 
        // NOTE: although there is a P/Invoke call involved in the implementation of this method, 
        //       there is no security risk involved, so no security demand is being made.
        // 

        public bool IsEqualDomainSid( SecurityIdentifier sid )
        {
            return Win32.IsEqualDomainSid( this, sid ); 
        }
 
        private static IdentityReferenceCollection TranslateToNTAccounts( IdentityReferenceCollection sourceSids, out bool someFailed ) 
        {
 
            //
            // Check if the lsa api is supported
            //
            if (!Win32.LsaApisSupported) { 
                throw new PlatformNotSupportedException( Environment.GetResourceString( "PlatformNotSupported_Win9x" ));
            } 
 
            IntPtr[] SidArrayPtr = new IntPtr[ sourceSids.Count ];
            GCHandle[] HandleArray = new GCHandle[ sourceSids.Count ]; 
            SafeLsaPolicyHandle LsaHandle = SafeLsaPolicyHandle.InvalidHandle;
            SafeLsaMemoryHandle ReferencedDomainsPtr = SafeLsaMemoryHandle.InvalidHandle;
            SafeLsaMemoryHandle NamesPtr = SafeLsaMemoryHandle.InvalidHandle;
            int i = 0; 

            if ( sourceSids == null ) 
            { 
                throw new ArgumentNullException( "sourceSids" );
            } 

            if ( sourceSids.Count == 0 )
            {
                throw new ArgumentException( Environment.GetResourceString( "Arg_EmptyCollection" ), "sourceSids" ); 
            }
 
            try 
            {
                // 
                // Pin all elements in the array of SIDs
                //

                foreach ( IdentityReference id in sourceSids ) 
                {
                    SecurityIdentifier sid = id as SecurityIdentifier; 
 
                    if ( sid == null )
                    { 
                        throw new ArgumentException( Environment.GetResourceString( "Argument_ImproperType" ), "sourceSids" );
                    }

                    HandleArray[i] = GCHandle.Alloc( sid.BinaryForm, GCHandleType.Pinned ); 
                    SidArrayPtr[i] = HandleArray[i].AddrOfPinnedObject();
                    i++; 
                } 

                // 
                // Open LSA policy (for lookup requires it)
                //

                LsaHandle = Win32.LsaOpenPolicy( null, PolicyRights.POLICY_LOOKUP_NAMES ); 

                // 
                // Perform the actual lookup 
                //
 
                someFailed = false;
                uint ReturnCode;
                ReturnCode = Win32Native.LsaLookupSids( LsaHandle, sourceSids.Count, SidArrayPtr, ref ReferencedDomainsPtr, ref NamesPtr );
 
                //
                // Make a decision regarding whether it makes sense to proceed 
                // based on the return code and the value of the forceSuccess argument 
                //
 
                if ( ReturnCode == Win32Native.STATUS_NO_MEMORY ||
                    ReturnCode == Win32Native.STATUS_INSUFFICIENT_RESOURCES )
                {
                    throw new OutOfMemoryException(); 
                }
 		  else  if ( ReturnCode == Win32Native.STATUS_ACCESS_DENIED ) 
                { 
                    throw new UnauthorizedAccessException();
                } 
                else if ( ReturnCode == Win32Native.STATUS_NONE_MAPPED ||
                    ReturnCode == Win32Native.STATUS_SOME_NOT_MAPPED )
                {
                    someFailed = true; 
                }
                else if ( ReturnCode != 0 ) 
                { 
                    int win32ErrorCode = Win32Native.LsaNtStatusToWinError(unchecked((int)ReturnCode));
 
                    BCLDebug.Assert( false, string.Format( CultureInfo.InvariantCulture, "Win32Native.LsaLookupSids returned {0}", win32ErrorCode));
                    throw new SystemException(Win32Native.GetMessage(win32ErrorCode));
                }
 
                //
                // Interpret the results and generate NTAccount objects 
                // 

                IdentityReferenceCollection Result = new IdentityReferenceCollection( sourceSids.Count ); 

                if ( ReturnCode == 0 || ReturnCode == Win32Native.STATUS_SOME_NOT_MAPPED )
                {
                    // 
                    // Interpret the results and generate NT Account objects
                    // 
 
                    Win32Native.LSA_REFERENCED_DOMAIN_LIST rdl = ( Win32Native.LSA_REFERENCED_DOMAIN_LIST )Marshal.PtrToStructure( ReferencedDomainsPtr.DangerousGetHandle(), typeof( Win32Native.LSA_REFERENCED_DOMAIN_LIST ));
                    string[] ReferencedDomains = new string[ rdl.Entries ]; 

                    for ( i = 0; i < rdl.Entries; i++ )
                    {
                        Win32Native.LSA_TRUST_INFORMATION ti = ( Win32Native.LSA_TRUST_INFORMATION )Marshal.PtrToStructure( new IntPtr(( long )rdl.Domains + i * Marshal.SizeOf( typeof( Win32Native.LSA_TRUST_INFORMATION ))), typeof( Win32Native.LSA_TRUST_INFORMATION )); 

                        ReferencedDomains[i] = Marshal.PtrToStringUni( ti.Name.Buffer, ti.Name.Length/2 ); 
                    } 

                    for ( i = 0; i < sourceSids.Count; i++ ) 
                    {
                        Win32Native.LSA_TRANSLATED_NAME Ltn;
                        SidNameUse Use;
                        string Account; 
                        string Domain;
 
                        Ltn = ( Win32Native.LSA_TRANSLATED_NAME )Marshal.PtrToStructure( new IntPtr(( long )NamesPtr.DangerousGetHandle() + i * Marshal.SizeOf( typeof( Win32Native.LSA_TRANSLATED_NAME ))), typeof( Win32Native.LSA_TRANSLATED_NAME )); 

                        Use = ( SidNameUse )Ltn.Use; 

                        switch ( Use )
                        {
                            case SidNameUse.User: 
                                goto case SidNameUse.WellKnownGroup;
 
                            case SidNameUse.Group: 
                                goto case SidNameUse.WellKnownGroup;
 
                            case SidNameUse.Alias:
                                goto case SidNameUse.WellKnownGroup;

                            case SidNameUse.Computer: 
                                goto case SidNameUse.WellKnownGroup;
 
                            case SidNameUse.WellKnownGroup: 

                                Account = Marshal.PtrToStringUni( Ltn.Name.Buffer, Ltn.Name.Length/2 ); 
                                Domain = ReferencedDomains[ Ltn.DomainIndex ];
                                Result.Add( new NTAccount( Domain, Account ));
                                break;
 
                            default:
 
                                someFailed = true; 
                                Result.Add( sourceSids[i] );
                                break; 

                        }
                    }
                } 
                else
                { 
                    for ( i = 0; i < sourceSids.Count; i++ ) 
                    {
                        Result.Add( sourceSids[i] ); 
                    }
                }

                return Result; 
            }
            finally 
            { 
                for ( i = 0; i < sourceSids.Count; i++ )
                { 
                    if ( HandleArray[i].IsAllocated )
                    {
                        HandleArray[i].Free();
                    } 
                }
 
                LsaHandle.Dispose(); 
                ReferencedDomainsPtr.Dispose();
                NamesPtr.Dispose(); 
            }
        }

        internal static IdentityReferenceCollection Translate( IdentityReferenceCollection sourceSids, Type targetType, bool forceSuccess) 
        {
            bool SomeFailed = false; 
            IdentityReferenceCollection Result; 

 
            Result = Translate( sourceSids, targetType, out SomeFailed );

            if (forceSuccess && SomeFailed) {
 
                IdentityReferenceCollection UnmappedIdentities = new IdentityReferenceCollection();
 
                foreach (IdentityReference id in Result) 
                {
                    if (id.GetType() != targetType) 
                    {
                        UnmappedIdentities.Add(id);
                    }
                } 

                throw new IdentityNotMappedException(Environment.GetResourceString("IdentityReference_IdentityNotMapped"), UnmappedIdentities); 
 
            }
 
            return Result;
        }

        internal static IdentityReferenceCollection Translate( IdentityReferenceCollection sourceSids, Type targetType, out bool someFailed ) 
        {
            if ( sourceSids == null ) 
            { 
                throw new ArgumentNullException( "sourceSids" );
            } 

            if ( targetType == typeof( NTAccount ))
            {
                return TranslateToNTAccounts( sourceSids, out someFailed ); 
            }
 
            throw new ArgumentException( Environment.GetResourceString( "IdentityReference_MustBeIdentityReference" ), "targetType" ); 
        }
 
        #endregion
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK