File: System\Messaging\AccessControlList.cs
Project: ndp\cdf\src\NetFx20\System.Messaging\System.Messaging.csproj (System.Messaging)
using System;
using System.Security.Permissions;
using System.Security;    
using System.Collections;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Text;
using System.Messaging.Interop;
 
namespace System.Messaging {
   
    /// <include file='doc\AccessControlList.uex' path='docs/doc[@for="AccessControlList"]/*' />
    /// <devdoc>
    ///    <para>[To be supplied.]</para>
    /// </devdoc> 
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1039:ListsAreStronglyTyped")]
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
    public class AccessControlList : CollectionBase {
    
        internal static readonly int UnknownEnvironment = 0;
        internal static readonly int W2kEnvironment = 1;
        internal static readonly int NtEnvironment = 2;
        internal static readonly int NonNtEnvironment = 3;
 
        // Double-checked locking pattern requires volatile for read/write synchronization
        private static volatile int environment = UnknownEnvironment;    
 
        private static object staticLock = new object();
            
        /// <include file='doc\AccessControlList.uex' path='docs/doc[@for="AccessControlList.AccessControlList"]/*' />
        public AccessControlList() {            
        }
        
        internal static int CurrentEnvironment {
            get {
                if (environment == UnknownEnvironment) { 
                    lock (AccessControlList.staticLock) {
                        if (environment == UnknownEnvironment) {
                            //SECREVIEW: Microsoft- need to assert Environment permissions here
                            //                        the environment check is not exposed as a public 
                            //                        method                        
                            EnvironmentPermission environmentPermission = new EnvironmentPermission(PermissionState.Unrestricted);                        
                            environmentPermission.Assert();                        
                            try {
                                if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
                                    if (Environment.OSVersion.Version.Major >= 5)
                                        environment = W2kEnvironment; 
                                    else
                                        environment = NtEnvironment; 
                                }                                
                                else                    
                                    environment = NonNtEnvironment;
                            }
                            finally {  
                                 EnvironmentPermission.RevertAssert();                             
                            }                                                    
                        }                
                    }
                }
            
                return environment;                        
            }                
        }               
    
        /// <include file='doc\AccessControlList.uex' path='docs/doc[@for="AccessControlList.Add"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public int Add(AccessControlEntry entry) {
            return List.Add(entry);
        }
   
        /// <include file='doc\AccessControlList.uex' path='docs/doc[@for="AccessControlList.Insert"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public void Insert(int index, AccessControlEntry entry) {
            List.Insert(index, entry);
        }
    
        /// <include file='doc\AccessControlList.uex' path='docs/doc[@for="AccessControlList.IndexOf"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public int IndexOf(AccessControlEntry entry) {
            return List.IndexOf(entry);
        }
    
        internal static void CheckEnvironment() {            
            if (CurrentEnvironment == NonNtEnvironment)
                throw new PlatformNotSupportedException(Res.GetString(Res.WinNTRequired));
        }
                                    
        /// <include file='doc\AccessControlList.uex' path='docs/doc[@for="AccessControlList.Contains"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public bool Contains(AccessControlEntry entry) {
            return List.Contains(entry);
        }
                                        
        /// <include file='doc\AccessControlList.uex' path='docs/doc[@for="AccessControlList.Remove"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public void Remove(AccessControlEntry entry) {
            List.Remove(entry);
        }
    
        /// <include file='doc\AccessControlList.uex' path='docs/doc[@for="AccessControlList.CopyTo"]/*' />
        /// <devdoc>
        ///    <para>[To be supplied.]</para>
        /// </devdoc>
        public void CopyTo(AccessControlEntry[] array, int index) {
            List.CopyTo(array, index);
        }
 
        internal IntPtr MakeAcl(IntPtr oldAcl) {
            CheckEnvironment();
            
            int ACECount = List.Count;
            IntPtr newAcl;
    
            NativeMethods.ExplicitAccess[] entries = new NativeMethods.ExplicitAccess[ACECount];
            
            GCHandle mem = GCHandle.Alloc(entries, GCHandleType.Pinned);
            try {
                for (int i = 0; i < ACECount; i++) {
                    int sidSize = 0;
                    int sidtype;
                    int domainSize = 0;
                    
                    AccessControlEntry ace = (AccessControlEntry)List[i];
            
                    if (ace.Trustee == null)
                        throw new InvalidOperationException(Res.GetString(Res.InvalidTrustee));
                    
                    string name = ace.Trustee.Name;
                    if (name == null) 
                        throw new InvalidOperationException(Res.GetString(Res.InvalidTrusteeName));
                    
                    if ((ace.Trustee.TrusteeType == TrusteeType.Computer) && !name.EndsWith("$"))
                        name += "$";
 
                    if (!UnsafeNativeMethods.LookupAccountName(ace.Trustee.SystemName, name, (IntPtr)0, ref sidSize, null, ref domainSize, out sidtype)) {
                        int errval = Marshal.GetLastWin32Error();
                        if (errval != 122)
                            throw new InvalidOperationException(Res.GetString(Res.CouldntResolve, ace.Trustee.Name, errval));
                    }
        
                    entries[i].data = (IntPtr)Marshal.AllocHGlobal(sidSize);
        
                    StringBuilder domainName = new StringBuilder(domainSize);                
                    if (!UnsafeNativeMethods.LookupAccountName(ace.Trustee.SystemName, name, entries[i].data, ref sidSize, domainName, ref domainSize, out sidtype))
                        throw new InvalidOperationException(Res.GetString(Res.CouldntResolveName, ace.Trustee.Name));
    
                    entries[i].grfAccessPermissions     = ace.accessFlags;
                    entries[i].grfAccessMode            = (int)ace.EntryType;
                    entries[i].grfInheritance           = 0;
                    entries[i].pMultipleTrustees        = (IntPtr)0;
                    entries[i].MultipleTrusteeOperation = NativeMethods.NO_MULTIPLE_TRUSTEE;
                    entries[i].TrusteeForm              = NativeMethods.TRUSTEE_IS_SID;
                    entries[i].TrusteeType              = (int)ace.Trustee.TrusteeType;
                }
    
                int err = SafeNativeMethods.SetEntriesInAclW(ACECount, (IntPtr)mem.AddrOfPinnedObject(), oldAcl, out newAcl);
    
                if (err != NativeMethods.ERROR_SUCCESS)
                    throw new Win32Exception(err);
            } 
            finally {
                mem.Free();
            
                for (int i = 0; i < ACECount; i++)
                    if (entries[i].data != (IntPtr)0)
                        Marshal.FreeHGlobal(entries[i].data);
                    
            }
    
    
            return newAcl;
        }
    
        internal static void FreeAcl(IntPtr acl) {
            SafeNativeMethods.LocalFree(acl);
        }
    }
}