private AuthorizationRuleCollection GetRules(bool access, bool includeExplicit, bool includeInherited, System.Type targetType)
{
ReadLock();
try
{
AuthorizationRuleCollection result = new AuthorizationRuleCollection();
if (!IsValidTargetTypeStatic(targetType))
{
throw new ArgumentException(SR.Arg_MustBeIdentityReferenceType, "targetType");
}
CommonAcl acl = null;
if (access)
{
if ((_securityDescriptor.ControlFlags & ControlFlags.DiscretionaryAclPresent) != 0)
{
acl = _securityDescriptor.DiscretionaryAcl;
}
}
else // !access == audit
{
if ((_securityDescriptor.ControlFlags & ControlFlags.SystemAclPresent) != 0)
{
acl = _securityDescriptor.SystemAcl;
}
}
if (acl == null)
{
//
// The required ACL was not present; return an empty collection.
//
return result;
}
IdentityReferenceCollection irTarget = null;
if (targetType != typeof(SecurityIdentifier))
{
IdentityReferenceCollection irSource = new IdentityReferenceCollection(acl.Count);
for (int i = 0; i < acl.Count; i++)
{
//
// Calling the indexer on a common ACL results in cloning,
// (which would not be the case if we were to use the internal RawAcl property)
// but also ensures that the resulting order of ACEs is proper
// However, this is a big price to pay - cloning all the ACEs just so that
// the canonical order could be ascertained just once.
// A better way would be to have an internal method that would canonicalize the ACL
// and call it once, then use the RawAcl.
//
QualifiedAce ace = acl[i] as QualifiedAce;
if (ace == null)
{
//
// Only consider qualified ACEs
//
continue;
}
if (ace.IsCallback == true)
{
//
// Ignore callback ACEs
//
continue;
}
if (access)
{
if (ace.AceQualifier != AceQualifier.AccessAllowed && ace.AceQualifier != AceQualifier.AccessDenied)
{
continue;
}
}
else
{
if (ace.AceQualifier != AceQualifier.SystemAudit)
{
continue;
}
}
irSource.Add(ace.SecurityIdentifier);
}
irTarget = irSource.Translate(targetType);
}
for (int i = 0; i < acl.Count; i++)
{
//
// Calling the indexer on a common ACL results in cloning,
// (which would not be the case if we were to use the internal RawAcl property)
// but also ensures that the resulting order of ACEs is proper
// However, this is a big price to pay - cloning all the ACEs just so that
// the canonical order could be ascertained just once.
// A better way would be to have an internal method that would canonicalize the ACL
// and call it once, then use the RawAcl.
//
QualifiedAce ace = acl[i] as CommonAce;
if (ace == null)
{
ace = acl[i] as ObjectAce;
if (ace == null)
{
//
// Only consider common or object ACEs
//
continue;
}
}
if (ace.IsCallback == true)
{
//
// Ignore callback ACEs
//
continue;
}
if (access)
{
if (ace.AceQualifier != AceQualifier.AccessAllowed && ace.AceQualifier != AceQualifier.AccessDenied)
{
continue;
}
}
else
{
if (ace.AceQualifier != AceQualifier.SystemAudit)
{
continue;
}
}
if ((includeExplicit && ((ace.AceFlags & AceFlags.Inherited) == 0)) || (includeInherited && ((ace.AceFlags & AceFlags.Inherited) != 0)))
{
IdentityReference iref = (targetType == typeof(SecurityIdentifier)) ? ace.SecurityIdentifier : irTarget[i];
if (access)
{
AccessControlType type;
if (ace.AceQualifier == AceQualifier.AccessAllowed)
{
type = AccessControlType.Allow;
}
else
{
type = AccessControlType.Deny;
}
if (ace is ObjectAce)
{
ObjectAce objectAce = ace as ObjectAce;
result.AddRule(AccessRuleFactory(iref, objectAce.AccessMask, objectAce.IsInherited, objectAce.InheritanceFlags, objectAce.PropagationFlags, type, objectAce.ObjectAceType, objectAce.InheritedObjectAceType));
}
else
{
CommonAce commonAce = ace as CommonAce;
if (commonAce == null)
{
continue;
}
result.AddRule(AccessRuleFactory(iref, commonAce.AccessMask, commonAce.IsInherited, commonAce.InheritanceFlags, commonAce.PropagationFlags, type));
}
}
else
{
if (ace is ObjectAce)
{
ObjectAce objectAce = ace as ObjectAce;
result.AddRule(AuditRuleFactory(iref, objectAce.AccessMask, objectAce.IsInherited, objectAce.InheritanceFlags, objectAce.PropagationFlags, objectAce.AuditFlags, objectAce.ObjectAceType, objectAce.InheritedObjectAceType));
}
else
{
CommonAce commonAce = ace as CommonAce;
if (commonAce == null)
{
continue;
}
result.AddRule(AuditRuleFactory(iref, commonAce.AccessMask, commonAce.IsInherited, commonAce.InheritanceFlags, commonAce.PropagationFlags, commonAce.AuditFlags));
}
}
}
}
return result;
}
finally
{
ReadUnlock();
}
}