diff --git a/PInvoke/Security/AdvApi32/WinNT.Extensions.cs b/PInvoke/Security/AdvApi32/WinNT.Extensions.cs new file mode 100644 index 00000000..ce48a19a --- /dev/null +++ b/PInvoke/Security/AdvApi32/WinNT.Extensions.cs @@ -0,0 +1,154 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using Vanara.Extensions; +using static Vanara.PInvoke.AdvApi32; + +namespace Vanara.PInvoke +{ + /// Extension methods for PACE, PACL and PSECURITY_DESCRIPTOR. + public static class WinNTExtensions + { + /// Gets the number of ACEs held by an ACL. + /// The pointer to the ACL structure to query. + /// The ace count. + public static uint AceCount(this PACL pACL) => IsValidAcl(pACL) && GetAclInformation(pACL, out ACL_SIZE_INFORMATION si) ? si.AceCount : 0; + + /// Gets the total number of bytes allocated to the ACL. + /// The pointer to the ACL structure to query. + /// The total of the free and used bytes in the ACL. + public static uint BytesAllocated(this PACL pACL) => IsValidAcl(pACL) && GetAclInformation(pACL, out ACL_SIZE_INFORMATION si) ? si.AclBytesFree + si.AclBytesInUse : 0; + + /// The GetAce function obtains a pointer to an access control entry (ACE) in an access control list (ACL). + /// A pointer to an ACL that contains the ACE to be retrieved. + /// + /// The index of the ACE to be retrieved. A value of zero corresponds to the first ACE in the ACL, a value of one to the second ACE, + /// and so on. + /// + /// A pointer to the ACE. + public static PACE GetAce(this PACL pAcl, uint aceIndex) + { + Win32Error.ThrowLastErrorIfFalse(AdvApi32.GetAce(pAcl, aceIndex, out var acePtr)); + return acePtr; + } + + /// Enumerates the ACEs in an ACL. + /// A pointer to an ACL that contains the ACE to be retrieved. + /// A sequence of PACE values from the ACL. + public static IEnumerable EnumerateAces(this PACL pAcl) + { + for (var i = 0U; i < pAcl.AceCount(); i++) + yield return GetAce(pAcl, i); + } + + /// Gets the Flags for an ACE, if defined. + /// A pointer to an ACE. + /// The Flags value, if this is an object ACE, otherwise . + /// pAce + public static AdvApi32.ObjectAceFlags? GetFlags(this PACE pAce) + { + if (pAce.IsNull) throw new ArgumentNullException(nameof(pAce)); + return !pAce.IsObjectAce() ? null : pAce.DangerousGetHandle().ToStructure().Flags; + } + + /// Gets the header for an ACE. + /// A pointer to an ACE. + /// The value. + /// pAce + public static ACE_HEADER GetHeader(this PACE pAce) => !pAce.IsNull ? pAce.DangerousGetHandle().ToStructure() : throw new ArgumentNullException(nameof(pAce)); + + /// Gets the InheritedObjectType for an ACE, if defined. + /// A pointer to an ACE. + /// The InheritedObjectType value, if this is an object ACE, otherwise . + /// pAce + public static Guid? GetInheritedObjectType(this PACE pAce) + { + if (pAce.IsNull) throw new ArgumentNullException(nameof(pAce)); + return !pAce.IsObjectAce() ? null : pAce.DangerousGetHandle().ToStructure().InheritedObjectType; + } + + /// Gets the mask for an ACE. + /// A pointer to an ACE. + /// The ACCESS_MASK value. + /// pAce + public static uint GetMask(this PACE pAce) => !pAce.IsNull ? pAce.DangerousGetHandle().ToStructure().Mask : throw new ArgumentNullException(nameof(pAce)); + + /// Gets the ObjectType for an ACE, if defined. + /// A pointer to an ACE. + /// The ObjectType value, if this is an object ACE, otherwise . + /// pAce + public static Guid? GetObjectType(this PACE pAce) + { + if (pAce.IsNull) throw new ArgumentNullException(nameof(pAce)); + return !pAce.IsObjectAce() ? null : pAce.DangerousGetHandle().ToStructure().ObjectType; + } + + /// Gets the SID for an ACE. + /// A pointer to an ACE. + /// The SID value. + /// pAce + public static SafePSID GetSid(this PACE pAce) + { + if (pAce.IsNull) throw new ArgumentNullException(nameof(pAce)); + var offset = Marshal.SizeOf(typeof(ACE_HEADER)) + sizeof(uint); + if (pAce.IsObjectAce()) offset += sizeof(uint) + Marshal.SizeOf(typeof(Guid)) * 2; + unsafe + { + return SafePSID.CreateFromPtr((IntPtr)((byte*)pAce.DangerousGetHandle() + offset)); + } + } + + /// Determines if a ACE is an object ACE. + /// A pointer to an ACE. + /// if is this is an object ACE; otherwise, . + /// pAce + /// pAce - Unknown ACE type. + public static bool IsObjectAce(this PACE pAce) + { + if (pAce.IsNull) throw new ArgumentNullException(nameof(pAce)); + var aceType = (byte)GetHeader(pAce).AceType; + if (aceType > 0x15) throw new ArgumentOutOfRangeException(nameof(pAce), "Unknown ACE type."); + return (aceType >= 0x5 && aceType <= 0x8) || aceType == 0xB || aceType == 0xC || aceType == 0xF || aceType == 0x10; + } + + /// Determines whether the security descriptor is self-relative. + /// The pointer to the SECURITY_DESCRIPTOR structure to query. + /// true if it is self-relative; otherwise, false. + public static bool IsSelfRelative(this PSECURITY_DESCRIPTOR pSD) => GetSecurityDescriptorControl(pSD, out var ctrl, out _) ? ctrl.IsFlagSet(SECURITY_DESCRIPTOR_CONTROL.SE_SELF_RELATIVE) : throw Win32Error.GetLastError().GetException(); + + /// Validates an access control list (ACL). + /// The pointer to the ACL structure to query. + /// true if the ACL is valid; otherwise, false. + public static bool IsValidAcl(this PACL pAcl) => IsValidAcl(pAcl); + + /// Determines whether the components of a security descriptor are valid. + /// The pointer to the SECURITY_DESCRIPTOR structure to query. + /// + /// true if the components of the security descriptor are valid. If any of the components of the security descriptor are not + /// valid, the return value is false. + /// + public static bool IsValidSecurityDescriptor(this PSECURITY_DESCRIPTOR pSD) => IsValidSecurityDescriptor(pSD); + + /// Gets the size, in bytes, of an ACE. + /// The pointer to the ACE structure to query. + /// The size, in bytes, of the ACE. + public static uint Length(this PACE pAce) + { + unsafe + { + var p = (ACE_HEADER*)(void*)pAce.DangerousGetHandle(); + return p == null ? 0U : p->AceSize; + } + } + + /// Gets the size, in bytes, of an ACL. If the ACL is not valid, 0 is returned. + /// The pointer to the ACL structure to query. + /// The size, in bytes, of an ACL. If the ACL is not valid, 0 is returned. + public static uint Length(this PACL pACL) => IsValidAcl(pACL) && GetAclInformation(pACL, out ACL_SIZE_INFORMATION si) ? si.AclBytesInUse : 0; + + /// Gets the size, in bytes, of a security descriptor. If it is not valid, 0 is returned. + /// The pointer to the SECURITY_DESCRIPTOR structure to query. + /// The size, in bytes, of a security descriptor. If it is not valid, 0 is returned. + public static uint Length(this PSECURITY_DESCRIPTOR pSD) => IsValidSecurityDescriptor(pSD) ? GetSecurityDescriptorLength(pSD) : 0U; + } +} \ No newline at end of file diff --git a/PInvoke/Security/AdvApi32/WinNT.cs b/PInvoke/Security/AdvApi32/WinNT.cs index bc3c912f..70eca830 100644 --- a/PInvoke/Security/AdvApi32/WinNT.cs +++ b/PInvoke/Security/AdvApi32/WinNT.cs @@ -4979,128 +4979,4 @@ namespace Vanara.PInvoke public string ToString(SECURITY_INFORMATION secInfo) => ConvertSecurityDescriptorToStringSecurityDescriptor(handle, secInfo); } } - - /// Extension methods for PACE, PACL and PSECURITY_DESCRIPTOR. - public static class WinNTExtensions - { - /// Gets the number of ACEs held by an ACL. - /// The pointer to the ACL structure to query. - /// The ace count. - public static uint AceCount(this PACL pACL) => AdvApi32.IsValidAcl(pACL) && AdvApi32.GetAclInformation(pACL, out AdvApi32.ACL_SIZE_INFORMATION si) ? si.AceCount : 0; - - /// Gets the total number of bytes allocated to the ACL. - /// The pointer to the ACL structure to query. - /// The total of the free and used bytes in the ACL. - public static uint BytesAllocated(this PACL pACL) => AdvApi32.IsValidAcl(pACL) && AdvApi32.GetAclInformation(pACL, out AdvApi32.ACL_SIZE_INFORMATION si) ? si.AclBytesFree + si.AclBytesInUse : 0; - - /// Gets the Flags for an ACE, if defined. - /// A pointer to an ACE. - /// The Flags value, if this is an object ACE, otherwise . - /// pAce - public static ObjectAceFlags? GetFlags(this PACE pAce) - { - if (pAce.IsNull) throw new ArgumentNullException(nameof(pAce)); - return !pAce.IsObjectAce() ? null : (ObjectAceFlags?)pAce.DangerousGetHandle().ToStructure().Flags; - } - - /// Gets the header for an ACE. - /// A pointer to an ACE. - /// The value. - /// pAce - public static AdvApi32.ACE_HEADER GetHeader(this PACE pAce) => !pAce.IsNull ? pAce.DangerousGetHandle().ToStructure() : throw new ArgumentNullException(nameof(pAce)); - - /// Gets the InheritedObjectType for an ACE, if defined. - /// A pointer to an ACE. - /// The InheritedObjectType value, if this is an object ACE, otherwise . - /// pAce - public static Guid? GetInheritedObjectType(this PACE pAce) - { - if (pAce.IsNull) throw new ArgumentNullException(nameof(pAce)); - return !pAce.IsObjectAce() ? null : (Guid?)pAce.DangerousGetHandle().ToStructure().InheritedObjectType; - } - - /// Gets the mask for an ACE. - /// A pointer to an ACE. - /// The ACCESS_MASK value. - /// pAce - public static uint GetMask(this PACE pAce) => !pAce.IsNull ? pAce.DangerousGetHandle().ToStructure().Mask : throw new ArgumentNullException(nameof(pAce)); - - /// Gets the ObjectType for an ACE, if defined. - /// A pointer to an ACE. - /// The ObjectType value, if this is an object ACE, otherwise . - /// pAce - public static Guid? GetObjectType(this PACE pAce) - { - if (pAce.IsNull) throw new ArgumentNullException(nameof(pAce)); - return !pAce.IsObjectAce() ? null : (Guid?)pAce.DangerousGetHandle().ToStructure().ObjectType; - } - - /// Gets the SID for an ACE. - /// A pointer to an ACE. - /// The SID value. - /// pAce - public static AdvApi32.SafePSID GetSid(this PACE pAce) - { - if (pAce.IsNull) throw new ArgumentNullException(nameof(pAce)); - var offset = Marshal.SizeOf(typeof(AdvApi32.ACE_HEADER)) + sizeof(uint); - if (pAce.IsObjectAce()) offset += sizeof(uint) + Marshal.SizeOf(typeof(Guid)) * 2; - unsafe - { - return AdvApi32.SafePSID.CreateFromPtr((IntPtr)((byte*)pAce.DangerousGetHandle() + offset)); - } - } - - /// Determines if a ACE is an object ACE. - /// A pointer to an ACE. - /// if is this is an object ACE; otherwise, . - /// pAce - /// pAce - Unknown ACE type. - public static bool IsObjectAce(this PACE pAce) - { - if (pAce.IsNull) throw new ArgumentNullException(nameof(pAce)); - var aceType = (byte)GetHeader(pAce).AceType; - if (aceType > 0x15) throw new ArgumentOutOfRangeException(nameof(pAce), "Unknown ACE type."); - return (aceType >= 0x5 && aceType <= 0x8) || aceType == 0xB || aceType == 0xC || aceType == 0xF || aceType == 0x10; - } - - /// Determines whether the security descriptor is self-relative. - /// The pointer to the SECURITY_DESCRIPTOR structure to query. - /// true if it is self-relative; otherwise, false. - public static bool IsSelfRelative(this PSECURITY_DESCRIPTOR pSD) => AdvApi32.GetSecurityDescriptorControl(pSD, out var ctrl, out _) ? ctrl.IsFlagSet(AdvApi32.SECURITY_DESCRIPTOR_CONTROL.SE_SELF_RELATIVE) : throw Win32Error.GetLastError().GetException(); - - /// Validates an access control list (ACL). - /// The pointer to the ACL structure to query. - /// true if the ACL is valid; otherwise, false. - public static bool IsValidAcl(this PACL pAcl) => AdvApi32.IsValidAcl(pAcl); - - /// Determines whether the components of a security descriptor are valid. - /// The pointer to the SECURITY_DESCRIPTOR structure to query. - /// - /// true if the components of the security descriptor are valid. If any of the components of the security descriptor are not - /// valid, the return value is false. - /// - public static bool IsValidSecurityDescriptor(this PSECURITY_DESCRIPTOR pSD) => AdvApi32.IsValidSecurityDescriptor(pSD); - - /// Gets the size, in bytes, of an ACE. - /// The pointer to the ACE structure to query. - /// The size, in bytes, of the ACE. - public static uint Length(this PACE pAce) - { - unsafe - { - var p = (AdvApi32.ACE_HEADER*)(void*)pAce.DangerousGetHandle(); - return p == null ? 0U : p->AceSize; - } - } - - /// Gets the size, in bytes, of an ACL. If the ACL is not valid, 0 is returned. - /// The pointer to the ACL structure to query. - /// The size, in bytes, of an ACL. If the ACL is not valid, 0 is returned. - public static uint Length(this PACL pACL) => AdvApi32.IsValidAcl(pACL) && AdvApi32.GetAclInformation(pACL, out AdvApi32.ACL_SIZE_INFORMATION si) ? si.AclBytesInUse : 0; - - /// Gets the size, in bytes, of a security descriptor. If it is not valid, 0 is returned. - /// The pointer to the SECURITY_DESCRIPTOR structure to query. - /// The size, in bytes, of a security descriptor. If it is not valid, 0 is returned. - public static uint Length(this PSECURITY_DESCRIPTOR pSD) => AdvApi32.IsValidSecurityDescriptor(pSD) ? AdvApi32.GetSecurityDescriptorLength(pSD) : 0U; - } } \ No newline at end of file