File: MMCUI\ACLWrapper.cs
Project: ndp\cdf\src\WCF\Tools\WsatConfig\WsatUI.csproj (WsatUI)
//------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------------------------
 
namespace Microsoft.Tools.ServiceModel.WsatConfig
{
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;
    using System.Collections;
    using System.Security.AccessControl;
 
    // class used for poping up the ACL Window
    static class ACLWrapper
    {
        // wrapper for actual call to Win32 function that pops up the ACL window
        internal static bool EditACLSecurity(
            ISecurityInformationManaged model,
            IntPtr hwndOwner)
        {
            // create a new instance of a ISecurityInformation object
            ISecurityInformation psi = new SecurityInfoCCW(model);
            // pop-up the ACL window for the ISecurityInformation object created
#pragma warning suppress 56523
            int result = SafeNativeMethods.EditSecurity(hwndOwner, psi);
            return result == 0 ? false : true;
        }
    }
 
    // needed only for the PropertySheetPageCallback function
    // no actual use in this project
    enum PageType
    {
        SI_PAGE_PERM = 0,
        SI_PAGE_ADVPERM,
        SI_PAGE_AUDIT,
        SI_PAGE_OWNER
    };
 
    // Flags that are used in conjunction with the ObjectInformation
    enum ObjectInfoFlags : int
    {
        EditPerms = 0x00000000,
        EditOwner = 0x00000001,
        EditAudit = 0x00000002,
        EditAll = 0x00000003,
        Container = 0x00000004,
        ReadOnly = 0x00000008,
        Advanced = 0x00000010,
        Reset = 0x00000020,
        OwnerReadOnly = 0x00000040,
        EditProperties = 0x00000080,
        OwnerRecurse = 0x00000100,
        NoAclProtect = 0x00000200,
        NoTreeApply = 0x00000400,
        PageTitle = 0x00000800,
        ServerIsDC = 0x00001000,
        ResetDaclTree = 0x00004000,
        ResetSaclTree = 0x00008000,
        ObjectGuid = 0x00010000,
        EditEffective = 0x00020000,
        ResetDacl = 0x00040000,
        ResetSacl = 0x00080000,
        ResetOwner = 0x00100000,
        NoAdditionalPermission = 0x00200000,
        MayWrite = 0x10000000
    };
 
    // ObjectInformation defines the content and available resources 
    // within the ACL window
    [StructLayout(LayoutKind.Sequential)]
    struct ObjectInfo
    {
        internal ObjectInfoFlags Flags;
        internal IntPtr hInstance; // must be IntPtr.Zero or a SafeHandle must be used
        [MarshalAs(UnmanagedType.LPWStr)]
        internal string ServerName;
        [MarshalAs(UnmanagedType.LPWStr)]
        internal string ObjectName;
        [MarshalAs(UnmanagedType.LPWStr)]
        internal string PageTitle;
        internal Guid ObjectType; // ignored unless ObjectInfoFlags.ObjectGuid is set
 
        internal ObjectInfo(
            ObjectInfoFlags flags,
            string serverName,
            string objectName,
            string pageTitle)
        {
            this.Flags = flags;
            this.ServerName = serverName;
            this.ObjectName = objectName;
            this.PageTitle = pageTitle;
            this.ObjectType = Guid.Empty;
            this.hInstance = IntPtr.Zero;
            if (this.PageTitle != null)
            {
                this.Flags = this.Flags | ObjectInfoFlags.PageTitle;
            }
        }
    };
 
    // AccessFlags tell the ACL window where to put Access properties 
    enum AccessFlags : int
    {
        Specific = 0x00010000,
        General = 0x00020000,
        Container = 0x00040000,
        Property = 0x00080000
    };
 
 
    // Structure that defines each property
    [StructLayout(LayoutKind.Sequential)]
    struct Access
    {
        internal IntPtr Guid; // leave this empty unless you are using Active Directory style ACLs
        internal int Mask;
        [MarshalAs(UnmanagedType.LPWStr)]
        internal string Name;
        internal AccessFlags Flags;
 
        internal Access(
            int mask,
            String name,
            AccessFlags flags)
        {
            this.Guid = IntPtr.Zero;
            this.Mask = mask;
            this.Name = name;
            this.Flags = flags;
        }
    };
 
    // Inheritance flags are defined only for the GetInheritTypes function
    // this is not used in this project
    enum InheritFlags : byte
    {
        Object = 1,
        Container = 2,
        InheritOnly = 8
    };
 
    // Inheritance Type is defined only for the GetInheritTypes function
    // this is not used in this project
    [StructLayout(LayoutKind.Sequential)]
    struct InheritType
    {
        internal Guid Guid;
        internal InheritFlags Flags;
        internal String Name;
    };
 
    enum AceFlags : byte
    {
        ObjectInherit = 0x01,
        ContainerInherit = 0x02,
        NoPropagateInherit = 0x04,
        InheritOnly = 0x08,
        Inherited = 0x10,
        SuccessAudit = 0x40,
        FailureAudit = 0x80
    };
 
    // Holds togather all the permissions for an object
    class AccessRightsWrapper
    {
        internal Access[] access;
        internal int DefaultIndex;  // indicates the item in Access array that
        // should be used for default rights for new objects
    };
 
