/// <summary>
        /// Set ACL for control.
        /// </summary>
        /// <param name="acl">The ACL to view.</param>
        /// <param name="access_type">The enum type for the view.</param>
        /// <param name="mapping">Generic mapping for the type.</param>
        /// <param name="valid_access">The valid bit mask for access for this type.</param>
        /// <param name="is_container">True to indicate this object is a container.</param>
        /// <param name="sdk_names">Show the ACEs using SDK style names.</param>
        public void SetAcl(Acl acl, Type access_type, GenericMapping mapping, AccessMask valid_access, bool is_container, bool sdk_names)
        {
            _acl          = acl;
            _access_type  = access_type;
            _mapping      = mapping;
            _valid_access = valid_access;
            _is_container = is_container;
            _sdk_names    = sdk_names;
            showSDKNamesToolStripMenuItem.Checked = sdk_names;

            bool has_conditional_ace      = false;
            bool has_inherited_object_ace = false;
            bool has_object_ace           = false;

            List <string> flags = new List <string>();

            if (acl.Defaulted)
            {
                flags.Add("Defaulted");
            }
            if (acl.Protected)
            {
                flags.Add("Protected");
            }
            if (acl.AutoInherited)
            {
                flags.Add("AutoInherited");
            }
            if (acl.AutoInheritReq)
            {
                flags.Add("AutoInheritReq");
            }

            if (flags.Count > 0)
            {
                lblFlags.Text = $"Flags: {string.Join(", ", flags)}";
            }
            else
            {
                lblFlags.Text = "Flags: None";
            }

            if (acl.NullAcl)
            {
                lblFlags.Text             += Environment.NewLine + "NULL ACL";
                listViewAcl.Visible        = false;
                listViewAccess.Visible     = false;
                groupBoxAclEntries.Visible = false;
                groupBoxAccess.Visible     = false;
                return;
            }

            listViewAcl.Items.Clear();
            listViewAcl.Visible    = true;
            listViewAccess.Visible = true;
            listViewAccess.Items.Clear();
            _current_access_type       = null;
            groupBoxAclEntries.Visible = true;
            groupBoxAccess.Visible     = true;

            foreach (var ace in acl)
            {
                if (ace.IsConditionalAce)
                {
                    has_conditional_ace = true;
                }
                if (ace.IsObjectAce)
                {
                    if (ace.ObjectType.HasValue)
                    {
                        has_object_ace = true;
                    }
                    if (ace.InheritedObjectType.HasValue)
                    {
                        has_inherited_object_ace = true;
                    }
                }
            }

            if (!has_conditional_ace)
            {
                listViewAcl.Columns.Remove(columnHeaderCondition);
                copyConditionToolStripMenuItem.Visible = false;
            }

            if (!has_object_ace)
            {
                listViewAcl.Columns.Remove(columnHeaderObject);
            }

            if (!has_inherited_object_ace)
            {
                listViewAcl.Columns.Remove(columnHeaderInheritedObject);
            }

            foreach (var ace in acl)
            {
                var item = listViewAcl.Items.Add(sdk_names ? NtSecurity.AceTypeToSDKName(ace.Type) : ace.Type.ToString());
                item.SubItems.Add(ace.Sid.Name);
                string access;
                if (ace.Type == AceType.MandatoryLabel)
                {
                    access = NtSecurity.AccessMaskToString(ace.Mask.ToMandatoryLabelPolicy(), sdk_names);
                }
                else if (ace.Flags.HasFlag(AceFlags.InheritOnly))
                {
                    access = NtSecurity.AccessMaskToString(ace.Mask.ToSpecificAccess(access_type), sdk_names);
                }
                else
                {
                    AccessMask mapped_mask = mapping.MapMask(ace.Mask);
                    mapped_mask = mapping.UnmapMask(mapped_mask);
                    access      = NtSecurity.AccessMaskToString(mapped_mask.ToSpecificAccess(access_type), sdk_names);
                }

                item.SubItems.Add(access);
                item.SubItems.Add(sdk_names ? NtSecurity.AceFlagsToSDKName(ace.Flags) : ace.Flags.ToString());
                if (has_conditional_ace)
                {
                    item.SubItems.Add(ace.Condition);
                }

                if (has_object_ace)
                {
                    item.SubItems.Add(ace.ObjectType?.ToString() ?? string.Empty);
                }

                if (has_inherited_object_ace)
                {
                    item.SubItems.Add(ace.InheritedObjectType?.ToString() ?? string.Empty);
                }

                item.Tag = ace;

                switch (ace.Type)
                {
                case AceType.Allowed:
                case AceType.AllowedCallback:
                case AceType.AllowedCallbackObject:
                case AceType.AllowedObject:
                    item.BackColor = Color.LightGreen;
                    break;

                case AceType.Denied:
                case AceType.DeniedCallback:
                case AceType.DeniedCallbackObject:
                case AceType.DeniedObject:
                    item.BackColor = Color.LightSalmon;
                    break;

                case AceType.ProcessTrustLabel:
                    item.BackColor = Color.LightSkyBlue;
                    break;

                case AceType.MandatoryLabel:
                    item.BackColor = Color.LightGoldenrodYellow;
                    break;

                case AceType.Audit:
                case AceType.AuditCallback:
                case AceType.AuditCallbackObject:
                case AceType.AuditObject:
                    item.BackColor = Color.LightCoral;
                    break;
                }
            }
            listViewAcl.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
            listViewAcl.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
        }
        private protected override void RunAccessCheck(IEnumerable <TokenEntry> tokens)
        {
            if (CheckScmAccess)
            {
                SecurityDescriptor sd            = ServiceUtils.GetScmSecurityDescriptor();
                GenericMapping     scm_mapping   = ServiceUtils.GetScmGenericMapping();
                AccessMask         access_rights = scm_mapping.MapMask(ScmAccess);
                foreach (TokenEntry token in tokens)
                {
                    AccessMask granted_access = NtSecurity.GetMaximumAccess(sd, token.Token, scm_mapping);
                    if (IsAccessGranted(granted_access, access_rights))
                    {
                        WriteAccessCheckResult("SCM", "SCM", granted_access, scm_mapping, sd,
                                               typeof(ServiceControlManagerAccessRights), false, token.Information);
                    }
                }
            }
            else
            {
                IEnumerable <Win32Service>      services    = GetServices();
                InternalGetAccessibleFileCmdlet file_cmdlet = null;
                HashSet <string> checked_files = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
                if (CheckFiles)
                {
                    file_cmdlet = new InternalGetAccessibleFileCmdlet(this)
                    {
                        FormatWin32Path    = true,
                        Access             = FileAccessRights.WriteData | FileAccessRights.WriteDac | FileAccessRights.WriteOwner | FileAccessRights.AppendData | FileAccessRights.Delete,
                        DirectoryAccess    = FileDirectoryAccessRights.AddFile | FileDirectoryAccessRights.WriteDac | FileDirectoryAccessRights.WriteOwner,
                        AllowPartialAccess = true
                    };
                }

                GenericMapping service_mapping = ServiceUtils.GetServiceGenericMapping();
                AccessMask     access_rights   = service_mapping.MapMask(Access);

                foreach (var service in services.Where(s => s?.SecurityDescriptor != null))
                {
                    foreach (TokenEntry token in tokens)
                    {
                        AccessMask granted_access = NtSecurity.GetMaximumAccess(service.SecurityDescriptor,
                                                                                token.Token, service_mapping);
                        ServiceAccessRights trigger_access = GetTriggerAccess(service, token.Token);
                        if (IsAccessGranted(granted_access, access_rights))
                        {
                            WriteObject(new ServiceAccessCheckResult(service.Name, granted_access | trigger_access,
                                                                     service.SecurityDescriptor, token.Information, trigger_access,
                                                                     granted_access.ToSpecificAccess <ServiceAccessRights>(), service));
                        }
                    }
                    if (CheckFiles)
                    {
                        if (!string.IsNullOrWhiteSpace(service.ImagePath) &&
                            File.Exists(service.ImagePath) &&
                            checked_files.Add(service.ImagePath))
                        {
                            file_cmdlet.RunAccessCheckPathInternal(tokens, service.ImagePath);
                            file_cmdlet.RunAccessCheckPathInternal(tokens, Path.GetDirectoryName(service.ImagePath));
                        }

                        if (!string.IsNullOrWhiteSpace(service.ServiceDll) &&
                            File.Exists(service.ServiceDll) &&
                            checked_files.Add(service.ServiceDll))
                        {
                            file_cmdlet.RunAccessCheckPathInternal(tokens, service.ServiceDll);
                            file_cmdlet.RunAccessCheckPathInternal(tokens, Path.GetDirectoryName(service.ServiceDll));
                        }
                    }
                }
            }
        }