    [StructLayout(LayoutKind.Sequential)]
    struct GenericAccess
    {
        internal Guid ObjectType;
        internal AceFlags AceFlags;
        internal int Mask;
    };
 
    [StructLayout(LayoutKind.Sequential)]
    struct GenericMapping
    {
        internal int GenericRead;
        internal int GenericWrite;
        internal int GenericExecute;
        internal int GenericAll;
 
        internal GenericMapping(
            int read,
            int write,
            int execute,
            int all)
        {
            GenericRead = read;
            GenericWrite = write;
            GenericExecute = execute;
            GenericAll = all;
        }
    };
 
    // interface for the WSATSecurityModel
    interface ISecurityInformationManaged
    {
        ObjectInfo GetObjectInformation();
 
        AccessRightsWrapper GetAccessRights(
            Guid objectType,
            ObjectInfoFlags flags);
 
        IntPtr GetSecurity(
            SecurityInfos requestedInformation,
            bool wantDefault);
 
        void SetSecurity(
            SecurityInfos providedInformation,
            IntPtr pSecurityDescriptor);
 
        void MapGeneric(
            ref GenericAccess generic);
 
        InheritType[] GetInheritTypes();
    }
 
    // COM imported interface, ISecurityInformation
    [ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
    Guid("965FC360-16FF-11d0-91CB-00AA00BBB723")]
    interface ISecurityInformation
    {
        void GetObjectInformation(
            out ObjectInfo pObjectInfo);
 
        void GetSecurity(
            SecurityInfos requestedInformation,
            out IntPtr ppSecurityDescriptor, // No need to use SafeHandle since the secDesc memory will be allocated and freed by system
            bool fDefault);
 
        void SetSecurity(
            SecurityInfos securityInformation,
            IntPtr pSecurityDescriptor);
 
        void GetAccessRights(
            ref Guid pguidObjectType,
            ObjectInfoFlags flags,
            [MarshalAs(UnmanagedType.LPArray)] out Access[] ppAccess,
            out int pcAccesses,
            out int piDefaultAccess);
 
        void MapGeneric(
            ref Guid pguidObjectType,
            ref AceFlags pAceFlags,
            ref int pMask);
 
        void GetInheritTypes(
            out InheritType[] ppInheritTypes,
            out uint count);
 
        void PropertySheetPageCallback(
            IntPtr hwnd,
            int uMsg,
            PageType uPage);
    }
 
    [ComVisible(true), Guid("8aa377ab-464b-44c8-9b02-5a7c09bbf18a")]
    struct SecurityInfoCCW : ISecurityInformation
    {
        ISecurityInformationManaged model;
 
        public SecurityInfoCCW(ISecurityInformationManaged model)
        {
            this.model = model;
        }
        
        public void GetObjectInformation(out ObjectInfo pObjectInfo)
        {
            pObjectInfo = model.GetObjectInformation();
        }
 
        public void GetSecurity(
            SecurityInfos requestedInformation,
            out IntPtr ppSecurityDescriptor,
            bool fDefault)
        {
            ppSecurityDescriptor = model.GetSecurity(requestedInformation, fDefault);
        }
 
        public void SetSecurity(
            SecurityInfos securityInformation,
            IntPtr pSecurityDescriptorFromUI)
        {
            // SecurityInformation is a enumeration - we don't need to check that if being null
            // pSecurityDescriptorFromUI is the security descriptor that we receive from the UI 
            // and need to store in the registry.
            if (pSecurityDescriptorFromUI.Equals(IntPtr.Zero))
            {
                throw new ArgumentNullException(SR.GetString(SR.ACLEditorSetSecurityError));
            }
            model.SetSecurity(
                securityInformation,
                pSecurityDescriptorFromUI);
        }
 
        public void GetAccessRights(
            ref Guid pguidObjectType,
            ObjectInfoFlags dwFlags,
            [MarshalAs(UnmanagedType.LPArray)] out Access[] ppAccess,
            out int pcAccesses,
            out int piDefaultAccess)
        {
            // should set objectType to the pguidObjectType, but we don't need that
            // => we leave objectType as Guid.Empty
            Guid objectType = Guid.Empty;
 
            AccessRightsWrapper accessRights = model.GetAccessRights(objectType, dwFlags);
            Access[] access = accessRights.access;
 
            ppAccess = access;
            pcAccesses = (int)access.Length;
            piDefaultAccess = (int)accessRights.DefaultIndex;
        }
 
        public void MapGeneric(
            ref Guid pguidObjectType,
            ref AceFlags pAceFlags,
            ref int pMask)
        {
            if (pAceFlags == 0 || pMask == 0) return;
            GenericAccess ga = new GenericAccess();
            ga.AceFlags = pAceFlags;
            ga.Mask = pMask;
            this.model.MapGeneric(ref ga);
            pAceFlags = ga.AceFlags;
            pMask = ga.Mask;
        }
 
        // this method is never invoked! it is here only due to the interface ISecurityInformation
        public void GetInheritTypes(
            out InheritType[] ppInheritTypes,
            out uint count)
        {
            // not implemented. it is never used!
            ppInheritTypes = new InheritType[0];
            count = 0;
        }
 
        public void PropertySheetPageCallback(
            IntPtr hwnd,
            int uMsg,
            PageType uPage)
        {
            // no implemetation required here
        }
    }
}