using System; using System.Collections.Generic; using System.ComponentModel; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; using System.Security.AccessControl; using Vanara.Extensions; using Vanara.InteropServices; using static Vanara.PInvoke.FunctionHelper; using static Vanara.PInvoke.Kernel32; namespace Vanara.PInvoke { public static partial class AdvApi32 { private static readonly Dictionary StructSizes = new(); /// Specifies the logon provider. public enum LogonUserProvider { /// /// Use the standard logon provider for the system. The default security provider is negotiate, unless you pass NULL for the /// domain name and the user name is not in UPN format. In this case, the default provider is NTLM. /// LOGON32_PROVIDER_DEFAULT = 0, /// Use the Windows NT 3.5 logon provider. LOGON32_PROVIDER_WINNT35 = 1, /// Use the NTLM logon provider. LOGON32_PROVIDER_WINNT40 = 2, /// Use the negotiate logon provider. LOGON32_PROVIDER_WINNT50 = 3, /// Use the virtual logon provider. LOGON32_PROVIDER_VIRTUAL = 4 } /// The type of logon operation to perform. public enum LogonUserType { /// /// This logon type is intended for users who will be interactively using the computer, such as a user being logged on by a /// terminal server, remote shell, or similar process. This logon type has the additional expense of caching logon information /// for disconnected operations; therefore, it is inappropriate for some client/server applications, such as a mail server. /// LOGON32_LOGON_INTERACTIVE = 2, /// /// This logon type is intended for high performance servers to authenticate plaintext passwords. The LogonUser function does not /// cache credentials for this logon type. /// LOGON32_LOGON_NETWORK = 3, /// /// This logon type is intended for batch servers, where processes may be executing on behalf of a user without their direct /// intervention. This type is also for higher performance servers that process many plaintext authentication attempts at a time, /// such as mail or web servers. /// LOGON32_LOGON_BATCH = 4, /// Indicates a service-type logon. The account provided must have the service privilege enabled. LOGON32_LOGON_SERVICE = 5, /// /// GINAs are no longer supported. /// /// Windows Server 2003 and Windows XP: This logon type is for GINA DLLs that log on users who will be interactively using /// the computer. This logon type can generate a unique audit record that shows when the workstation was unlocked. /// /// LOGON32_LOGON_UNLOCK = 7, /// /// This logon type preserves the name and password in the authentication package, which allows the server to make connections to /// other network servers while impersonating the client. A server can accept plain-text credentials from a client, call /// LogonUser, verify that the user can access the system across the network, and still communicate with other servers. /// LOGON32_LOGON_NETWORK_CLEARTEXT = 8, /// /// This logon type allows the caller to clone its current token and specify new credentials for outbound connections. The new /// logon session has the same local identifier but uses different credentials for other network connections. This logon type is /// supported only by the LOGON32_PROVIDER_WINNT50 logon provider. /// LOGON32_LOGON_NEW_CREDENTIALS = 9 } /// /// The AccessCheck function determines whether a security descriptor grants a specified set of access rights to the client /// identified by an access token. Typically, server applications use this function to check access to a private object. /// /// A pointer to a SECURITY_DESCRIPTOR structure against which access is checked. /// /// A handle to an impersonation token that represents the client that is attempting to gain access. The handle must have TOKEN_QUERY /// access to the token; otherwise, the function fails with ERROR_ACCESS_DENIED. /// /// /// /// Access mask that specifies the access rights to check. This mask must have been mapped by the MapGenericMask function to contain /// no generic access rights. /// /// /// If this parameter is MAXIMUM_ALLOWED, the function sets the GrantedAccess access mask to indicate the maximum access rights the /// security descriptor allows the client. /// /// /// /// A pointer to the GENERIC_MAPPING structure associated with the object for which access is being checked. /// /// /// A pointer to a PRIVILEGE_SET structure that receives the privileges used to perform the access validation. If no privileges were /// used, the function sets the PrivilegeCount member to zero. /// /// Specifies the size, in bytes, of the buffer pointed to by the PrivilegeSet parameter. /// /// A pointer to an access mask that receives the granted access rights. If AccessStatus is set to FALSE, the function sets /// the access mask to zero. If the function fails, it does not set the access mask. /// /// /// A pointer to a variable that receives the results of the access check. If the security descriptor allows the requested access /// rights to the client identified by the access token, AccessStatus is set to TRUE. Otherwise, AccessStatus is set to /// FALSE, and you can call GetLastError to get extended error information. /// /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// /// /// For more information, see the How AccessCheck Works overview. /// /// The AccessCheck function compares the specified security descriptor with the specified access token and indicates, in the /// AccessStatus parameter, whether access is granted or denied. If access is granted, the requested access mask becomes the object's /// granted access mask. /// /// /// If the security descriptor's DACL is NULL, the AccessStatus parameter returns TRUE, which indicates that the client /// has the requested access. /// /// /// The AccessCheck function fails with ERROR_INVALID_SECURITY_DESCR if the security descriptor does not contain owner and /// group SIDs. /// /// /// The AccessCheck function does not generate an audit. If your application requires audits for access checks, use functions /// such as AccessCheckAndAuditAlarm, AccessCheckByTypeAndAuditAlarm, AccessCheckByTypeResultListAndAuditAlarm, or /// AccessCheckByTypeResultListAndAuditAlarmByHandle, instead of AccessCheck. /// /// Examples /// For an example that uses this function, see Verifying Client Access with ACLs. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-accesscheck BOOL AccessCheck( // PSECURITY_DESCRIPTOR pSecurityDescriptor, HANDLE ClientToken, DWORD DesiredAccess, PGENERIC_MAPPING GenericMapping, PPRIVILEGE_SET // PrivilegeSet, LPDWORD PrivilegeSetLength, LPDWORD GrantedAccess, LPBOOL AccessStatus ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "d9fd2e44-5782-40c9-a1cf-1788ca7afc50")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AccessCheck(PSECURITY_DESCRIPTOR pSecurityDescriptor, HTOKEN ClientToken, ACCESS_MASK DesiredAccess, in GENERIC_MAPPING GenericMapping, [In, Out, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PRIVILEGE_SET.Marshaler))] PRIVILEGE_SET PrivilegeSet, ref uint PrivilegeSetLength, out uint GrantedAccess, [MarshalAs(UnmanagedType.Bool)] out bool AccessStatus); /// /// The AccessCheckByType function determines whether a security descriptor grants a specified set of access rights to the /// client identified by an access token. The function can check the client's access to a hierarchy of objects, such as an object, /// its property sets, and properties. The function grants or denies access to the hierarchy as a whole. Typically, server /// applications use this function to check access to a private object. /// /// A pointer to a SECURITY_DESCRIPTOR structure against which access is checked. /// /// /// A pointer to a security identifier (SID). If the security descriptor is associated with an object that represents a principal /// (for example, a user object), the PrincipalSelfSid parameter should be the SID of the object. When evaluating access, this SID /// logically replaces the SID in any access control entry containing the well-known PRINCIPAL_SELF SID (S-1-5-10). For information /// about well-known SIDs, see Well-known SIDs. /// /// Set this parameter to NULL if the protected object does not represent a principal. /// /// /// A handle to an impersonation token that represents the client attempting to gain access. The handle must have TOKEN_QUERY access /// to the token; otherwise, the function fails with ERROR_ACCESS_DENIED. /// /// /// /// Access mask that specifies the access rights to check. This mask must have been mapped by the MapGenericMask function to contain /// no generic access rights. /// /// /// If this parameter is MAXIMUM_ALLOWED, the function sets the GrantedAccess access mask to indicate the maximum access rights the /// security descriptor allows the client. /// /// /// /// /// A pointer to an array of OBJECT_TYPE_LIST structures that identify the hierarchy of object types for which to check access. Each /// element in the array specifies a GUID that identifies the object type and a value indicating the level of the object type in the /// hierarchy of object types. The array should not have two elements with the same GUID. /// /// /// The array must have at least one element. The first element in the array must be at level zero and identify the object itself. /// The array can have only one level zero element. The second element is a subobject, such as a property set, at level 1. Following /// each level 1 entry are subordinate entries for the level 2 through 4 subobjects. Thus, the levels for the elements in the array /// might be {0, 1, 2, 2, 1, 2, 3}. If the object type list is out of order, AccessCheckByType fails and GetLastError returns ERROR_INVALID_PARAMETER. /// /// If ObjectTypeList is NULL, AccessCheckByType is the same as the AccessCheck function. /// /// Specifies the number of elements in the ObjectTypeList array. /// /// A pointer to the GENERIC_MAPPING structure associated with the object for which access is being checked. The GenericAll /// member of the GENERIC_MAPPING structure should contain all the access rights that can be granted by the resource manager, /// including STANDARD_RIGHTS_ALL and all of the rights that are set in the GenericRead, GenericWrite, and /// GenericExecute members. /// /// /// A pointer to a PRIVILEGE_SET structure that receives the privileges used to perform the access validation. If no privileges were /// used, the function sets the PrivilegeCount member to zero. /// /// Specifies the size, in bytes, of the buffer pointed to by the PrivilegeSet parameter. /// /// A pointer to an access mask that receives the granted access rights. If AccessStatus is set to FALSE, the function sets /// the access mask to zero. If the function fails, it does not set the access mask. /// /// /// A pointer to a variable that receives the results of the access check. If the security descriptor allows the requested access /// rights to the client identified by the access token, AccessStatus is set to TRUE. Otherwise, AccessStatus is set to /// FALSE, and you can call GetLastError to get extended error information. /// /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// /// /// For more information, see the How AccessCheck Works overview. /// /// The AccessCheckByType function compares the specified security descriptor with the specified access token and indicates, /// in the AccessStatus parameter, whether access is granted or denied. /// /// /// The ObjectTypeList array does not necessarily represent the entire defined object. Rather, it represents that subset of the /// object for which to check access. For instance, to check access to two properties in a property set, specify an object type list /// with four elements: the object itself at level zero, the property set at level 1, and the two properties at level 2. /// /// /// The AccessCheckByType function evaluates ACEs that apply to the object itself and object-specific ACEs for the object /// types listed in the ObjectTypeList array. The function ignores object-specific ACEs for object types not listed in the /// ObjectTypeList array. Thus, the results returned in the AccessStatus parameter indicate the access allowed to the subset of the /// object defined by the ObjectTypeList parameter, not to the entire object. /// /// /// For more information about how a hierarchy of ACEs controls access to an object and its subobjects, see ACEs to Control Access to /// an Object's Properties. /// /// /// If the security descriptor's DACL is NULL, the AccessStatus parameter returns TRUE, indicating that the client has /// the requested access. /// /// If the security descriptor does not contain owner and group SIDs, AccessCheckByType fails with ERROR_INVALID_SECURITY_DESCR. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-accesscheckbytype BOOL AccessCheckByType( // PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID PrincipalSelfSid, HANDLE ClientToken, DWORD DesiredAccess, POBJECT_TYPE_LIST // ObjectTypeList, DWORD ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, PPRIVILEGE_SET PrivilegeSet, LPDWORD // PrivilegeSetLength, LPDWORD GrantedAccess, LPBOOL AccessStatus ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "50acfc17-459d-464c-9927-88b32dd424c7")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AccessCheckByType(PSECURITY_DESCRIPTOR pSecurityDescriptor, [Optional] PSID PrincipalSelfSid, HTOKEN ClientToken, ACCESS_MASK DesiredAccess, [In, Optional] OBJECT_TYPE_LIST[] ObjectTypeList, [Optional] uint ObjectTypeListLength, in GENERIC_MAPPING GenericMapping, [In, Out, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PRIVILEGE_SET.Marshaler))] PRIVILEGE_SET PrivilegeSet, ref uint PrivilegeSetLength, out uint GrantedAccess, [MarshalAs(UnmanagedType.Bool)] out bool AccessStatus); /// /// The AccessCheckByTypeResultList function determines whether a security descriptor grants a specified set of access rights /// to the client identified by an access token. The function can check the client's access to a hierarchy of objects, such as an /// object, its property sets, and properties. The function reports the access rights granted or denied to each object type in the /// hierarchy. Typically, server applications use this function to check access to a private object. /// /// A pointer to a SECURITY_DESCRIPTOR structure against which access is checked. /// /// /// A pointer to a security identifier (SID). If the security descriptor is associated with an object that represents a principal /// (for example, a user object), the PrincipalSelfSid parameter should be the SID of the object. When evaluating access, this SID /// logically replaces the SID in any access control entry (ACE) that contains the well-known PRINCIPAL_SELF SID (S-1-5-10). For /// information about well-known SIDs, see Well-known SIDs. /// /// If the protected object does not represent a principal, set this parameter to NULL. /// /// /// A handle to an impersonation token that represents the client attempting to gain access. The handle must have TOKEN_QUERY access /// to the token; otherwise, the function fails with ERROR_ACCESS_DENIED. /// /// /// /// An access mask that specifies the access rights to check. This mask must have been mapped by the MapGenericMask function to /// contain no generic access rights. /// /// /// If this parameter is MAXIMUM_ALLOWED, the function sets the access masks in the GrantedAccess array to indicate the client's /// maximum access rights to each element in the object type list. /// /// /// /// /// A pointer to an array of OBJECT_TYPE_LIST structures that identify the hierarchy of object types for which to check access. Each /// element in the array specifies a GUID that identifies the object type and a value that indicates the level of the object type in /// the hierarchy of object types. The array should not have two elements with the same GUID. /// /// /// The array must have at least one element. The first element in the array must be at level zero and identify the object itself. /// The array can have only one level zero element. The second element is a subobject, such as a property set, at level 1. Following /// each level 1 entry are subordinate entries for the level 2 through 4 subobjects. Thus, the levels for the elements in the array /// might be {0, 1, 2, 2, 1, 2, 3}. If the object type list is out of order, AccessCheckByTypeResultList fails and /// GetLastError returns ERROR_INVALID_PARAMETER. /// /// /// /// The number of elements in the ObjectTypeList array. This is also the number of elements in the arrays pointed to by the /// GrantedAccessList and AccessStatusList parameters. /// /// /// A pointer to the GENERIC_MAPPING structure associated with the object for which access is being checked. /// /// /// A pointer to a PRIVILEGE_SET structure that receives the privileges used to perform the access validation. If no privileges were /// used, the function sets the PrivilegeCount member to zero. /// /// The size, in bytes, of the buffer pointed to by the PrivilegeSet parameter. /// /// A pointer to an array of access masks. The function sets each access mask to indicate the access rights granted to the /// corresponding element in the object type list. If the function fails, it does not set the access masks. /// /// /// A pointer to an array of status codes for the corresponding elements in the object type list. The function sets an element to /// zero to indicate success or a nonzero value to indicate the specific error during the access check. If the function fails, it /// does not set any of the elements in the array. /// /// /// If the function succeeds, the function returns nonzero. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// /// /// For more information, see the How AccessCheck Works overview. /// /// The AccessCheckByTypeResultList function compares the specified security descriptor with the specified access token and /// indicates, in the AccessStatusList parameter, whether access is granted or denied for each of the elements in the object types list. /// /// /// The ObjectTypeList array does not necessarily represent the entire defined object. Rather, it represents that subset of the /// object for which to check access. For instance, to check access to two properties in a property set, specify an object type list /// with four elements: the object itself at level zero, the property set at level 1, and the two properties at level 2. /// /// /// The AccessCheckByTypeResultList function evaluates ACEs that apply to the object itself and object-specific ACEs for the /// object types listed in the ObjectTypeList array. The function ignores object-specific ACEs for object types not listed in the /// ObjectTypeList array. Thus, the results returned for element zero in the AccessStatusList parameter indicate the access allowed /// to the subset of the object defined by the ObjectTypeList parameter, not to the entire object. /// /// /// For more information about how a hierarchy of ACEs controls access to an object and its subobjects, see ACEs to Control Access to /// an Object's Properties. /// /// /// If the security descriptor's discretionary access control list (DACL) is NULL, the function grants the requested access to /// all of the elements in the object type list. /// /// If the security descriptor does not contain owner and group SIDs, AccessCheckByTypeResultList fails with ERROR_INVALID_SECURITY_DESCR. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-accesscheckbytyperesultlist BOOL // AccessCheckByTypeResultList( PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID PrincipalSelfSid, HANDLE ClientToken, DWORD // DesiredAccess, POBJECT_TYPE_LIST ObjectTypeList, DWORD ObjectTypeListLength, PGENERIC_MAPPING GenericMapping, PPRIVILEGE_SET // PrivilegeSet, LPDWORD PrivilegeSetLength, LPDWORD GrantedAccessList, LPDWORD AccessStatusList ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "ce713421-d4ff-48ed-b751-5e5c5397d820")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AccessCheckByTypeResultList(PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID PrincipalSelfSid, HTOKEN ClientToken, ACCESS_MASK DesiredAccess, [In] OBJECT_TYPE_LIST[] ObjectTypeList, uint ObjectTypeListLength, in GENERIC_MAPPING GenericMapping, [In, Out, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PRIVILEGE_SET.Marshaler))] PRIVILEGE_SET PrivilegeSet, ref uint PrivilegeSetLength, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5)] uint[] GrantedAccessList, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5)] uint[] AccessStatusList); /// /// /// The AddAccessAllowedAce function adds an access-allowed access control entry (ACE) to an access control list (ACL). The /// access is granted to a specified security identifier (SID). /// /// To control whether the new ACE can be inherited by child objects, use the AddAccessAllowedAceEx function. /// /// /// A pointer to an ACL. This function adds an access-allowed ACE to the end of this ACL. The ACE is in the form of an /// ACCESS_ALLOWED_ACE structure. /// /// /// Specifies the revision level of the ACL being modified. /// This value can be ACL_REVISION or ACL_REVISION_DS. Use ACL_REVISION_DS if the ACL contains object-specific ACEs. /// /// Specifies the mask of access rights to be granted to the specified SID. /// A pointer to the SID representing a user, group, or logon account being granted access. /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. The following are possible /// error values. /// /// /// /// Return code /// Description /// /// /// ERROR_ALLOTTED_SPACE_EXCEEDED /// The new ACE does not fit into the ACL. A larger ACL buffer is required. /// /// /// ERROR_INVALID_ACL /// The specified ACL is not properly formed. /// /// /// ERROR_INVALID_SID /// The specified SID is not structurally valid. /// /// /// ERROR_REVISION_MISMATCH /// The specified revision is not known or is incompatible with that of the ACL. /// /// /// ERROR_SUCCESS /// The ACE was successfully added. /// /// /// /// /// The addition of an access-allowed ACE to an ACL is the most common form of ACL modification. /// /// The AddAccessAllowedAce and AddAccessDeniedAce functions add a new ACE to the end of the list of ACEs for the ACL. These /// functions do not automatically place the new ACE in the proper canonical order. It is the caller's responsibility to ensure that /// the ACL is in canonical order by adding ACEs in the proper sequence. /// /// /// The ACE_HEADER structure placed in the ACE by the AddAccessAllowedAce function specifies a type and size, but provides no /// inheritance and no ACE flags. /// /// Examples /// For an example that uses this function, see Starting an Interactive Client Process. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-addaccessallowedace BOOL // AddAccessAllowedAce( PACL pAcl, DWORD dwAceRevision, DWORD AccessMask, PSID pSid ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "1004353a-f907-4452-9c0f-85eba0ece813")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AddAccessAllowedAce(PACL pAcl, uint dwAceRevision, ACCESS_MASK AccessMask, PSID pSid); /// /// The AddAccessAllowedAceEx function adds an access-allowed access control entry (ACE) to the end of a discretionary access /// control list (DACL). /// /// /// A pointer to a DACL. The AddAccessAllowedAceEx function adds an access-allowed ACE to the end of this DACL. The ACE is in /// the form of an ACCESS_ALLOWED_ACE structure. /// /// /// Specifies the revision level of the DACL being modified. This value can be ACL_REVISION or ACL_REVISION_DS. Use ACL_REVISION_DS /// if the DACL contains object-specific ACEs. /// /// /// /// A set of bit flags that control ACE inheritance. The function sets these flags in the AceFlags member of the ACE_HEADER /// structure of the new ACE. This parameter can be a combination of the following values. /// /// /// /// Value /// Meaning /// /// /// CONTAINER_INHERIT_ACE /// The ACE is inherited by container objects. /// /// /// INHERIT_ONLY_ACE /// /// The ACE does not apply to the object to which the access control list (ACL) is assigned, but it can be inherited by child objects. /// /// /// /// INHERITED_ACE /// /// Indicates an inherited ACE. This flag allows operations that change the security on a tree of objects to modify inherited ACEs /// while not changing ACEs that were directly applied to the object. /// /// /// /// NO_PROPAGATE_INHERIT_ACE /// The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE bits are not propagated to an inherited ACE. /// /// /// OBJECT_INHERIT_ACE /// The ACE is inherited by non-container objects. /// /// /// /// /// A set of bit flags that use the ACCESS_MASK format. These flags specify the access rights that the new ACE allows for the /// specified security identifier (SID). /// /// A pointer to a SID that identifies the user, group, or logon session to which the new ACE allows access. /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. The following are possible /// error values. /// /// /// /// Return code /// Description /// /// /// ERROR_ALLOTTED_SPACE_EXCEEDED /// The new ACE does not fit into the ACL. A larger ACL buffer is required. /// /// /// ERROR_INVALID_ACL /// The specified ACL is not properly formed. /// /// /// ERROR_INVALID_FLAGS /// The AceFlags parameter is not valid. /// /// /// ERROR_INVALID_SID /// The specified SID is not structurally valid. /// /// /// ERROR_REVISION_MISMATCH /// The specified revision is not known or is incompatible with that of the ACL. /// /// /// ERROR_SUCCESS /// The ACE was successfully added. /// /// /// /// /// The caller must ensure that ACEs are added to the DACL in the correct order. For more information, see Order of ACEs in a DACL. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-addaccessallowedaceex BOOL // AddAccessAllowedAceEx( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, PSID pSid ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "6ddec01f-237f-4b6a-8ea8-a126017b30c5")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AddAccessAllowedAceEx(PACL pAcl, uint dwAceRevision, AceFlags AceFlags, ACCESS_MASK AccessMask, PSID pSid); /// /// The AddAccessAllowedObjectAce function adds an access-allowed access control entry (ACE) to the end of a discretionary /// access control list (DACL). The new ACE can grant access to an object, or to a property set or property on an object. You can /// also use AddAccessAllowedObjectAce to add an ACE that only a specified type of child object can inherit. /// /// /// A pointer to a DACL. The AddAccessAllowedObjectAce function adds an access-allowed ACE to the end of this DACL. The ACE is /// in the form of an ACCESS_ALLOWED_OBJECT_ACE structure. /// /// /// Specifies the revision level of the DACL being modified. This value must be ACL_REVISION_DS. If the DACL's revision level is /// lower than ACL_REVISION_DS, the function changes it to ACL_REVISION_DS. /// /// /// /// A set of bit flags that control ACE inheritance. The function sets these flags in the AceFlags member of the ACE_HEADER /// structure of the new ACE. This parameter can be a combination of the following values. /// /// /// /// Value /// Meaning /// /// /// CONTAINER_INHERIT_ACE /// The ACE is inherited by container objects. /// /// /// INHERIT_ONLY_ACE /// /// The ACE does not apply to the object to which the access control list (ACL) is assigned, but it can be inherited by child objects. /// /// /// /// INHERITED_ACE /// /// Indicates an inherited ACE. This flag allows operations that change the security on a tree of objects to modify inherited ACEs, /// while not changing ACEs that were directly applied to the object. /// /// /// /// NO_PROPAGATE_INHERIT_ACE /// The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE bits are not propagated to an inherited ACE. /// /// /// OBJECT_INHERIT_ACE /// The ACE is inherited by non-container objects. /// /// /// /// /// A set of bit flags that use the ACCESS_MASK format. These flags specify the access rights that the new ACE allows for the /// specified security identifier (SID). /// /// /// A pointer to a GUID structure that identifies the type of object, property set, or property protected by the new ACE. If this /// parameter is NULL, the new ACE protects the object to which the DACL is assigned. /// /// /// A pointer to a GUID structure that identifies the type of object that can inherit the new ACE. If this parameter is non- /// NULL, only the specified object type can inherit the ACE. If NULL, any type of child object can inherit the ACE. In /// either case, inheritance is also controlled by the value of the AceFlags parameter, as well as by any protection against /// inheritance placed on the child objects. /// /// A pointer to a SID that identifies the user, group, or logon session to which the new ACE allows access. /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. The following are possible /// error values. /// /// /// /// Return code /// Description /// /// /// ERROR_ALLOTTED_SPACE_EXCEEDED /// The new ACE does not fit into the ACL. A larger ACL buffer is required. /// /// /// ERROR_INVALID_ACL /// The specified ACL is not properly formed. /// /// /// ERROR_INVALID_FLAGS /// The AceFlags parameter is not valid. /// /// /// ERROR_INVALID_SID /// The specified SID is not structurally valid. /// /// /// ERROR_REVISION_MISMATCH /// The specified revision is not known or is incompatible with that of the ACL. /// /// /// ERROR_SUCCESS /// The ACE was successfully added. /// /// /// /// /// /// If both ObjectTypeGuid and InheritedObjectTypeGuid are NULL, use the AddAccessAllowedAceEx function rather than /// AddAccessAllowedObjectAce. This is suggested because an ACCESS_ALLOWED_ACE is smaller and more efficient than an ACCESS_ALLOWED_OBJECT_ACE. /// /// /// The caller must ensure that ACEs are added to the DACL in the correct order. For more information, see Order of ACEs in a DACL. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-addaccessallowedobjectace BOOL // AddAccessAllowedObjectAce( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, GUID *ObjectTypeGuid, GUID // *InheritedObjectTypeGuid, PSID pSid ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "ccf83e95-ba6f-49f5-a312-52eac90f209a")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AddAccessAllowedObjectAce(PACL pAcl, uint dwAceRevision, AceFlags AceFlags, ACCESS_MASK AccessMask, in Guid ObjectTypeGuid, in Guid InheritedObjectTypeGuid, PSID pSid); /// /// The AddAccessAllowedObjectAce function adds an access-allowed access control entry (ACE) to the end of a discretionary /// access control list (DACL). The new ACE can grant access to an object, or to a property set or property on an object. You can /// also use AddAccessAllowedObjectAce to add an ACE that only a specified type of child object can inherit. /// /// /// A pointer to a DACL. The AddAccessAllowedObjectAce function adds an access-allowed ACE to the end of this DACL. The ACE is /// in the form of an ACCESS_ALLOWED_OBJECT_ACE structure. /// /// /// Specifies the revision level of the DACL being modified. This value must be ACL_REVISION_DS. If the DACL's revision level is /// lower than ACL_REVISION_DS, the function changes it to ACL_REVISION_DS. /// /// /// /// A set of bit flags that control ACE inheritance. The function sets these flags in the AceFlags member of the ACE_HEADER /// structure of the new ACE. This parameter can be a combination of the following values. /// /// /// /// Value /// Meaning /// /// /// CONTAINER_INHERIT_ACE /// The ACE is inherited by container objects. /// /// /// INHERIT_ONLY_ACE /// /// The ACE does not apply to the object to which the access control list (ACL) is assigned, but it can be inherited by child objects. /// /// /// /// INHERITED_ACE /// /// Indicates an inherited ACE. This flag allows operations that change the security on a tree of objects to modify inherited ACEs, /// while not changing ACEs that were directly applied to the object. /// /// /// /// NO_PROPAGATE_INHERIT_ACE /// The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE bits are not propagated to an inherited ACE. /// /// /// OBJECT_INHERIT_ACE /// The ACE is inherited by non-container objects. /// /// /// /// /// A set of bit flags that use the ACCESS_MASK format. These flags specify the access rights that the new ACE allows for the /// specified security identifier (SID). /// /// /// A pointer to a GUID structure that identifies the type of object, property set, or property protected by the new ACE. If this /// parameter is NULL, the new ACE protects the object to which the DACL is assigned. /// /// /// A pointer to a GUID structure that identifies the type of object that can inherit the new ACE. If this parameter is non- /// NULL, only the specified object type can inherit the ACE. If NULL, any type of child object can inherit the ACE. In /// either case, inheritance is also controlled by the value of the AceFlags parameter, as well as by any protection against /// inheritance placed on the child objects. /// /// A pointer to a SID that identifies the user, group, or logon session to which the new ACE allows access. /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. The following are possible /// error values. /// /// /// /// Return code /// Description /// /// /// ERROR_ALLOTTED_SPACE_EXCEEDED /// The new ACE does not fit into the ACL. A larger ACL buffer is required. /// /// /// ERROR_INVALID_ACL /// The specified ACL is not properly formed. /// /// /// ERROR_INVALID_FLAGS /// The AceFlags parameter is not valid. /// /// /// ERROR_INVALID_SID /// The specified SID is not structurally valid. /// /// /// ERROR_REVISION_MISMATCH /// The specified revision is not known or is incompatible with that of the ACL. /// /// /// ERROR_SUCCESS /// The ACE was successfully added. /// /// /// /// /// /// If both ObjectTypeGuid and InheritedObjectTypeGuid are NULL, use the AddAccessAllowedAceEx function rather than /// AddAccessAllowedObjectAce. This is suggested because an ACCESS_ALLOWED_ACE is smaller and more efficient than an ACCESS_ALLOWED_OBJECT_ACE. /// /// /// The caller must ensure that ACEs are added to the DACL in the correct order. For more information, see Order of ACEs in a DACL. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-addaccessallowedobjectace BOOL // AddAccessAllowedObjectAce( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, GUID *ObjectTypeGuid, GUID // *InheritedObjectTypeGuid, PSID pSid ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "ccf83e95-ba6f-49f5-a312-52eac90f209a")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AddAccessAllowedObjectAce(PACL pAcl, uint dwAceRevision, AceFlags AceFlags, ACCESS_MASK AccessMask, [Optional] IntPtr ObjectTypeGuid, [Optional] IntPtr InheritedObjectTypeGuid, PSID pSid); /// /// /// The AddAccessDeniedAce function adds an access-denied access control entry (ACE) to an access control list (ACL). The /// access is denied to a specified security identifier (SID). /// /// To control whether the new ACE can be inherited by child objects, use the AddAccessDeniedAceEx function. /// /// /// A pointer to an ACL . This function adds an access-denied ACE to the end of this ACL. The ACE is in the form of an /// ACCESS_DENIED_ACE structure. /// /// /// Specifies the revision level of the ACL being modified. /// This value can be ACL_REVISION or ACL_REVISION_DS. Use ACL_REVISION_DS if the ACL contains object-specific ACEs. /// /// Specifies the mask of access rights being denied to the specified SID. /// A pointer to the SID structure representing the user, group, or logon account being denied access. /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. The following are possible /// error values. /// /// /// /// Return code /// Description /// /// /// ERROR_ALLOTTED_SPACE_EXCEEDED /// The new ACE does not fit into the ACL. A larger ACL buffer is required. /// /// /// ERROR_INVALID_ACL /// The specified ACL is not properly formed. /// /// /// ERROR_INVALID_SID /// The specified SID is not structurally valid. /// /// /// ERROR_REVISION_MISMATCH /// The specified revision is not known or is incompatible with that of the ACL. /// /// /// ERROR_SUCCESS /// The ACE was successfully added. /// /// /// /// /// /// The AddAccessAllowedAce and AddAccessDeniedAce functions add a new ACE to the end of the list of ACEs for the ACL. These /// functions do not automatically place the new ACE in the proper canonical order. It is the caller's responsibility to ensure that /// the ACL is in canonical order by adding ACEs in the proper sequence. /// /// /// The ACE_HEADER structure placed in the ACE by the AddAccessDeniedAce function specifies a type and size, but provides no /// ACE flags. /// /// The ACE added by AddAccessDeniedAce is not inheritable. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-addaccessdeniedace BOOL // AddAccessDeniedAce( PACL pAcl, DWORD dwAceRevision, DWORD AccessMask, PSID pSid ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "5b4c4164-48f4-4cd5-b60e-554f2498d547")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AddAccessDeniedAce(PACL pAcl, uint dwAceRevision, ACCESS_MASK AccessMask, PSID pSid); /// /// The AddAccessDeniedAceEx function adds an access-denied access control entry (ACE) to the end of a discretionary access /// control list (DACL). /// /// /// A pointer to a DACL. The AddAccessDeniedAceEx function adds an access-denied ACE to the end of this DACL. The ACE is in /// the form of an ACCESS_DENIED_ACE structure. /// /// /// Specifies the revision level of the DACL being modified. This value can be ACL_REVISION or ACL_REVISION_DS. Use ACL_REVISION_DS /// if the DACL contains object-specific ACEs. /// /// /// /// A set of bit flags that control ACE inheritance. The function sets these flags in the AceFlags member of the ACE_HEADER /// structure of the new ACE. This parameter can be a combination of the following values. /// /// /// /// Value /// Meaning /// /// /// CONTAINER_INHERIT_ACE /// The ACE is inherited by container objects. /// /// /// INHERIT_ONLY_ACE /// /// The ACE does not apply to the object to which the access control list (ACL) is assigned, but it can be inherited by child objects. /// /// /// /// INHERITED_ACE /// /// Indicates an inherited ACE. This flag allows operations that change the security on a tree of objects to modify inherited ACEs, /// while not changing ACEs that were directly applied to the object. /// /// /// /// NO_PROPAGATE_INHERIT_ACE /// The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE bits are not propagated to an inherited ACE. /// /// /// OBJECT_INHERIT_ACE /// The ACE is inherited by non-container objects. /// /// /// /// /// A set of bit flags that use the ACCESS_MASK format to specify the access rights that the new ACE denies to the specified security /// identifier (SID). /// /// A pointer to a SID that identifies the user, group, or logon session to which the new ACE denies access. /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. The following are possible /// error values. /// /// /// /// Return code /// Description /// /// /// ERROR_ALLOTTED_SPACE_EXCEEDED /// The new ACE does not fit into the ACL. A larger ACL buffer is required. /// /// /// ERROR_INVALID_ACL /// The specified ACL is not properly formed. /// /// /// ERROR_INVALID_FLAGS /// The AceFlags parameter is not valid. /// /// /// ERROR_INVALID_SID /// The specified SID is not structurally valid. /// /// /// ERROR_REVISION_MISMATCH /// The specified revision is not known or is incompatible with that of the ACL. /// /// /// ERROR_SUCCESS /// The ACE was successfully added. /// /// /// /// /// Although the AddAccessDeniedAceEx function adds the new ACE to the end of the DACL, access-denied ACEs should appear at /// the beginning of a DACL. The caller must ensure that ACEs are added to the DACL in the correct order. For more information, see /// Order of ACEs in a DACL. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-addaccessdeniedaceex BOOL // AddAccessDeniedAceEx( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, PSID pSid ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "e353c88c-f82e-40c0-b676-38f0060acc81")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AddAccessDeniedAceEx(PACL pAcl, uint dwAceRevision, AceFlags AceFlags, ACCESS_MASK AccessMask, PSID pSid); /// /// The AddAccessDeniedObjectAce function adds an access-denied access control entry (ACE) to the end of a discretionary /// access control list (DACL). The new ACE can deny access to an object, or to a property set or property on an object. You can also /// use AddAccessDeniedObjectAce to add an ACE that only a specified type of child object can inherit. /// /// /// A pointer to a DACL. The AddAccessDeniedObjectAce function adds an access-denied ACE to the end of this DACL. The ACE is /// in the form of an ACCESS_DENIED_OBJECT_ACE structure. /// /// /// Specifies the revision level of the DACL being modified. This value must be ACL_REVISION_DS. If the DACL's revision level is /// lower than ACL_REVISION_DS, the function changes it to ACL_REVISION_DS. /// /// /// /// A set of bit flags that control ACE inheritance. The function sets these flags in the AceFlags member of the ACE_HEADER /// structure of the new ACE. This parameter can be a combination of the following values. /// /// /// /// Value /// Meaning /// /// /// CONTAINER_INHERIT_ACE /// The ACE is inherited by container objects. /// /// /// INHERIT_ONLY_ACE /// /// The ACE does not apply to the object to which the access control list (ACL) is assigned, but it can be inherited by child objects. /// /// /// /// INHERITED_ACE /// /// Indicates an inherited ACE. This flag allows operations that change the security on a tree of objects to modify inherited ACEs, /// while not changing ACEs that were directly applied to the object. /// /// /// /// NO_PROPAGATE_INHERIT_ACE /// The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE bits are not propagated to an inherited ACE. /// /// /// OBJECT_INHERIT_ACE /// The ACE is inherited by non-container objects. /// /// /// /// /// A set of bit flags that use the ACCESS_MASK format to specify the access rights that the new ACE denies to the specified security /// identifier (SID). /// /// /// A pointer to a GUID structure that identifies the type of object, property set, or property protected by the new ACE. If this /// parameter is NULL, the new ACE protects the object to which the ACL is assigned. /// /// /// A pointer to a GUID structure that identifies the type of object that can inherit the new ACE. If this parameter is non- /// NULL, only the specified object type can inherit the ACE. If NULL, any type of child object can inherit the ACE. In /// either case, inheritance is also controlled by the value of the AceFlags parameter, as well as by any protection against /// inheritance placed on the child objects. /// /// A pointer to a SID that identifies the user, group, or logon session to which the new ACE allows access. /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. The following are possible /// error values. /// /// /// /// Return code /// Description /// /// /// ERROR_ALLOTTED_SPACE_EXCEEDED /// The new ACE does not fit into the ACL. A larger ACL buffer is required. /// /// /// ERROR_INVALID_ACL /// The specified ACL is not properly formed. /// /// /// ERROR_INVALID_FLAGS /// The AceFlags parameter is not valid. /// /// /// ERROR_INVALID_SID /// The specified SID is not structurally valid. /// /// /// ERROR_REVISION_MISMATCH /// The specified revision is not known or is incompatible with that of the ACL. /// /// /// ERROR_SUCCESS /// The ACE was successfully added. /// /// /// /// /// /// If both ObjectTypeGuid and InheritedObjectTypeGuid are NULL, use the AddAccessDeniedAceEx function rather than /// AddAccessDeniedObjectAce. This is suggested because an ACCESS_DENIED_ACE is smaller and more efficient than an ACCESS_DENIED_OBJECT_ACE. /// /// /// Although the AddAccessDeniedObjectAce function adds the new ACE to the end of the ACL, access-denied ACEs should appear at /// the beginning of an ACL. The caller must ensure that ACEs are added to the DACL in the correct order. For more information, see /// Order of ACEs in a DACL. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-addaccessdeniedobjectace BOOL // AddAccessDeniedObjectAce( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, GUID *ObjectTypeGuid, GUID // *InheritedObjectTypeGuid, PSID pSid ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "1427c908-92b6-46b2-9189-a2fd93c470b1")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AddAccessDeniedObjectAce(PACL pAcl, uint dwAceRevision, AceFlags AceFlags, ACCESS_MASK AccessMask, in Guid ObjectTypeGuid, in Guid InheritedObjectTypeGuid, PSID pSid); /// /// The AddAccessDeniedObjectAce function adds an access-denied access control entry (ACE) to the end of a discretionary /// access control list (DACL). The new ACE can deny access to an object, or to a property set or property on an object. You can also /// use AddAccessDeniedObjectAce to add an ACE that only a specified type of child object can inherit. /// /// /// A pointer to a DACL. The AddAccessDeniedObjectAce function adds an access-denied ACE to the end of this DACL. The ACE is /// in the form of an ACCESS_DENIED_OBJECT_ACE structure. /// /// /// Specifies the revision level of the DACL being modified. This value must be ACL_REVISION_DS. If the DACL's revision level is /// lower than ACL_REVISION_DS, the function changes it to ACL_REVISION_DS. /// /// /// /// A set of bit flags that control ACE inheritance. The function sets these flags in the AceFlags member of the ACE_HEADER /// structure of the new ACE. This parameter can be a combination of the following values. /// /// /// /// Value /// Meaning /// /// /// CONTAINER_INHERIT_ACE /// The ACE is inherited by container objects. /// /// /// INHERIT_ONLY_ACE /// /// The ACE does not apply to the object to which the access control list (ACL) is assigned, but it can be inherited by child objects. /// /// /// /// INHERITED_ACE /// /// Indicates an inherited ACE. This flag allows operations that change the security on a tree of objects to modify inherited ACEs, /// while not changing ACEs that were directly applied to the object. /// /// /// /// NO_PROPAGATE_INHERIT_ACE /// The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE bits are not propagated to an inherited ACE. /// /// /// OBJECT_INHERIT_ACE /// The ACE is inherited by non-container objects. /// /// /// /// /// A set of bit flags that use the ACCESS_MASK format to specify the access rights that the new ACE denies to the specified security /// identifier (SID). /// /// /// A pointer to a GUID structure that identifies the type of object, property set, or property protected by the new ACE. If this /// parameter is NULL, the new ACE protects the object to which the ACL is assigned. /// /// /// A pointer to a GUID structure that identifies the type of object that can inherit the new ACE. If this parameter is non- /// NULL, only the specified object type can inherit the ACE. If NULL, any type of child object can inherit the ACE. In /// either case, inheritance is also controlled by the value of the AceFlags parameter, as well as by any protection against /// inheritance placed on the child objects. /// /// A pointer to a SID that identifies the user, group, or logon session to which the new ACE allows access. /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. The following are possible /// error values. /// /// /// /// Return code /// Description /// /// /// ERROR_ALLOTTED_SPACE_EXCEEDED /// The new ACE does not fit into the ACL. A larger ACL buffer is required. /// /// /// ERROR_INVALID_ACL /// The specified ACL is not properly formed. /// /// /// ERROR_INVALID_FLAGS /// The AceFlags parameter is not valid. /// /// /// ERROR_INVALID_SID /// The specified SID is not structurally valid. /// /// /// ERROR_REVISION_MISMATCH /// The specified revision is not known or is incompatible with that of the ACL. /// /// /// ERROR_SUCCESS /// The ACE was successfully added. /// /// /// /// /// /// If both ObjectTypeGuid and InheritedObjectTypeGuid are NULL, use the AddAccessDeniedAceEx function rather than /// AddAccessDeniedObjectAce. This is suggested because an ACCESS_DENIED_ACE is smaller and more efficient than an ACCESS_DENIED_OBJECT_ACE. /// /// /// Although the AddAccessDeniedObjectAce function adds the new ACE to the end of the ACL, access-denied ACEs should appear at /// the beginning of an ACL. The caller must ensure that ACEs are added to the DACL in the correct order. For more information, see /// Order of ACEs in a DACL. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-addaccessdeniedobjectace BOOL // AddAccessDeniedObjectAce( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, GUID *ObjectTypeGuid, GUID // *InheritedObjectTypeGuid, PSID pSid ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "1427c908-92b6-46b2-9189-a2fd93c470b1")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AddAccessDeniedObjectAce(PACL pAcl, uint dwAceRevision, AceFlags AceFlags, ACCESS_MASK AccessMask, [Optional] IntPtr ObjectTypeGuid, [Optional] IntPtr InheritedObjectTypeGuid, PSID pSid); /// The AddAce function adds one or more access control entries (ACEs) to a specified access control list (ACL). /// A pointer to an ACL. This function adds an ACE to this ACL. /// /// Specifies the revision level of the ACL being modified. /// /// This value can be ACL_REVISION or ACL_REVISION_DS. Use ACL_REVISION_DS if the ACL contains object-specific ACEs. This value must /// be compatible with the AceType field of all ACEs in pAceList. Otherwise, the function will fail and set the last error to ERROR_INVALID_PARAMETER. /// /// /// /// Specifies the position in the ACL's list of ACEs at which to add new ACEs. A value of zero inserts the ACEs at the beginning of /// the list. A value of MAXDWORD appends the ACEs to the end of the list. /// /// /// A pointer to a list of one or more ACEs to be added to the specified ACL. The ACEs in the list must be stored contiguously. /// /// Specifies the size, in bytes, of the input buffer pointed to by the pAceList parameter. /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. The following are possible /// error values. /// /// /// /// Return code /// Description /// /// /// ERROR_INSUFFICIENT_BUFFER /// The new ACE does not fit into the ACL. A larger ACL buffer is required. /// /// /// ERROR_INVALID_PARAMETER /// The specified ACL is not properly formed. /// /// /// ERROR_SUCCESS /// The ACE was successfully added. /// /// /// /// /// /// Applications frequently use the FindFirstFreeAce and GetAce functions when using the AddAce function to manipulate an ACL. /// In addition, the ACL_SIZE_INFORMATION structure retrieved by the GetAclInformation function contains the size of the ACL and the /// number of ACEs it contains. /// /// Examples /// For an example that uses this function, see Starting an Interactive Client Process. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-addace BOOL AddAce( PACL pAcl, DWORD // dwAceRevision, DWORD dwStartingAceIndex, LPVOID pAceList, DWORD nAceListLength ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "f472d864-a273-49b5-b5e2-98772989971e")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AddAce(PACL pAcl, uint dwAceRevision, uint dwStartingAceIndex, IntPtr pAceList, uint nAceListLength); /// /// /// The AddAuditAccessAce function adds a system-audit access control entry (ACE) to a system access control list (ACL). The /// access of a specified security identifier (SID) is audited. /// /// To control whether the new ACE can be inherited by child objects, use the AddAuditAccessAceEx function. /// /// /// A pointer to an ACL. This function adds a system-audit ACE to this ACL. The ACE is in the form of a SYSTEM_AUDIT_ACE structure. /// /// /// Specifies the revision level of the ACL being modified. /// This value can be ACL_REVISION or ACL_REVISION_DS. Use ACL_REVISION_DS if the ACL contains object-specific ACEs. /// /// Specifies the mask of access rights to be audited for the specified SID. /// A pointer to the SID representing the process whose access is being audited. /// /// Specifies whether successful access attempts are to be audited. Set this flag to TRUE to enable auditing; otherwise, set /// it to FALSE. /// /// /// Specifies whether unsuccessful access attempts are to be audited. Set this flag to TRUE to enable auditing; otherwise, set /// it to FALSE. /// /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. The following are possible /// error values. /// /// /// /// Return code /// Description /// /// /// ERROR_ALLOTTED_SPACE_EXCEEDED /// The new ACE does not fit into the ACL. A larger ACL buffer is required. /// /// /// ERROR_INVALID_ACL /// The specified ACL is not properly formed. /// /// /// ERROR_INVALID_SID /// The specified SID is not structurally valid. /// /// /// ERROR_REVISION_MISMATCH /// The specified revision is not known or is incompatible with that of the ACL. /// /// /// ERROR_SUCCESS /// The ACE was successfully added. /// /// /// /// /// The ACE_HEADER structure placed in the ACE by the AddAuditAccessAce function specifies a type and size, but provides no /// ACE flags. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-addauditaccessace BOOL AddAuditAccessAce( // PACL pAcl, DWORD dwAceRevision, DWORD dwAccessMask, PSID pSid, BOOL bAuditSuccess, BOOL bAuditFailure ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "34f22aea-9cde-411e-b2d5-bfcd3bfe325d")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AddAuditAccessAce(PACL pAcl, uint dwAceRevision, ACCESS_MASK dwAccessMask, PSID pSid, [MarshalAs(UnmanagedType.Bool)] bool bAuditSuccess, [MarshalAs(UnmanagedType.Bool)] bool bAuditFailure); /// /// The AddAuditAccessAceEx function adds a system-audit access control entry (ACE) to the end of a system access control list (SACL). /// /// /// A pointer to a SACL. The AddAuditAccessAceEx function adds a system-audit ACE to this SACL. The ACE is in the form of a /// SYSTEM_AUDIT_ACE structure. /// /// /// Specifies the revision level of the SACL being modified. This value can be ACL_REVISION or ACL_REVISION_DS. Use ACL_REVISION_DS /// if the SACL contains object-specific ACEs. /// /// /// /// A set of bit flags that control ACE inheritance and the type of access attempts to audit. The function sets these flags in the /// AceFlags member of the ACE_HEADER structure of the new ACE. This parameter can be a combination of the following values. /// /// /// /// Value /// Meaning /// /// /// CONTAINER_INHERIT_ACE /// The ACE is inherited by container objects. /// /// /// FAILED_ACCESS_ACE_FLAG /// /// If you set this flag or specify TRUE for the bAuditFailure parameter, failed attempts to use the specified access rights cause /// the system to generate an audit record in the security event log. /// /// /// /// INHERIT_ONLY_ACE /// /// The ACE does not apply to the object to which the access control list (ACL) is assigned, but it can be inherited by child objects. /// /// /// /// INHERITED_ACE /// /// Indicates an inherited ACE. This flag allows operations that change the security on a tree of objects to modify inherited ACEs, /// while not changing ACEs that were directly applied to the object. /// /// /// /// NO_PROPAGATE_INHERIT_ACE /// The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE bits are not propagated to an inherited ACE. /// /// /// OBJECT_INHERIT_ACE /// The ACE is inherited by non-container objects. /// /// /// SUCCESSFUL_ACCESS_ACE_FLAG /// /// If you set this flag or specify TRUE for the bAuditSuccess parameter, successful uses of the specified access rights cause the /// system to generate an audit record in the security event log. /// /// /// /// /// /// A set of bit flags that use the ACCESS_MASK format to specify the access rights that the new ACE audits for the specified /// security identifier (SID). /// /// A pointer to a SID that identifies the user, group, or logon session for which the new ACE audits access. /// /// Specifies whether successful uses of the specified access rights cause the system to generate an audit record in the security /// event log. If this flag is TRUE or if the AceFlags parameter specifies the SUCCESSFUL_ACCESS_ACE_FLAG flag, the system /// records successful access attempts; otherwise, it does not. /// /// /// Specifies whether failed attempts to use the specified access rights cause the system to generate an audit record in the security /// event log. If this flag is TRUE or if the AceFlags parameter specifies the FAILED_ACCESS_ACE_FLAG flag, the system records /// failed access attempts; otherwise, it does not. /// /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. The following are possible /// error values. /// /// /// /// Return code /// Description /// /// /// ERROR_ALLOTTED_SPACE_EXCEEDED /// The new ACE does not fit into the ACL. A larger ACL buffer is required. /// /// /// ERROR_INVALID_ACL /// The specified ACL is not properly formed. /// /// /// ERROR_INVALID_FLAGS /// The AceFlags parameter is not valid. /// /// /// ERROR_INVALID_SID /// The specified SID is not structurally valid. /// /// /// ERROR_REVISION_MISMATCH /// The specified revision is not known or is incompatible with that of the ACL. /// /// /// ERROR_SUCCESS /// The ACE was successfully added. /// /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-addauditaccessaceex BOOL // AddAuditAccessAceEx( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD dwAccessMask, PSID pSid, BOOL bAuditSuccess, BOOL // bAuditFailure ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "ddd1d815-c4ce-4572-982c-139e17cda192")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AddAuditAccessAceEx(PACL pAcl, uint dwAceRevision, AceFlags AceFlags, ACCESS_MASK dwAccessMask, PSID pSid, [MarshalAs(UnmanagedType.Bool)] bool bAuditSuccess, [MarshalAs(UnmanagedType.Bool)] bool bAuditFailure); /// /// The AddAuditAccessObjectAce function adds a system-audit access control entry (ACE) to the end of a system access control /// list (SACL). The new ACE can audit access to an object, or to a property set or property on an object. You can also use /// AddAuditAccessObjectAce to add an ACE that only a specified type of child object can inherit. /// /// /// A pointer to a SACL. The AddAuditAccessObjectAce function adds a system-audit ACE to the end of this SACL. The ACE is in /// the form of a SYSTEM_AUDIT_OBJECT_ACE structure. /// /// /// Specifies the revision level of the SACL being modified. This value must be ACL_REVISION_DS. If the SACL's revision level is /// lower than ACL_REVISION_DS, the function changes it to ACL_REVISION_DS. /// /// /// /// A set of bit flags that control ACE inheritance and the type of access attempts to audit. The function sets these flags in the /// AceFlags member of the ACE_HEADER structure of the new ACE. This parameter can be a combination of the following values. /// /// /// /// Value /// Meaning /// /// /// CONTAINER_INHERIT_ACE /// The ACE is inherited by container objects. /// /// /// FAILED_ACCESS_ACE_FLAG /// /// If you set this flag or specify TRUE for the bAuditFailure parameter, failed attempts to use the specified access rights cause /// the system to generate an audit record in the security event log. /// /// /// /// INHERIT_ONLY_ACE /// /// The ACE does not apply to the object to which the access control list (ACL) is assigned, but it can be inherited by child objects. /// /// /// /// INHERITED_ACE /// /// Indicates an inherited ACE. This flag allows operations that change the security on a tree of objects to modify inherited ACEs, /// while not changing ACEs that were directly applied to the object. /// /// /// /// NO_PROPAGATE_INHERIT_ACE /// The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE bits are not propagated to an inherited ACE. /// /// /// OBJECT_INHERIT_ACE /// The ACE is inherited by non-container objects. /// /// /// SUCCESSFUL_ACCESS_ACE_FLAG /// /// If you set this flag or specify TRUE for the bAuditSuccess parameter, successful uses of the specified access rights cause the /// system to generate an audit record in the security event log. /// /// /// /// /// /// An ACCESS_MASK that specifies the access rights that the new ACE audits for the specified security identifier (SID). /// /// /// A pointer to a GUID structure that identifies the type of object, property set, or property protected by the new ACE. If this /// parameter is NULL, the new ACE protects the object to which the ACL is assigned. /// /// /// A pointer to a GUID structure that identifies the type of object that can inherit the new ACE. If this parameter is non- /// NULL, only the specified object type can inherit the ACE. If NULL, any type of child object can inherit the ACE. In /// either case, inheritance is also controlled by the value of the AceFlags parameter, as well as by any protection against /// inheritance placed on the child objects. /// /// A pointer to a SID that identifies the user, group, or logon session for which the new ACE audits access. /// /// Specifies whether successful uses of the specified access rights cause the system to generate an audit record in the security /// event log. If this flag is TRUE or if the AceFlags parameter specifies the SUCCESSFUL_ACCESS_ACE_FLAG flag, the system /// records successful access attempts; otherwise, it does not. /// /// /// Specifies whether failed attempts to use the specified access rights cause the system to generate an audit record in the security /// event log. If this flag is TRUE or if the AceFlags parameter specifies the FAILED_ACCESS_ACE_FLAG flag, the system records /// failed access attempts; otherwise, it does not. /// /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. The following are possible /// error values. /// /// /// /// Return code /// Description /// /// /// ERROR_ALLOTTED_SPACE_EXCEEDED /// The new ACE does not fit into the ACL. A larger ACL buffer is required. /// /// /// ERROR_INVALID_ACL /// The specified ACL is not properly formed. /// /// /// ERROR_INVALID_FLAGS /// The AceFlags parameter is not valid. /// /// /// ERROR_INVALID_SID /// The specified SID is not structurally valid. /// /// /// ERROR_REVISION_MISMATCH /// The specified revision is not known or is incompatible with that of the ACL. /// /// /// ERROR_SUCCESS /// The ACE was successfully added. /// /// /// /// /// If both ObjectTypeGuid and InheritedObjectTypeGuid are NULL, use the AddAuditAccessAceEx function rather than /// AddAuditAccessObjectAce. This is suggested because a SYSTEM_AUDIT_ACE is smaller and more efficient than a SYSTEM_AUDIT_OBJECT_ACE. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-addauditaccessobjectace BOOL // AddAuditAccessObjectAce( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, GUID *ObjectTypeGuid, GUID // *InheritedObjectTypeGuid, PSID pSid, BOOL bAuditSuccess, BOOL bAuditFailure ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "be852a0c-9d96-4b29-b5f9-d9c41d838c12")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AddAuditAccessObjectAce(PACL pAcl, uint dwAceRevision, AceFlags AceFlags, ACCESS_MASK AccessMask, in Guid ObjectTypeGuid, in Guid InheritedObjectTypeGuid, PSID pSid, [MarshalAs(UnmanagedType.Bool)] bool bAuditSuccess, [MarshalAs(UnmanagedType.Bool)] bool bAuditFailure); /// /// The AddAuditAccessObjectAce function adds a system-audit access control entry (ACE) to the end of a system access control /// list (SACL). The new ACE can audit access to an object, or to a property set or property on an object. You can also use /// AddAuditAccessObjectAce to add an ACE that only a specified type of child object can inherit. /// /// /// A pointer to a SACL. The AddAuditAccessObjectAce function adds a system-audit ACE to the end of this SACL. The ACE is in /// the form of a SYSTEM_AUDIT_OBJECT_ACE structure. /// /// /// Specifies the revision level of the SACL being modified. This value must be ACL_REVISION_DS. If the SACL's revision level is /// lower than ACL_REVISION_DS, the function changes it to ACL_REVISION_DS. /// /// /// /// A set of bit flags that control ACE inheritance and the type of access attempts to audit. The function sets these flags in the /// AceFlags member of the ACE_HEADER structure of the new ACE. This parameter can be a combination of the following values. /// /// /// /// Value /// Meaning /// /// /// CONTAINER_INHERIT_ACE /// The ACE is inherited by container objects. /// /// /// FAILED_ACCESS_ACE_FLAG /// /// If you set this flag or specify TRUE for the bAuditFailure parameter, failed attempts to use the specified access rights cause /// the system to generate an audit record in the security event log. /// /// /// /// INHERIT_ONLY_ACE /// /// The ACE does not apply to the object to which the access control list (ACL) is assigned, but it can be inherited by child objects. /// /// /// /// INHERITED_ACE /// /// Indicates an inherited ACE. This flag allows operations that change the security on a tree of objects to modify inherited ACEs, /// while not changing ACEs that were directly applied to the object. /// /// /// /// NO_PROPAGATE_INHERIT_ACE /// The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE bits are not propagated to an inherited ACE. /// /// /// OBJECT_INHERIT_ACE /// The ACE is inherited by non-container objects. /// /// /// SUCCESSFUL_ACCESS_ACE_FLAG /// /// If you set this flag or specify TRUE for the bAuditSuccess parameter, successful uses of the specified access rights cause the /// system to generate an audit record in the security event log. /// /// /// /// /// /// An ACCESS_MASK that specifies the access rights that the new ACE audits for the specified security identifier (SID). /// /// /// A pointer to a GUID structure that identifies the type of object, property set, or property protected by the new ACE. If this /// parameter is NULL, the new ACE protects the object to which the ACL is assigned. /// /// /// A pointer to a GUID structure that identifies the type of object that can inherit the new ACE. If this parameter is non- /// NULL, only the specified object type can inherit the ACE. If NULL, any type of child object can inherit the ACE. In /// either case, inheritance is also controlled by the value of the AceFlags parameter, as well as by any protection against /// inheritance placed on the child objects. /// /// A pointer to a SID that identifies the user, group, or logon session for which the new ACE audits access. /// /// Specifies whether successful uses of the specified access rights cause the system to generate an audit record in the security /// event log. If this flag is TRUE or if the AceFlags parameter specifies the SUCCESSFUL_ACCESS_ACE_FLAG flag, the system /// records successful access attempts; otherwise, it does not. /// /// /// Specifies whether failed attempts to use the specified access rights cause the system to generate an audit record in the security /// event log. If this flag is TRUE or if the AceFlags parameter specifies the FAILED_ACCESS_ACE_FLAG flag, the system records /// failed access attempts; otherwise, it does not. /// /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. The following are possible /// error values. /// /// /// /// Return code /// Description /// /// /// ERROR_ALLOTTED_SPACE_EXCEEDED /// The new ACE does not fit into the ACL. A larger ACL buffer is required. /// /// /// ERROR_INVALID_ACL /// The specified ACL is not properly formed. /// /// /// ERROR_INVALID_FLAGS /// The AceFlags parameter is not valid. /// /// /// ERROR_INVALID_SID /// The specified SID is not structurally valid. /// /// /// ERROR_REVISION_MISMATCH /// The specified revision is not known or is incompatible with that of the ACL. /// /// /// ERROR_SUCCESS /// The ACE was successfully added. /// /// /// /// /// If both ObjectTypeGuid and InheritedObjectTypeGuid are NULL, use the AddAuditAccessAceEx function rather than /// AddAuditAccessObjectAce. This is suggested because a SYSTEM_AUDIT_ACE is smaller and more efficient than a SYSTEM_AUDIT_OBJECT_ACE. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-addauditaccessobjectace BOOL // AddAuditAccessObjectAce( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, GUID *ObjectTypeGuid, GUID // *InheritedObjectTypeGuid, PSID pSid, BOOL bAuditSuccess, BOOL bAuditFailure ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "be852a0c-9d96-4b29-b5f9-d9c41d838c12")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AddAuditAccessObjectAce(PACL pAcl, uint dwAceRevision, AceFlags AceFlags, ACCESS_MASK AccessMask, [Optional] IntPtr ObjectTypeGuid, [Optional] IntPtr InheritedObjectTypeGuid, PSID pSid, [MarshalAs(UnmanagedType.Bool)] bool bAuditSuccess, [MarshalAs(UnmanagedType.Bool)] bool bAuditFailure); /// /// The AddMandatoryAce function adds a SYSTEM_MANDATORY_LABEL_ACE access control entry (ACE) to the specified system access /// control list (SACL). /// /// /// A pointer to an SACL. This function adds a mandatory ACE to the end of this SACL. The ACE is in the form of a /// SYSTEM_MANDATORY_LABEL_ACE structure. /// /// /// The revision level of the SACL being modified. This value can be one of the following values. /// /// /// Value /// Meaning /// /// /// ACL_REVISION /// The SACL does not contain object-specific ACEs. /// /// /// ACL_REVISION_DS /// The SACL contains object-specified ACEs. /// /// /// /// /// /// A set of bit flags that control ACE inheritance. This function sets these flags in the AceFlags member of the ACE_HEADER /// structure of the new ACE. /// /// This parameter can be a combination of the following values. /// /// /// Value /// Meaning /// /// /// OBJECT_INHERIT_ACE 0x1 /// The ACE is inherited by non-container objects. /// /// /// CONTAINER_INHERIT_ACE 0x2 /// The ACE is inherited by container objects. /// /// /// NO_PROPAGATE_INHERIT_ACE 0x4 /// The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE bits are not propagated to an inherited ACE. /// /// /// INHERIT_ONLY_ACE 0x8 /// The ACE does not apply to the object to which the SACL is assigned, but the ACE can be inherited by child objects. /// /// /// INHERITED_ACE 0x10 /// /// The ACE is inherited. Operations that change the security on a tree of objects may modify inherited ACEs without changing ACEs /// that were directly applied to the object. /// /// /// /// /// /// /// The access policy for principals with a mandatory integrity level lower than the object associated with the SACL that contains /// this ACE. /// /// /// /// Value /// Meaning /// /// /// SYSTEM_MANDATORY_LABEL_NO_WRITE_UP 0x1 /// A principal with a lower mandatory level than the object cannot write to the object. /// /// /// SYSTEM_MANDATORY_LABEL_NO_READ_UP 0x2 /// A principal with a lower mandatory level than the object cannot read the object. /// /// /// SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP 0x4 /// A principal with a lower mandatory level than the object cannot execute the object. /// /// /// /// /// A pointer to an SID that specifies the mandatory integrity level of the object associated with the SACL being appended. /// /// /// If the function succeeds, it returns TRUE. /// /// If the function fails, it returns FALSE. For extended error information, call GetLastError. The following are possible /// error values. /// /// /// /// Return code/value /// Description /// /// /// ERROR_ALLOTTED_SPACE_EXCEEDED 0x540 /// The new ACE does not fit into the pAcl buffer. /// /// /// /// /// To compile an application that uses this function, define _WIN32_WINNT as 0x0600 or later. For more information, see Using the /// Windows Headers. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-addmandatoryace BOOL AddMandatoryAce( PACL // pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD MandatoryPolicy, PSID pLabelSid ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "22c8f384-fdb7-4d5a-8854-d9fd25cd351e")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AddMandatoryAce(PACL pAcl, uint dwAceRevision, AceFlags AceFlags, SYSTEM_MANDATORY_LABEL MandatoryPolicy, PSID pLabelSid); /// /// The AddResourceAttributeAce function adds a SYSTEM_RESOURCE_ATTRIBUTE_ACE access control entry (ACE) to the end of a /// system access control list (SACL). A SYSTEM_RESOURCE_ATTRIBUTE_ACE structure specifies an attribute name and a /// value-ordered list of elements that is associated with a resource and potentially used during access checks. The set of standard /// access rights are defined in the Standard Access Rights topic. /// /// /// A pointer to an access control list (ACL). This function adds an ACE to this ACL. The value of this parameter cannot be /// NULL. The ACE is in the form of a SYSTEM_RESOURCE_ATTRIBUTE_ACE structure. /// /// /// Specifies the revision level of the ACL being modified. This value can be ACL_REVISION or ACL_REVISION_DS. Use ACL_REVISION_DS if /// the ACL contains object-specific ACEs. /// /// /// /// A set of bit flags that control ACE inheritance. The function sets these flags in the AceFlags member of the ACE_HEADER /// structure of the new ACE. /// /// /// For consistency with the Windows 8 Advanced File Permissions UI, applications should specify the CONTAINER_INHERIT_ACE and /// OBJECT_INHERIT_ACE flags in the AceFlags parameter. /// /// This parameter can be a combination of the following values. /// /// /// Value /// Meaning /// /// /// CONTAINER_INHERIT_ACE 2 (0x2) /// The ACE is inherited by the container objects. /// /// /// INHERIT_ONLY_ACE 8 (0x8) /// The ACE does not apply to the object the ACE is assigned to, but it can be inherited by child objects. /// /// /// INHERITED_ACE 16 (0x10) /// /// Indicates an inherited ACE. This flag allows operations that change the security on a tree of objects to modify inherited ACEs /// while not changing ACEs that were directly applied to the object. /// /// /// /// NO_PROPAGATE_INHERIT_ACE 4 (0x4) /// The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE bits are not propagated to an inherited ACE. /// /// /// OBJECT_INHERIT_ACE 1 (0x1) /// The ACE is inherited by non-container objects. /// /// /// /// Must be zero for Windows 8 and Windows Server 2012. /// Must be the Everyone SID (S-1-1-0) for Windows 8 and Windows Server 2012. /// Specifies the attribute information that will be appended after the SID in the ACE. /// /// The size, in bytes, of the actual ACL buffer used. If the buffer specified by the pAcl parameter is not big enough, the value of /// this parameter is the total size required for the ACL buffer. /// /// /// If the function succeeds, it returns TRUE. /// If the function fails, it returns FALSE. To get extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-addresourceattributeace BOOL // AddResourceAttributeAce( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, PSID pSid, // PCLAIM_SECURITY_ATTRIBUTES_INFORMATION pAttributeInfo, PDWORD pReturnLength ); [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "AA2064E4-6F76-4D7B-8540-D55A91168825")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AddResourceAttributeAce(PACL pAcl, uint dwAceRevision, AceFlags AceFlags, ACCESS_MASK AccessMask, PSID pSid, in CLAIM_SECURITY_ATTRIBUTES_INFORMATION pAttributeInfo, ref uint pReturnLength); /// /// The AddScopedPolicyIDAce function adds a SYSTEM_SCOPED_POLICY_ID_ACE access control entry (ACE) to the end of a system /// access control list (SACL). A SYSTEM_SCOPED_POLICY_ID_ACE structure specifies a central access policy (CAP) to be /// associated with the resource and can be used during access checks. The set of standard access rights are defined in the Standard /// Access Rights topic. /// /// /// A pointer to an access control list (ACL). This function adds an ACE to this ACL. The value of this parameter cannot be NULL. /// /// /// Specifies the revision level of the ACL being modified. This value can be ACL_REVISION or ACL_REVISION_DS. Use ACL_REVISION_DS if /// the ACL contains object-specific ACEs. /// /// /// /// A set of bit flags that control ACE inheritance. The function sets these flags in the AceFlags member of the ACE_HEADER /// structure of the new ACE. /// /// /// For consistency with the Windows 8 Advanced File Permissions UI, applications should specify the CONTAINER_INHERIT_ACE and /// OBJECT_INHERIT_ACE flags in the AceFlags parameter. /// /// This parameter can be a combination of the following values. /// /// /// Value /// Meaning /// /// /// CONTAINER_INHERIT_ACE 2 (0x2) /// The ACE is inherited by the container objects. /// /// /// INHERIT_ONLY_ACE 8 (0x8) /// The ACE does not apply to the object the ACE is assigned to, but it can be inherited by child objects. /// /// /// INHERITED_ACE 16 (0x10) /// /// Indicates an inherited ACE. This flag allows operations that change the security on a tree of objects to modify inherited ACEs /// while not changing ACEs that were directly applied to the object. /// /// /// /// NO_PROPAGATE_INHERIT_ACE 4 (0x4) /// The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE bits are not propagated to an inherited ACE. /// /// /// OBJECT_INHERIT_ACE 1 (0x1) /// The ACE is inherited by non-container objects. /// /// /// /// Must be zero for Windows 8 and Windows Server 2012. /// A pointer to the SID (S-1-17-*) that identifies the Central Access Policy to be associated with the resource. /// /// If the function succeeds, it returns TRUE. /// If the function fails, it returns FALSE. To get extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-addscopedpolicyidace BOOL // AddScopedPolicyIDAce( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, PSID pSid ); [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "30AA5730-566C-4B02-A904-5A38237EE8E3")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AddScopedPolicyIDAce(PACL pAcl, uint dwAceRevision, AceFlags AceFlags, ACCESS_MASK AccessMask, PSID pSid); /// /// The AdjustTokenGroups function enables or disables groups already present in the specified access token. Access to /// TOKEN_ADJUST_GROUPS is required to enable or disable groups in an access token. /// /// /// A handle to the access token that contains the groups to be enabled or disabled. The handle must have TOKEN_ADJUST_GROUPS access /// to the token. If the PreviousState parameter is not NULL, the handle must also have TOKEN_QUERY access. /// /// /// Boolean value that indicates whether the groups are to be set to their default enabled and disabled states. If this value is /// TRUE, the groups are set to their default states and the NewState parameter is ignored. If this value is FALSE, the /// groups are set according to the information pointed to by the NewState parameter. /// /// /// A pointer to a TOKEN_GROUPS structure that contains the groups to be enabled or disabled. If the ResetToDefault parameter is /// FALSE, the function sets each of the groups to the value of that group's SE_GROUP_ENABLED attribute in the /// TOKEN_GROUPS structure. If ResetToDefault is TRUE, this parameter is ignored. /// /// /// On return, a TOKEN_GROUPS structure containing the previous state of any groups the function modifies. That is, if a group has /// been modified by this function, the group and its previous state are contained in the TOKEN_GROUPS structure referenced by /// PreviousState. If the GroupCount member of TOKEN_GROUPS is zero, then no groups have been changed by this function. /// /// If the function succeeds, the return value is ERROR_SUCCESS; other it is extended error information. /// /// /// The information retrieved in the PreviousState parameter is formatted as a TOKEN_GROUPS structure. This means a pointer to the /// buffer can be passed as the NewState parameter in a subsequent call to the AdjustTokenGroups function, restoring the /// original state of the groups. /// /// /// The NewState parameter can list groups to be changed that are not present in the access token. This does not affect the /// successful modification of the groups in the token. /// /// /// The AdjustTokenGroups function cannot disable groups with the SE_GROUP_MANDATORY attribute in the TOKEN_GROUPS structure. /// Use CreateRestrictedToken instead. /// /// You cannot enable a group that has the SE_GROUP_USE_FOR_DENY_ONLY attribute. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-adjusttokengroups BOOL AdjustTokenGroups( // HANDLE TokenHandle, BOOL ResetToDefault, PTOKEN_GROUPS NewState, DWORD BufferLength, PTOKEN_GROUPS PreviousState, PDWORD // ReturnLength ); [PInvokeData("securitybaseapi.h", MSDNShortId = "839c4b58-4c61-4f72-8337-1e3dfa267ee5")] public static Win32Error AdjustTokenGroups(HTOKEN TokenHandle, bool ResetToDefault, in TOKEN_GROUPS NewState, out TOKEN_GROUPS PreviousState) { using var ns = new SafeAnysizeStruct(NewState); using var dummy = new SafeHGlobalHandle(1); return CallMethodWithTypedBuf((ref uint sz) => { var err = BoolToLastErr(AdjustTokenGroups(TokenHandle, ResetToDefault, ns, dummy.Size, dummy, out sz)); sz += 4; return err; }, (IntPtr ptr, ref uint sz) => BoolToLastErr(AdjustTokenGroups(TokenHandle, ResetToDefault, ns, sz, ptr, out _)), out PreviousState); } /// /// The AdjustTokenGroups function enables or disables groups already present in the specified access token. Access to /// TOKEN_ADJUST_GROUPS is required to enable or disable groups in an access token. /// /// /// A handle to the access token that contains the groups to be enabled or disabled. The handle must have TOKEN_ADJUST_GROUPS access /// to the token. If the PreviousState parameter is not NULL, the handle must also have TOKEN_QUERY access. /// /// /// Boolean value that indicates whether the groups are to be set to their default enabled and disabled states. If this value is /// TRUE, the groups are set to their default states and the NewState parameter is ignored. If this value is FALSE, the /// groups are set according to the information pointed to by the NewState parameter. /// /// /// A pointer to a TOKEN_GROUPS structure that contains the groups to be enabled or disabled. If the ResetToDefault parameter is /// FALSE, the function sets each of the groups to the value of that group's SE_GROUP_ENABLED attribute in the /// TOKEN_GROUPS structure. If ResetToDefault is TRUE, this parameter is ignored. /// /// /// The size, in bytes, of the buffer pointed to by the PreviousState parameter. This parameter can be zero if the PreviousState /// parameter is NULL. /// /// /// /// A pointer to a buffer that receives a TOKEN_GROUPS structure containing the previous state of any groups the function modifies. /// That is, if a group has been modified by this function, the group and its previous state are contained in the TOKEN_GROUPS /// structure referenced by PreviousState. If the GroupCount member of TOKEN_GROUPS is zero, then no groups have been /// changed by this function. This parameter can be NULL. /// /// /// If a buffer is specified but it does not contain enough space to receive the complete list of modified groups, no group states /// are changed and the function fails. In this case, the function sets the variable pointed to by the ReturnLength parameter to the /// number of bytes required to hold the complete list of modified groups. /// /// /// /// A pointer to a variable that receives the actual number of bytes needed for the buffer pointed to by the PreviousState parameter. /// This parameter can be NULL and is ignored if PreviousState is NULL. /// /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// /// /// /// The information retrieved in the PreviousState parameter is formatted as a TOKEN_GROUPS structure. This means a pointer to the /// buffer can be passed as the NewState parameter in a subsequent call to the AdjustTokenGroups function, restoring the /// original state of the groups. /// /// /// The NewState parameter can list groups to be changed that are not present in the access token. This does not affect the /// successful modification of the groups in the token. /// /// /// The AdjustTokenGroups function cannot disable groups with the SE_GROUP_MANDATORY attribute in the TOKEN_GROUPS structure. /// Use CreateRestrictedToken instead. /// /// You cannot enable a group that has the SE_GROUP_USE_FOR_DENY_ONLY attribute. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-adjusttokengroups BOOL AdjustTokenGroups( // HANDLE TokenHandle, BOOL ResetToDefault, PTOKEN_GROUPS NewState, DWORD BufferLength, PTOKEN_GROUPS PreviousState, PDWORD // ReturnLength ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "839c4b58-4c61-4f72-8337-1e3dfa267ee5")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AdjustTokenGroups(HTOKEN TokenHandle, [MarshalAs(UnmanagedType.Bool)] bool ResetToDefault, [In] IntPtr NewState, [In, Optional] uint BufferLength, [In, Out, Optional] IntPtr PreviousState, out uint ReturnLength); /// /// The AdjustTokenPrivileges function enables or disables privileges in the specified access token. Enabling or disabling /// privileges in an access token requires TOKEN_ADJUST_PRIVILEGES access. /// /// /// A handle to the access token that contains the privileges to be modified. The handle must have TOKEN_ADJUST_PRIVILEGES access to /// the token. If the PreviousState parameter is not NULL, the handle must also have TOKEN_QUERY access. /// /// /// Specifies whether the function disables all of the token's privileges. If this value is TRUE, the function disables all /// privileges and ignores the NewState parameter. If it is FALSE, the function modifies privileges based on the information /// pointed to by the NewState parameter. /// /// /// /// A pointer to a TOKEN_PRIVILEGES structure that specifies an array of privileges and their attributes. If the DisableAllPrivileges /// parameter is FALSE, the AdjustTokenPrivileges function enables, disables, or removes these privileges for the /// token. The following table describes the action taken by the AdjustTokenPrivileges function, based on the privilege attribute. /// /// /// /// Value /// Meaning /// /// /// SE_PRIVILEGE_ENABLED /// The function enables the privilege. /// /// /// SE_PRIVILEGE_REMOVED /// /// The privilege is removed from the list of privileges in the token. The other privileges in the list are reordered to remain /// contiguous. SE_PRIVILEGE_REMOVED supersedes SE_PRIVILEGE_ENABLED. Because the privilege has been removed from the token, attempts /// to reenable the privilege result in the warning ERROR_NOT_ALL_ASSIGNED as if the privilege had never existed. Attempting to /// remove a privilege that does not exist in the token results in ERROR_NOT_ALL_ASSIGNED being returned. Privilege checks for /// removed privileges result in STATUS_PRIVILEGE_NOT_HELD. Failed privilege check auditing occurs as normal. The removal of the /// privilege is irreversible, so the name of the removed privilege is not included in the PreviousState parameter after a call to /// AdjustTokenPrivileges. Windows XP with SP1: The function cannot remove privileges. This value is not supported. /// /// /// /// None /// The function disables the privilege. /// /// /// If DisableAllPrivileges is TRUE, the function ignores this parameter. /// /// /// On return, a TOKEN_PRIVILEGES structure that contains the previous state of any privileges that the function modifies. That is, /// if a privilege has been modified by this function, the privilege and its previous state are contained in the /// TOKEN_PRIVILEGES structure referenced by PreviousState. If the PrivilegeCount member of TOKEN_PRIVILEGES is /// zero, then no privileges have been changed by this function. /// /// /// The return value is one of the following values when the function succeeds: /// /// /// Return code /// Description /// /// /// ERROR_SUCCESS /// The function adjusted all specified privileges. /// /// /// ERROR_NOT_ALL_ASSIGNED /// /// The token does not have one or more of the privileges specified in the NewState parameter. The function may succeed with this /// error value even if no privileges were adjusted. The PreviousState parameter indicates the privileges that were adjusted. /// /// /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// /// /// /// The AdjustTokenPrivileges function cannot add new privileges to the access token. It can only enable or disable the /// token's existing privileges. To determine the token's privileges, call the GetTokenInformation function. /// /// /// The NewState parameter can specify privileges that the token does not have, without causing the function to fail. In this case, /// the function adjusts the privileges that the token does have and ignores the other privileges so that the function succeeds. Call /// the GetLastError function to determine whether the function adjusted all of the specified privileges. The PreviousState parameter /// indicates the privileges that were adjusted. /// /// /// The PreviousState parameter retrieves a TOKEN_PRIVILEGES structure that contains the original state of the adjusted privileges. /// To restore the original state, pass the PreviousState pointer as the NewState parameter in a subsequent call to the /// AdjustTokenPrivileges function. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-adjusttokenprivileges BOOL // AdjustTokenPrivileges( HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, // PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength ); [PInvokeData("securitybaseapi.h", MSDNShortId = "8e3f70cd-814e-4aab-8f48-0ca482beef2e")] public static Win32Error AdjustTokenPrivileges(HTOKEN TokenHandle, bool DisableAllPrivileges, in TOKEN_PRIVILEGES NewState, out TOKEN_PRIVILEGES PreviousState) { using var ns = new SafeAnysizeStruct(NewState); using var dummy = new SafeHGlobalHandle(1); return CallMethodWithTypedBuf((ref uint sz) => BoolToLastErr(AdjustTokenPrivileges(TokenHandle, DisableAllPrivileges, ns, dummy.Size, dummy, out sz)), (IntPtr ptr, ref uint sz) => BoolToLastErr(AdjustTokenPrivileges(TokenHandle, DisableAllPrivileges, ns, sz, ptr, out _)), out PreviousState); } /// /// The AdjustTokenPrivileges function enables or disables privileges in the specified access token. Enabling or disabling /// privileges in an access token requires TOKEN_ADJUST_PRIVILEGES access. /// /// /// A handle to the access token that contains the privileges to be modified. The handle must have TOKEN_ADJUST_PRIVILEGES access to /// the token. If the PreviousState parameter is not NULL, the handle must also have TOKEN_QUERY access. /// /// /// Specifies whether the function disables all of the token's privileges. If this value is TRUE, the function disables all /// privileges and ignores the NewState parameter. If it is FALSE, the function modifies privileges based on the information /// pointed to by the NewState parameter. /// /// /// /// A pointer to a TOKEN_PRIVILEGES structure that specifies an array of privileges and their attributes. If the DisableAllPrivileges /// parameter is FALSE, the AdjustTokenPrivileges function enables, disables, or removes these privileges for the /// token. The following table describes the action taken by the AdjustTokenPrivileges function, based on the privilege attribute. /// /// /// /// Value /// Meaning /// /// /// SE_PRIVILEGE_ENABLED /// The function enables the privilege. /// /// /// SE_PRIVILEGE_REMOVED /// /// The privilege is removed from the list of privileges in the token. The other privileges in the list are reordered to remain /// contiguous. SE_PRIVILEGE_REMOVED supersedes SE_PRIVILEGE_ENABLED. Because the privilege has been removed from the token, attempts /// to reenable the privilege result in the warning ERROR_NOT_ALL_ASSIGNED as if the privilege had never existed. Attempting to /// remove a privilege that does not exist in the token results in ERROR_NOT_ALL_ASSIGNED being returned. Privilege checks for /// removed privileges result in STATUS_PRIVILEGE_NOT_HELD. Failed privilege check auditing occurs as normal. The removal of the /// privilege is irreversible, so the name of the removed privilege is not included in the PreviousState parameter after a call to /// AdjustTokenPrivileges. Windows XP with SP1: The function cannot remove privileges. This value is not supported. /// /// /// /// None /// The function disables the privilege. /// /// /// If DisableAllPrivileges is TRUE, the function ignores this parameter. /// /// /// Specifies the size, in bytes, of the buffer pointed to by the PreviousState parameter. This parameter can be zero if the /// PreviousState parameter is NULL. /// /// /// /// A pointer to a buffer that the function fills with a TOKEN_PRIVILEGES structure that contains the previous state of any /// privileges that the function modifies. That is, if a privilege has been modified by this function, the privilege and its previous /// state are contained in the TOKEN_PRIVILEGES structure referenced by PreviousState. If the PrivilegeCount member of /// TOKEN_PRIVILEGES is zero, then no privileges have been changed by this function. This parameter can be NULL. /// /// /// If you specify a buffer that is too small to receive the complete list of modified privileges, the function fails and does not /// adjust any privileges. In this case, the function sets the variable pointed to by the ReturnLength parameter to the number of /// bytes required to hold the complete list of modified privileges. /// /// /// /// A pointer to a variable that receives the required size, in bytes, of the buffer pointed to by the PreviousState parameter. This /// parameter can be NULL if PreviousState is NULL. /// /// /// /// If the function succeeds, the return value is nonzero. To determine whether the function adjusted all of the specified /// privileges, call GetLastError, which returns one of the following values when the function succeeds: /// /// /// /// Return code /// Description /// /// /// ERROR_SUCCESS /// The function adjusted all specified privileges. /// /// /// ERROR_NOT_ALL_ASSIGNED /// /// The token does not have one or more of the privileges specified in the NewState parameter. The function may succeed with this /// error value even if no privileges were adjusted. The PreviousState parameter indicates the privileges that were adjusted. /// /// /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// /// /// /// The AdjustTokenPrivileges function cannot add new privileges to the access token. It can only enable or disable the /// token's existing privileges. To determine the token's privileges, call the GetTokenInformation function. /// /// /// The NewState parameter can specify privileges that the token does not have, without causing the function to fail. In this case, /// the function adjusts the privileges that the token does have and ignores the other privileges so that the function succeeds. Call /// the GetLastError function to determine whether the function adjusted all of the specified privileges. The PreviousState parameter /// indicates the privileges that were adjusted. /// /// /// The PreviousState parameter retrieves a TOKEN_PRIVILEGES structure that contains the original state of the adjusted privileges. /// To restore the original state, pass the PreviousState pointer as the NewState parameter in a subsequent call to the /// AdjustTokenPrivileges function. /// /// Examples /// For an example that uses this function, see Enabling and Disabling Privileges. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-adjusttokenprivileges BOOL // AdjustTokenPrivileges( HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, // PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "8e3f70cd-814e-4aab-8f48-0ca482beef2e")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AdjustTokenPrivileges([In] HTOKEN TokenHandle, [In, MarshalAs(UnmanagedType.Bool)] bool DisableAllPrivileges, [In] IntPtr NewState, [In, Optional] uint BufferLength, [In, Out, Optional] IntPtr PreviousState, out uint ReturnLength); /// /// The AdjustTokenPrivileges function enables or disables privileges in the specified access token. Enabling or disabling /// privileges in an access token requires TOKEN_ADJUST_PRIVILEGES access. /// /// /// A handle to the access token that contains the privileges to be modified. The handle must have TOKEN_ADJUST_PRIVILEGES access to /// the token. If the PreviousState parameter is not NULL, the handle must also have TOKEN_QUERY access. /// /// /// Specifies whether the function disables all of the token's privileges. If this value is TRUE, the function disables all /// privileges and ignores the NewState parameter. If it is FALSE, the function modifies privileges based on the information /// pointed to by the NewState parameter. /// /// /// /// A pointer to a TOKEN_PRIVILEGES structure that specifies an array of privileges and their attributes. If the DisableAllPrivileges /// parameter is FALSE, the AdjustTokenPrivileges function enables, disables, or removes these privileges for the /// token. The following table describes the action taken by the AdjustTokenPrivileges function, based on the privilege attribute. /// /// /// /// Value /// Meaning /// /// /// SE_PRIVILEGE_ENABLED /// The function enables the privilege. /// /// /// SE_PRIVILEGE_REMOVED /// /// The privilege is removed from the list of privileges in the token. The other privileges in the list are reordered to remain /// contiguous. SE_PRIVILEGE_REMOVED supersedes SE_PRIVILEGE_ENABLED. Because the privilege has been removed from the token, attempts /// to reenable the privilege result in the warning ERROR_NOT_ALL_ASSIGNED as if the privilege had never existed. Attempting to /// remove a privilege that does not exist in the token results in ERROR_NOT_ALL_ASSIGNED being returned. Privilege checks for /// removed privileges result in STATUS_PRIVILEGE_NOT_HELD. Failed privilege check auditing occurs as normal. The removal of the /// privilege is irreversible, so the name of the removed privilege is not included in the PreviousState parameter after a call to /// AdjustTokenPrivileges. Windows XP with SP1: The function cannot remove privileges. This value is not supported. /// /// /// /// None /// The function disables the privilege. /// /// /// If DisableAllPrivileges is TRUE, the function ignores this parameter. /// /// /// Specifies the size, in bytes, of the buffer pointed to by the PreviousState parameter. This parameter can be zero if the /// PreviousState parameter is NULL. /// /// /// /// A pointer to a buffer that the function fills with a TOKEN_PRIVILEGES structure that contains the previous state of any /// privileges that the function modifies. That is, if a privilege has been modified by this function, the privilege and its previous /// state are contained in the TOKEN_PRIVILEGES structure referenced by PreviousState. If the PrivilegeCount member of /// TOKEN_PRIVILEGES is zero, then no privileges have been changed by this function. This parameter can be NULL. /// /// /// If you specify a buffer that is too small to receive the complete list of modified privileges, the function fails and does not /// adjust any privileges. In this case, the function sets the variable pointed to by the ReturnLength parameter to the number of /// bytes required to hold the complete list of modified privileges. /// /// /// /// A pointer to a variable that receives the required size, in bytes, of the buffer pointed to by the PreviousState parameter. This /// parameter can be NULL if PreviousState is NULL. /// /// /// /// If the function succeeds, the return value is nonzero. To determine whether the function adjusted all of the specified /// privileges, call GetLastError, which returns one of the following values when the function succeeds: /// /// /// /// Return code /// Description /// /// /// ERROR_SUCCESS /// The function adjusted all specified privileges. /// /// /// ERROR_NOT_ALL_ASSIGNED /// /// The token does not have one or more of the privileges specified in the NewState parameter. The function may succeed with this /// error value even if no privileges were adjusted. The PreviousState parameter indicates the privileges that were adjusted. /// /// /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// /// /// /// The AdjustTokenPrivileges function cannot add new privileges to the access token. It can only enable or disable the /// token's existing privileges. To determine the token's privileges, call the GetTokenInformation function. /// /// /// The NewState parameter can specify privileges that the token does not have, without causing the function to fail. In this case, /// the function adjusts the privileges that the token does have and ignores the other privileges so that the function succeeds. Call /// the GetLastError function to determine whether the function adjusted all of the specified privileges. The PreviousState parameter /// indicates the privileges that were adjusted. /// /// /// The PreviousState parameter retrieves a TOKEN_PRIVILEGES structure that contains the original state of the adjusted privileges. /// To restore the original state, pass the PreviousState pointer as the NewState parameter in a subsequent call to the /// AdjustTokenPrivileges function. /// /// Examples /// For an example that uses this function, see Enabling and Disabling Privileges. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-adjusttokenprivileges BOOL // AdjustTokenPrivileges( HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, // PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "8e3f70cd-814e-4aab-8f48-0ca482beef2e")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AdjustTokenPrivileges([In] HTOKEN TokenHandle, [In, MarshalAs(UnmanagedType.Bool)] bool DisableAllPrivileges, [In] IntPtr NewState, [In] uint BufferLength = 0, IntPtr PreviousState = default, IntPtr ReturnLength = default); /// The AllocateLocallyUniqueId function allocates a locally unique identifier (LUID). /// A pointer to a LUID structure that receives the allocated LUID. /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// // BOOL WINAPI AllocateLocallyUniqueId( _Out_ PLUID Luid); https://msdn.microsoft.com/en-us/library/windows/desktop/aa375260(v=vs.85).aspx [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "aa375260")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AllocateLocallyUniqueId(out LUID Luid); /// /// The AreAllAccessesGranted function checks whether a set of requested access rights has been granted. The access rights are /// represented as bit flags in an access mask. /// /// An access mask that specifies the access rights that have been granted. /// /// An access mask that specifies the access rights that have been requested. This mask must have been mapped from generic to /// specific and standard access rights, usually by calling the MapGenericMask function. /// /// /// If all requested access rights have been granted, the return value is nonzero. /// If not all requested access rights have been granted, the return value is zero. /// /// /// The AreAllAccessesGranted function is commonly used by a server application to check the access rights of a client /// attempting to gain access to an object. When the bits set in the DesiredAccess parameter match the bits set in the GrantedAccess /// parameter, all requested rights have been granted. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-areallaccessesgranted BOOL // AreAllAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "91349693-8667-49dd-a813-657497b7d467")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AreAllAccessesGranted(uint GrantedAccess, ACCESS_MASK DesiredAccess); /// /// The AreAnyAccessesGranted function tests whether any of a set of requested access rights has been granted. The access /// rights are represented as bit flags in an access mask. /// /// Specifies the granted access mask. /// /// Specifies the access mask to be requested. This mask must have been mapped from generic to specific and standard access rights, /// usually by calling the MapGenericMask function. /// /// /// If any of the requested access rights have been granted, the return value is nonzero. /// If none of the requested access rights have been granted, the return value is zero. /// /// /// The AreAnyAccessesGranted function is often used by a server application to check the access rights of a client attempting /// to gain access to an object. When any of the bits set in the DesiredAccess parameter match the bits set in the GrantedAccess /// parameter, at least one of the requested access rights has been granted. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-areanyaccessesgranted BOOL // AreAnyAccessesGranted( DWORD GrantedAccess, DWORD DesiredAccess ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "4bac6ebc-716a-4725-b9e6-a109b27dfc18")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool AreAnyAccessesGranted(uint GrantedAccess, ACCESS_MASK DesiredAccess); /// The CheckTokenCapability function checks the capabilities of a given token. /// /// /// A handle to an access token. The handle must have TOKEN_QUERY access to the token. The token must be an impersonation token. /// /// /// If TokenHandle is NULL, CheckTokenCapability uses the impersonation token of the calling thread. If the thread is /// not impersonating, the function duplicates the thread's primary token to create an impersonation token. /// /// /// /// A pointer to a capability SID structure. The CheckTokenCapability function checks the capabilities of this access token. /// /// /// Receives the results of the check. If the access token has the capability, it returns TRUE, otherwise, it returns FALSE. /// /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-checktokencapability BOOL // CheckTokenCapability( HANDLE TokenHandle, PSID CapabilitySidToCheck, PBOOL HasCapability ); [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "436A5110-B79E-4E64-92E8-1C9E713D0948")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CheckTokenCapability(HTOKEN TokenHandle, PSID CapabilitySidToCheck, [MarshalAs(UnmanagedType.Bool)] out bool HasCapability); /// /// The CheckTokenMembership function determines whether a specified security identifier (SID) is enabled in an access token. /// If you want to determine group membership for app container tokens, you need to use the CheckTokenMembershipEx function. /// /// /// /// A handle to an access token. The handle must have TOKEN_QUERY access to the token. The token must be an impersonation token. /// /// /// If TokenHandle is NULL, CheckTokenMembership uses the impersonation token of the calling thread. If the thread is /// not impersonating, the function duplicates the thread's primary token to create an impersonation token. /// /// /// /// A pointer to a SID structure. The CheckTokenMembership function checks for the presence of this SID in the user and group /// SIDs of the access token. /// /// /// A pointer to a variable that receives the results of the check. If the SID is present and has the SE_GROUP_ENABLED attribute, /// IsMember returns TRUE; otherwise, it returns FALSE. /// /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// /// /// /// The CheckTokenMembership function simplifies the process of determining whether a SID is both present and enabled in an /// access token. /// /// /// Even if a SID is present in the token, the system may not use the SID in an access check. The SID may be disabled or have the /// SE_GROUP_USE_FOR_DENY_ONLY attribute. The system uses only enabled SIDs to grant access when performing an access check. /// For more information, see SID Attributes in an Access Token. /// /// /// If TokenHandle is a restricted token, or if TokenHandle is NULL and the current effective token of the calling thread is a /// restricted token, CheckTokenMembership also checks whether the SID is present in the list of restricting SIDs. /// /// Examples /// The following example shows checking a token for membership in the Administrators local group. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-checktokenmembership BOOL // CheckTokenMembership( HANDLE TokenHandle, PSID SidToCheck, PBOOL IsMember ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "c254a167-c4e7-4b84-9be3-6862761309f8")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CheckTokenMembership(HTOKEN TokenHandle, PSID SidToCheck, [MarshalAs(UnmanagedType.Bool)] out bool IsMember); /// The CheckTokenMembershipEx function determines whether the specified SID is enabled in the specified token. /// /// A handle to an access token. If present, this token is checked for the SID. If not present, then the current effective token is /// used. This must be an impersonation token. /// /// /// A pointer to a SID structure. The function checks for the presence of this SID in the presence of the token. /// /// /// Flags that affect the behavior of the function. Currently the only valid flag is CTMF_INCLUDE_APPCONTAINER which allows app /// containers to pass the call as long as the other requirements of the token are met, such as the group specified is present and enabled. /// /// TRUE if the SID is enabled in the token; otherwise, FALSE. /// /// If the function succeeds, it returns TRUE. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-checktokenmembershipex BOOL // CheckTokenMembershipEx( HANDLE TokenHandle, PSID SidToCheck, DWORD Flags, PBOOL IsMember ); [DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "0420FC77-8035-42A5-8907-83D0CE53FB64")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CheckTokenMembershipEx(HTOKEN TokenHandle, PSID SidToCheck, CTMF Flags, [MarshalAs(UnmanagedType.Bool)] out bool IsMember); /// /// The ConvertToAutoInheritPrivateObjectSecurity function converts a security descriptor and its access control lists (ACLs) /// to a format that supports automatic propagation of inheritable access control entries (ACEs). /// /// /// A pointer to the security descriptor for the parent container of the object. If there is no parent container, this parameter is NULL. /// /// A pointer to the current security descriptor of the object. /// /// A pointer to a variable that receives a pointer to the newly allocated self-relative security descriptor. It is the caller's /// responsibility to call the DestroyPrivateObjectSecurity function to free this security descriptor. /// /// /// A pointer to a GUID structure that identifies the type of object associated with the CurrentSecurityDescriptor parameter. If the /// object does not have a GUID, this parameter must be NULL. /// /// /// If TRUE, the new object is a container and can contain other objects. If FALSE, the new object is not a container. /// /// /// A pointer to a GENERIC_MAPPING structure that specifies the mapping from each generic right to specific rights for the object. /// /// /// If the function succeeds, the function returns nonzero. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// /// /// /// The ConvertToAutoInheritPrivateObjectSecurity function attempts to determine whether the ACEs in the discretionary access /// control list (DACL) and system access control list (SACL) of the current security descriptor were inherited from the parent /// security descriptor. The function passes the ParentDescriptor parameter to the CreatePrivateObjectSecurityEx function to get ACLs /// that contain only inherited ACEs. Then it compares these ACEs to the ACEs in the original security descriptor to determine which /// of the original ACEs were inherited. The ACEs do not need to match one-to-one. For instance, an ACE that allows read and write /// access to a trustee can be equivalent to two ACEs: an ACE that allows read access and an ACE that allows write access. /// /// /// Any ACEs in the original security descriptor that are equivalent to the ACEs inherited from the parent security descriptor are /// marked with the INHERITED_ACE flag and added to the new security descriptor. All other ACEs in the original security descriptor /// are added to the new security descriptor as noninherited ACEs. /// /// /// If the original DACL does not have any inherited ACEs, the function sets the SE_DACL_PROTECTED flag in the control bits of the /// new security descriptor. Similarly, the SE_SACL_PROTECTED flag is set if none of the ACEs in the SACL is inherited. /// /// /// For DACLs that have inherited ACEs, the function reorders the ACEs into two groups. The first group has ACEs that were directly /// applied to the object. The second group has inherited ACEs. This ordering ensures that noninherited ACEs have precedence over /// inherited ACEs. For more information, see Order of ACEs in a DACL. /// /// /// The function sets the SE_DACL_AUTO_INHERITED and SE_SACL_AUTO_INHERITED flags in the control bits of the new security descriptor. /// /// /// The function does not change the ordering of access-allowed ACEs in relation to access-denied ACEs in the DACL because to do so /// would change the semantics of the resulting security descriptor. If the function cannot convert the DACL without changing the /// semantics, it leaves the DACL unchanged and sets the SE_DACL_PROTECTED flag. /// /// The new security descriptor has the same owner and primary group as the original security descriptor. /// /// The new security descriptor is equivalent to the original security descriptor, so the caller needs no access rights or privileges /// to update the security descriptor to the new format. /// /// This function works with ACL_REVISION and ACL_REVISION_DS ACLs. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-converttoautoinheritprivateobjectsecurity // BOOL ConvertToAutoInheritPrivateObjectSecurity( PSECURITY_DESCRIPTOR ParentDescriptor, PSECURITY_DESCRIPTOR // CurrentSecurityDescriptor, PSECURITY_DESCRIPTOR *NewSecurityDescriptor, GUID *ObjectType, BOOLEAN IsDirectoryObject, // PGENERIC_MAPPING GenericMapping ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "eaaa5509-eff5-461d-843b-7ebbbe0dd58f")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool ConvertToAutoInheritPrivateObjectSecurity([In, Optional] PSECURITY_DESCRIPTOR ParentDescriptor, [In] PSECURITY_DESCRIPTOR CurrentSecurityDescriptor, out SafePrivateObjectSecurity NewSecurityDescriptor, in Guid ObjectType, [MarshalAs(UnmanagedType.U1)] bool IsDirectoryObject, in GENERIC_MAPPING GenericMapping); /// /// The ConvertToAutoInheritPrivateObjectSecurity function converts a security descriptor and its access control lists (ACLs) /// to a format that supports automatic propagation of inheritable access control entries (ACEs). /// /// /// A pointer to the security descriptor for the parent container of the object. If there is no parent container, this parameter is NULL. /// /// A pointer to the current security descriptor of the object. /// /// A pointer to a variable that receives a pointer to the newly allocated self-relative security descriptor. It is the caller's /// responsibility to call the DestroyPrivateObjectSecurity function to free this security descriptor. /// /// /// A pointer to a GUID structure that identifies the type of object associated with the CurrentSecurityDescriptor parameter. If the /// object does not have a GUID, this parameter must be NULL. /// /// /// If TRUE, the new object is a container and can contain other objects. If FALSE, the new object is not a container. /// /// /// A pointer to a GENERIC_MAPPING structure that specifies the mapping from each generic right to specific rights for the object. /// /// /// If the function succeeds, the function returns nonzero. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// /// /// /// The ConvertToAutoInheritPrivateObjectSecurity function attempts to determine whether the ACEs in the discretionary access /// control list (DACL) and system access control list (SACL) of the current security descriptor were inherited from the parent /// security descriptor. The function passes the ParentDescriptor parameter to the CreatePrivateObjectSecurityEx function to get ACLs /// that contain only inherited ACEs. Then it compares these ACEs to the ACEs in the original security descriptor to determine which /// of the original ACEs were inherited. The ACEs do not need to match one-to-one. For instance, an ACE that allows read and write /// access to a trustee can be equivalent to two ACEs: an ACE that allows read access and an ACE that allows write access. /// /// /// Any ACEs in the original security descriptor that are equivalent to the ACEs inherited from the parent security descriptor are /// marked with the INHERITED_ACE flag and added to the new security descriptor. All other ACEs in the original security descriptor /// are added to the new security descriptor as noninherited ACEs. /// /// /// If the original DACL does not have any inherited ACEs, the function sets the SE_DACL_PROTECTED flag in the control bits of the /// new security descriptor. Similarly, the SE_SACL_PROTECTED flag is set if none of the ACEs in the SACL is inherited. /// /// /// For DACLs that have inherited ACEs, the function reorders the ACEs into two groups. The first group has ACEs that were directly /// applied to the object. The second group has inherited ACEs. This ordering ensures that noninherited ACEs have precedence over /// inherited ACEs. For more information, see Order of ACEs in a DACL. /// /// /// The function sets the SE_DACL_AUTO_INHERITED and SE_SACL_AUTO_INHERITED flags in the control bits of the new security descriptor. /// /// /// The function does not change the ordering of access-allowed ACEs in relation to access-denied ACEs in the DACL because to do so /// would change the semantics of the resulting security descriptor. If the function cannot convert the DACL without changing the /// semantics, it leaves the DACL unchanged and sets the SE_DACL_PROTECTED flag. /// /// The new security descriptor has the same owner and primary group as the original security descriptor. /// /// The new security descriptor is equivalent to the original security descriptor, so the caller needs no access rights or privileges /// to update the security descriptor to the new format. /// /// This function works with ACL_REVISION and ACL_REVISION_DS ACLs. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-converttoautoinheritprivateobjectsecurity // BOOL ConvertToAutoInheritPrivateObjectSecurity( PSECURITY_DESCRIPTOR ParentDescriptor, PSECURITY_DESCRIPTOR // CurrentSecurityDescriptor, PSECURITY_DESCRIPTOR *NewSecurityDescriptor, GUID *ObjectType, BOOLEAN IsDirectoryObject, // PGENERIC_MAPPING GenericMapping ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "eaaa5509-eff5-461d-843b-7ebbbe0dd58f")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool ConvertToAutoInheritPrivateObjectSecurity([In, Optional] PSECURITY_DESCRIPTOR ParentDescriptor, [In] PSECURITY_DESCRIPTOR CurrentSecurityDescriptor, out SafePrivateObjectSecurity NewSecurityDescriptor, [In, Optional] IntPtr ObjectType, [MarshalAs(UnmanagedType.U1)] bool IsDirectoryObject, in GENERIC_MAPPING GenericMapping); /// /// /// The CreatePrivateObjectSecurity function allocates and initializes a self-relative security descriptor for a new private /// object. A protected server calls this function when it creates a new private object. /// /// /// To specify the object type GUID of the new object or control how access control entries (ACEs) are inherited, use the /// CreatePrivateObjectSecurityEx function. /// /// /// /// A pointer to the security descriptor for the parent directory in which a new object is being created. If there is no parent /// directory, this parameter can be NULL. /// /// /// A pointer to a security descriptor provided by the creator of the object. If the object's creator does not explicitly pass /// security information for the new object, this parameter is intended to be NULL. /// /// /// A pointer to a variable that receives a pointer to the newly allocated self-relative security descriptor. The caller must call /// the DestroyPrivateObjectSecurity function to free this security descriptor. /// /// /// Specifies whether the new object is a container. A value of TRUE indicates the object contains other objects, such as a directory. /// /// /// /// A handle to the access token for the client process on whose behalf the object is being created. If this is an impersonation /// token, it must be at SecurityIdentification level or higher. For a full description of the SecurityIdentification impersonation /// level, see the SECURITY_IMPERSONATION_LEVEL enumerated type. /// /// /// A client token is used to retrieve default security information for the new object, such as its default owner, primary group, and /// discretionary access control list. The token must be open for TOKEN_QUERY access. /// /// /// If all of the following conditions are true, then the handle must be opened for TOKEN_DUPLICATE access in addition to /// TOKEN_QUERY access. /// /// /// /// The token handle refers to a primary token. /// /// /// The security descriptor of the token contains one or more ACEs with the OwnerRights SID. /// /// /// A security descriptor is specified for the CreatorDescriptor parameter. /// /// /// The caller of this function does not set the SEF_AVOID_OWNER_RESTRICTION flag in the AutoInheritFlags parameter. /// /// /// /// /// A pointer to a GENERIC_MAPPING structure that specifies the mapping from each generic right to specific rights for the object. /// /// /// If the function succeeds, the function returns nonzero. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// /// /// If a system access control list (SACL) is specified in the SECURITY_DESCRIPTOR specified by the CreatorDescriptor parameter, the /// Token parameter must have the SE_SECURITY_NAME privilege enabled. The CreatePrivateObjectSecurity function checks this /// privilege and may generate audits during the process. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-createprivateobjectsecurity BOOL // CreatePrivateObjectSecurity( PSECURITY_DESCRIPTOR ParentDescriptor, PSECURITY_DESCRIPTOR CreatorDescriptor, PSECURITY_DESCRIPTOR // *NewDescriptor, BOOL IsDirectoryObject, HANDLE Token, PGENERIC_MAPPING GenericMapping ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "5f4832b6-5cf5-4050-9e20-56674f2e2cb1")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CreatePrivateObjectSecurity([In, Optional] PSECURITY_DESCRIPTOR ParentDescriptor, [In, Optional] PSECURITY_DESCRIPTOR CreatorDescriptor, out SafePrivateObjectSecurity NewDescriptor, [MarshalAs(UnmanagedType.Bool)] bool IsDirectoryObject, [In, Optional] HTOKEN Token, in GENERIC_MAPPING GenericMapping); /// /// The CreatePrivateObjectSecurityEx function allocates and initializes a self-relative security descriptor for a new private /// object created by the resource manager calling this function. /// /// /// A pointer to the security descriptor for the parent container of the object. If there is no parent container, this parameter is NULL. /// /// /// A pointer to a security descriptor provided by the creator of the object. If the object's creator does not explicitly pass /// security information for the new object, this parameter can be NULL. Alternatively, this parameter can point to a default /// security descriptor. /// /// /// A pointer to a variable that receives a pointer to the newly allocated self-relative security descriptor. When you have finished /// using the security descriptor, free it by calling the DestroyPrivateObjectSecurity function. /// /// /// A pointer to a GUID structure that identifies the type of object associated with NewDescriptor. If the object does not /// have a GUID, set ObjectType to NULL. /// /// /// Specifies whether the new object can contain other objects. A value of TRUE indicates that the new object is a container. /// A value of FALSE indicates that the new object is not a container. /// /// /// /// A set of bit flags that control how access control entries (ACEs) are inherited from ParentDescriptor. This parameter can be a /// combination of the following values. /// /// /// /// /// Value /// Meaning /// /// /// SEF_AVOID_OWNER_CHECK0x10 /// /// The function does not check the validity of the owner in the resultant NewDescriptor as described in Remarks below. If the /// SEF_AVOID_PRIVILEGE_CHECK flag is also set, the Token parameter can be NULL. /// /// /// /// SEF_AVOID_OWNER_RESTRICTION0x1000 /// /// Any restrictions specified by the ParentDescriptor that would limit the caller's ability to specify a DACL in the /// CreatorDescriptor are ignored. /// /// /// /// SEF_AVOID_PRIVILEGE_CHECK0x08 /// /// The function does not perform privilege checking. If the SEF_AVOID_OWNER_CHECK flag is also set, the Token parameter can be NULL. /// This flag is useful while implementing automatic inheritance to avoid checking privileges on each child updated. /// /// /// /// SEF_DACL_AUTO_INHERIT0x01 /// /// The new discretionary access control list (DACL) contains ACEs inherited from the DACL of ParentDescriptor, as well as any /// explicit ACEs specified in the DACL of CreatorDescriptor. If this flag is not set, the new DACL does not inherit ACEs. /// /// /// /// SEF_DEFAULT_DESCRIPTOR_FOR_OBJECT0x04 /// /// CreatorDescriptor is the default descriptor for the type of object specified by ObjectType. As such, CreatorDescriptor is ignored /// if ParentDescriptor has any object-specific ACEs for the type of object specified by the ObjectType parameter. If no such ACEs /// are inherited, CreatorDescriptor is handled as though this flag were not specified. /// /// /// /// SEF_DEFAULT_GROUP_FROM_PARENT0x40 /// /// The group of NewDescriptor defaults to the group from ParentDescriptor. If not set, the group of NewDescriptor defaults to the /// group of the token specified by the Token parameter. The group of the token is specified in the token itself. In either case, if /// the CreatorDescriptor parameter is not NULL, the NewDescriptor group is set to the group from CreatorDescriptor. /// /// /// /// SEF_DEFAULT_OWNER_FROM_PARENT0x20 /// /// The owner of NewDescriptor defaults to the owner from ParentDescriptor. If not set, the owner of NewDescriptor defaults to the /// owner of the token specified by the Token parameter. The owner of the token is specified in the token itself. In either case, if /// the CreatorDescriptor parameter is not NULL, the NewDescriptor owner is set to the owner from CreatorDescriptor. /// /// /// /// SEF_MACL_NO_EXECUTE_UP0x400 /// /// When this flag is set, the mandatory label ACE in CreatorDescriptor is not used to create a mandatory label ACE in NewDescriptor. /// Instead, a new SYSTEM_MANDATORY_LABEL_ACE with an access mask of SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP and the SID from the /// token's integrity SID is added to NewDescriptor. /// /// /// /// SEF_MACL_NO_READ_UP0x200 /// /// When this flag is set, the mandatory label ACE in CreatorDescriptor is not used to create a mandatory label ACE in NewDescriptor. /// Instead, a new SYSTEM_MANDATORY_LABEL_ACE with an access mask of SYSTEM_MANDATORY_LABEL_NO_READ_UP and the SID from the /// token's integrity SID is added to NewDescriptor. /// /// /// /// SEF_MACL_NO_WRITE_UP0x100 /// /// When this flag is set, the mandatory label ACE in CreatorDescriptor is not used to create a mandatory label ACE in NewDescriptor. /// Instead, a new SYSTEM_MANDATORY_LABEL_ACE with an access mask of SYSTEM_MANDATORY_LABEL_NO_WRITE_UP and the SID from the /// token's integrity SID is added to NewDescriptor. /// /// /// /// SEF_SACL_AUTO_INHERIT0x02 /// /// The new system access control list (SACL) contains ACEs inherited from the SACL of ParentDescriptor, as well as any explicit ACEs /// specified in the SACL of CreatorDescriptor. If this flag is not set, the new SACL does not inherit ACEs. /// /// /// /// /// /// /// /// A handle to the access token for the client process on whose behalf the object is being created. If this is an impersonation /// token, it must be at SecurityIdentification level or higher. For a full description of the SecurityIdentification impersonation /// level, see the SECURITY_IMPERSONATION_LEVEL enumerated type. /// /// /// The client token contains default security information, such as the default owner, primary group, and DACL. The function uses /// these defaults if the information is not in the input security descriptors. The token must be open for TOKEN_QUERY access. /// /// /// If all of the following conditions are true, then the handle must be opened for TOKEN_DUPLICATE access in addition to /// TOKEN_QUERY access. /// /// /// /// A pointer to a GENERIC_MAPPING structure that specifies the mapping from each generic right to specific rights for the object. /// /// /// If the function succeeds, the function returns nonzero. /// /// If the function fails, it returns zero. To get extended error information, call GetLastError. Some of the extended error /// codes and their meanings are listed in the following table. /// /// /// /// /// Return code /// Description /// /// /// ERROR_INVALID_OWNER /// /// The function cannot retrieve an owner for the new security descriptor or the SID cannot be assigned as an owner. This occurs when /// validating the owner SID against the passed-in token. /// /// /// /// ERROR_INVALID_PRIMARY_GROUP /// The function cannot retrieve a primary group for the new security descriptor. /// /// /// ERROR_NO_TOKEN /// The function received NULL instead of a token for owner validation or privilege checking. /// /// /// ERROR_PRIVILEGE_NOT_HELD /// /// A SACL is being set, SEF_AVOID_PRIVILEGE_CHECK was not passed in, and the token passed in did not have SE_SECURITY_NAME enabled. /// /// /// /// /// // BOOL WINAPI CreatePrivateObjectSecurityEx( _In_opt_ PSECURITY_DESCRIPTOR ParentDescriptor, _In_opt_ PSECURITY_DESCRIPTOR // CreatorDescriptor, _Out_ PSECURITY_DESCRIPTOR *NewDescriptor, _In_opt_ GUID *ObjectType, _In_ BOOL IsContainerObject, _In_ ULONG // AutoInheritFlags, _In_opt_ HANDLE Token, _In_ PGENERIC_MAPPING GenericMapping); https://msdn.microsoft.com/en-us/library/windows/desktop/aa446581(v=vs.85).aspx [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("Winbase.h", MSDNShortId = "aa446581")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CreatePrivateObjectSecurityEx([In, Optional] PSECURITY_DESCRIPTOR ParentDescriptor, [In, Optional] PSECURITY_DESCRIPTOR CreatorDescriptor, out SafePrivateObjectSecurity NewDescriptor, in Guid ObjectType, [MarshalAs(UnmanagedType.Bool)] bool IsContainerObject, SEF AutoInheritFlags, [In, Optional] HTOKEN Token, in GENERIC_MAPPING GenericMapping); /// /// The CreatePrivateObjectSecurityEx function allocates and initializes a self-relative security descriptor for a new private /// object created by the resource manager calling this function. /// /// /// A pointer to the security descriptor for the parent container of the object. If there is no parent container, this parameter is NULL. /// /// /// A pointer to a security descriptor provided by the creator of the object. If the object's creator does not explicitly pass /// security information for the new object, this parameter can be NULL. Alternatively, this parameter can point to a default /// security descriptor. /// /// /// A pointer to a variable that receives a pointer to the newly allocated self-relative security descriptor. When you have finished /// using the security descriptor, free it by calling the DestroyPrivateObjectSecurity function. /// /// /// A pointer to a GUID structure that identifies the type of object associated with NewDescriptor. If the object does not /// have a GUID, set ObjectType to NULL. /// /// /// Specifies whether the new object can contain other objects. A value of TRUE indicates that the new object is a container. /// A value of FALSE indicates that the new object is not a container. /// /// /// /// A set of bit flags that control how access control entries (ACEs) are inherited from ParentDescriptor. This parameter can be a /// combination of the following values. /// /// /// /// /// Value /// Meaning /// /// /// SEF_AVOID_OWNER_CHECK0x10 /// /// The function does not check the validity of the owner in the resultant NewDescriptor as described in Remarks below. If the /// SEF_AVOID_PRIVILEGE_CHECK flag is also set, the Token parameter can be NULL. /// /// /// /// SEF_AVOID_OWNER_RESTRICTION0x1000 /// /// Any restrictions specified by the ParentDescriptor that would limit the caller's ability to specify a DACL in the /// CreatorDescriptor are ignored. /// /// /// /// SEF_AVOID_PRIVILEGE_CHECK0x08 /// /// The function does not perform privilege checking. If the SEF_AVOID_OWNER_CHECK flag is also set, the Token parameter can be NULL. /// This flag is useful while implementing automatic inheritance to avoid checking privileges on each child updated. /// /// /// /// SEF_DACL_AUTO_INHERIT0x01 /// /// The new discretionary access control list (DACL) contains ACEs inherited from the DACL of ParentDescriptor, as well as any /// explicit ACEs specified in the DACL of CreatorDescriptor. If this flag is not set, the new DACL does not inherit ACEs. /// /// /// /// SEF_DEFAULT_DESCRIPTOR_FOR_OBJECT0x04 /// /// CreatorDescriptor is the default descriptor for the type of object specified by ObjectType. As such, CreatorDescriptor is ignored /// if ParentDescriptor has any object-specific ACEs for the type of object specified by the ObjectType parameter. If no such ACEs /// are inherited, CreatorDescriptor is handled as though this flag were not specified. /// /// /// /// SEF_DEFAULT_GROUP_FROM_PARENT0x40 /// /// The group of NewDescriptor defaults to the group from ParentDescriptor. If not set, the group of NewDescriptor defaults to the /// group of the token specified by the Token parameter. The group of the token is specified in the token itself. In either case, if /// the CreatorDescriptor parameter is not NULL, the NewDescriptor group is set to the group from CreatorDescriptor. /// /// /// /// SEF_DEFAULT_OWNER_FROM_PARENT0x20 /// /// The owner of NewDescriptor defaults to the owner from ParentDescriptor. If not set, the owner of NewDescriptor defaults to the /// owner of the token specified by the Token parameter. The owner of the token is specified in the token itself. In either case, if /// the CreatorDescriptor parameter is not NULL, the NewDescriptor owner is set to the owner from CreatorDescriptor. /// /// /// /// SEF_MACL_NO_EXECUTE_UP0x400 /// /// When this flag is set, the mandatory label ACE in CreatorDescriptor is not used to create a mandatory label ACE in NewDescriptor. /// Instead, a new SYSTEM_MANDATORY_LABEL_ACE with an access mask of SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP and the SID from the /// token's integrity SID is added to NewDescriptor. /// /// /// /// SEF_MACL_NO_READ_UP0x200 /// /// When this flag is set, the mandatory label ACE in CreatorDescriptor is not used to create a mandatory label ACE in NewDescriptor. /// Instead, a new SYSTEM_MANDATORY_LABEL_ACE with an access mask of SYSTEM_MANDATORY_LABEL_NO_READ_UP and the SID from the /// token's integrity SID is added to NewDescriptor. /// /// /// /// SEF_MACL_NO_WRITE_UP0x100 /// /// When this flag is set, the mandatory label ACE in CreatorDescriptor is not used to create a mandatory label ACE in NewDescriptor. /// Instead, a new SYSTEM_MANDATORY_LABEL_ACE with an access mask of SYSTEM_MANDATORY_LABEL_NO_WRITE_UP and the SID from the /// token's integrity SID is added to NewDescriptor. /// /// /// /// SEF_SACL_AUTO_INHERIT0x02 /// /// The new system access control list (SACL) contains ACEs inherited from the SACL of ParentDescriptor, as well as any explicit ACEs /// specified in the SACL of CreatorDescriptor. If this flag is not set, the new SACL does not inherit ACEs. /// /// /// /// /// /// /// /// A handle to the access token for the client process on whose behalf the object is being created. If this is an impersonation /// token, it must be at SecurityIdentification level or higher. For a full description of the SecurityIdentification impersonation /// level, see the SECURITY_IMPERSONATION_LEVEL enumerated type. /// /// /// The client token contains default security information, such as the default owner, primary group, and DACL. The function uses /// these defaults if the information is not in the input security descriptors. The token must be open for TOKEN_QUERY access. /// /// /// If all of the following conditions are true, then the handle must be opened for TOKEN_DUPLICATE access in addition to /// TOKEN_QUERY access. /// /// /// /// A pointer to a GENERIC_MAPPING structure that specifies the mapping from each generic right to specific rights for the object. /// /// /// If the function succeeds, the function returns nonzero. /// /// If the function fails, it returns zero. To get extended error information, call GetLastError. Some of the extended error /// codes and their meanings are listed in the following table. /// /// /// /// /// Return code /// Description /// /// /// ERROR_INVALID_OWNER /// /// The function cannot retrieve an owner for the new security descriptor or the SID cannot be assigned as an owner. This occurs when /// validating the owner SID against the passed-in token. /// /// /// /// ERROR_INVALID_PRIMARY_GROUP /// The function cannot retrieve a primary group for the new security descriptor. /// /// /// ERROR_NO_TOKEN /// The function received NULL instead of a token for owner validation or privilege checking. /// /// /// ERROR_PRIVILEGE_NOT_HELD /// /// A SACL is being set, SEF_AVOID_PRIVILEGE_CHECK was not passed in, and the token passed in did not have SE_SECURITY_NAME enabled. /// /// /// /// /// // BOOL WINAPI CreatePrivateObjectSecurityEx( _In_opt_ PSECURITY_DESCRIPTOR ParentDescriptor, _In_opt_ PSECURITY_DESCRIPTOR // CreatorDescriptor, _Out_ PSECURITY_DESCRIPTOR *NewDescriptor, _In_opt_ GUID *ObjectType, _In_ BOOL IsContainerObject, _In_ ULONG // AutoInheritFlags, _In_opt_ HANDLE Token, _In_ PGENERIC_MAPPING GenericMapping); https://msdn.microsoft.com/en-us/library/windows/desktop/aa446581(v=vs.85).aspx [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("Winbase.h", MSDNShortId = "aa446581")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CreatePrivateObjectSecurityEx([In, Optional] PSECURITY_DESCRIPTOR ParentDescriptor, [In, Optional] PSECURITY_DESCRIPTOR CreatorDescriptor, out SafePrivateObjectSecurity NewDescriptor, [In, Optional] IntPtr ObjectType, [MarshalAs(UnmanagedType.Bool)] bool IsContainerObject, SEF AutoInheritFlags, [In, Optional] HTOKEN Token, in GENERIC_MAPPING GenericMapping); /// /// The CreatePrivateObjectSecurityWithMultipleInheritance function allocates and initializes a self-relative security /// descriptor for a new private object created by the resource manager calling this function. This function supports private objects /// (such as Directory Service objects with attached auxiliary classes) composed of multiple object types or classes. /// /// /// A pointer to the security descriptor for the parent container of the object. If there is no parent container, this parameter is NULL. /// /// /// A pointer to a security descriptor provided by the creator of the object. If the object's creator does not explicitly pass /// security information for the new object, this parameter can be NULL. Alternatively, this parameter can point to a default /// security descriptor. /// /// /// A pointer to a variable to receive a pointer to the newly allocated self-relative security descriptor. When you have finished /// using the security descriptor, free it by calling the DestroyPrivateObjectSecurity function. /// /// /// An array of pointers to GUID structures that identify the object types or classes of the object associated with NewDescriptor. /// For Active Directory objects, this array contains pointers to the class GUIDs of the object's structural class and all attached /// auxiliary classes. Set ObjectTypes to NULL if the object does not have a GUID. /// /// The number of GUIDs present in the ObjectTypes parameter. /// /// Specifies whether the new object can contain other objects. A value of TRUE indicates that the new object is a container. /// A value of FALSE indicates that the new object is not a container. /// /// /// /// A set of bit flags that control how access control entries (ACEs) are inherited from ParentDescriptor. This parameter can be a /// combination of the following values. /// /// /// /// Value /// Meaning /// /// /// SEF_DACL_AUTO_INHERIT 0x01 /// /// The new discretionary access control list (DACL) contains ACEs inherited from the DACL of ParentDescriptor, as well as any /// explicit ACEs specified in the DACL of CreatorDescriptor. If this flag is not set, the new DACL does not inherit ACEs. /// /// /// /// SEF_SACL_AUTO_INHERIT 0x02 /// /// The new system access control list (SACL) contains ACEs inherited from the SACL of ParentDescriptor, as well as any explicit ACEs /// specified in the SACL of CreatorDescriptor. If this flag is not set, the new SACL does not inherit ACEs. /// /// /// /// SEF_DEFAULT_DESCRIPTOR_FOR_OBJECT 0x04 /// /// CreatorDescriptor is the default descriptor for the types of objects specified by ObjectTypes. As such, CreatorDescriptor is /// ignored if ParentDescriptor has any object-specific ACEs for the types of objects specified by the ObjectTypes parameter. If no /// such ACEs are inherited, CreatorDescriptor is handled as though this flag were not specified. /// /// /// /// SEF_AVOID_PRIVILEGE_CHECK 0x08 /// /// The function does not perform privilege checking. If the SEF_AVOID_OWNER_CHECK flag is also set, the Token parameter can be NULL. /// This flag is useful while implementing automatic inheritance to avoid checking privileges on each child updated. /// /// /// /// SEF_AVOID_OWNER_CHECK 0x10 /// /// The function does not check the validity of the owner in the resultant NewDescriptor as described in the Remarks section. If the /// SEF_AVOID_PRIVILEGE_CHECK flag is also set, the Token parameter can be NULL. /// /// /// /// SEF_DEFAULT_OWNER_FROM_PARENT 0x20 /// /// The owner of NewDescriptor defaults to the owner from ParentDescriptor. If not set, the owner of NewDescriptor defaults to the /// owner of the token specified by the Token parameter. The owner of the token is specified in the token itself. In either case, if /// the CreatorDescriptor parameter is not NULL, the NewDescriptor owner is set to the owner from CreatorDescriptor. /// /// /// /// SEF_DEFAULT_GROUP_FROM_PARENT 0x40 /// /// The group of NewDescriptor defaults to the group from ParentDescriptor. If not set, the group of NewDescriptor defaults to the /// group of the token specified by the Token parameter. The group of the token is specified in the token itself. In either case, if /// the CreatorDescriptor parameter is not NULL, the NewDescriptor group is set to the group from CreatorDescriptor. /// /// /// /// SEF_MACL_NO_WRITE_UP 0x100 /// A principal with a mandatory level lower than that of the object cannot write to the object. /// /// /// SEF_MACL_NO_READ_UP 0x200 /// A principal with a mandatory level lower than that of the object cannot read the object. /// /// /// SEF_MACL_NO_EXECUTE_UP 0x400 /// A principal with a mandatory level lower than that of the object cannot execute the object. /// /// /// SEF_AVOID_OWNER_RESTRICTION 0x1000 /// /// Any restrictions specified by the ParentDescriptor parameter that would limit the caller's ability to specify a DACL in the /// CreatorDescriptor are ignored. /// /// /// /// /// /// /// A handle to the access token for the client process on whose behalf the object is being created. If this is an impersonation /// token, it must be at SecurityIdentification level or higher. For a full description of the SecurityIdentification impersonation /// level, see the SECURITY_IMPERSONATION_LEVEL enumerated type. /// /// /// The client token contains default security information, such as the default owner, primary group, and DACL. This function uses /// these defaults if the information is not in the input security descriptors. The token must be open for TOKEN_QUERY access. /// /// /// If all of the following conditions are true, then the handle must be opened for TOKEN_DUPLICATE access in addition to /// TOKEN_QUERY access. /// /// /// /// The token handle refers to a primary token. /// /// /// The security descriptor of the token contains one or more ACEs with the OwnerRights SID. /// /// /// A security descriptor is specified for the CreatorDescriptor parameter. /// /// /// The caller of this function does not set the SEF_AVOID_OWNER_RESTRICTION flag in the AutoInheritFlags parameter. /// /// /// /// /// A pointer to a GENERIC_MAPPING structure that specifies the mapping from each generic right to specific rights for the object. /// /// /// If the function succeeds, the function returns a nonzero value. /// /// If the function fails, it returns zero. Call GetLastError for extended error information. Some extended error codes and their /// meanings are listed in the following table. /// /// /// /// Return code /// Description /// /// /// ERROR_INVALID_PRIMARY_GROUP /// The function cannot retrieve a primary group for the new security descriptor. /// /// /// ERROR_INVALID_OWNER /// /// The function cannot retrieve an owner for the new security descriptor or the security identifier (SID) cannot be assigned as an /// owner. This occurs when validating the owner SID against the passed-in token. /// /// /// /// ERROR_NO_TOKEN /// The function received NULL instead of a token for owner validation or privilege checking. /// /// /// ERROR_PRIVILEGE_NOT_HELD /// /// A SACL is being set, SEF_AVOID_PRIVILEGE_CHECK was not passed in, and the token passed in did not have SE_SECURITY_NAME enabled. /// /// /// /// /// /// /// The CreatePrivateObjectSecurityEx function is identical to calling the CreatePrivateObjectSecurityWithMultipleInheritance /// function with a single GUID in ObjectTypes. /// /// /// The AutoInheritFlags are distinct from the similarly named bits in the Control member of the SECURITY_DESCRIPTOR /// structure. For an explanation of the control bits, see SECURITY_DESCRIPTOR_CONTROL. /// /// /// If AutoInheritFlags specifies the SEF_DACL_AUTO_INHERIT bit, the function applies the following rules to the DACL in the new /// security descriptor: /// /// /// /// The SE_DACL_AUTO_INHERITED flag is set in the Control member of the new security descriptor. /// /// /// /// The DACL of the new security descriptor inherits ACEs from ParentDescriptor regardless of whether CreatorDescriptor is the /// default security descriptor or was explicitly specified by the creator. The new DACL is a combination of the parent and creator /// DACLs as defined by the rules of inheritance. Specifically, any ACEs in ParentDescriptor that are inheritable either to all child /// objects or to any object class listed in ObjectTypes will be applied to the new DACL. /// /// /// /// Inherited ACEs are marked as INHERITED_ACE. /// /// /// If AutoInheritFlags specifies the SEF_SACL_AUTO_INHERIT bit, the function applies similar rules to the new SACL. /// /// For both DACLs and SACLs, certain types of ACEs in ParentDescriptor and CreatorDescriptor will be manipulated and possibly /// replaced by two ACEs in NewDescriptor. Specifically, an inheritable ACE that contains at least one of the following mappable /// elements may result in two ACEs in the output security descriptor. Mappable elements include: /// /// /// /// Generic access rights in the ACCESS_MASK /// /// /// Creator Owner SID or Creator Group SID as the ACE subject identifier /// /// /// ACEs with any of these mappable elements will result in the following two ACEs in NewDescriptor: /// /// /// /// An ACE that is a copy of the original, but with the INHERIT_ONLY flag set. However, this ACE will not be created if either of the /// following two conditions exist: /// /// /// /// An effective ACE in which the INHERITED_ACE bit is turned on and the generic elements are mapped to specific elements: /// /// /// /// If AutoInheritFlags does not specify the SEF_AVOID_OWNER_CHECK bit, owner validity checking is performed according to the /// following rules. The Owner in the resultant NewDescriptormust be a legally formed SID, and either must match the TokenUser in /// Token or must match a group in the TokenGroups in Token. The attributes on the group: /// /// /// /// Must include SE_GROUP_OWNER /// /// /// Must not include SE_GROUP_USE_FOR_DENY_ONLY /// /// /// /// Callers that do not have access to the token of the client that will ultimately be setting the owner may choose to skip owner /// validation checking. /// /// /// To create a security descriptor for a new object, call CreatePrivateObjectSecurityWithMultipleInheritance with /// ParentDescriptor set to the security descriptor of the parent container and CreatorDescriptor set to the security descriptor /// proposed by the creator of the object. /// /// /// To verify the current security descriptor on an object, call CreatePrivateObjectSecurityWithMultipleInheritance with /// ParentDescriptor set to the security descriptor of the parent container and CreatorDescriptor set to the current security /// descriptor of the object. This call ensures that the ACEs are appropriately inherited from parent to child security descriptors. /// /// /// If the CreatorDescriptor security descriptor contains a SACL, Token must have the SE_SECURITY_NAME privilege enabled or the /// caller must specify the SEF_AVOID_PRIVILEGE_CHECK flag in AutoInheritFlags. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-createprivateobjectsecuritywithmultipleinheritance // BOOL CreatePrivateObjectSecurityWithMultipleInheritance( PSECURITY_DESCRIPTOR ParentDescriptor, PSECURITY_DESCRIPTOR // CreatorDescriptor, PSECURITY_DESCRIPTOR *NewDescriptor, GUID **ObjectTypes, ULONG GuidCount, BOOL IsContainerObject, ULONG // AutoInheritFlags, HANDLE Token, PGENERIC_MAPPING GenericMapping ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "8c5a2ac2-612c-4625-8c68-27d99d4ba9d5")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CreatePrivateObjectSecurityWithMultipleInheritance([In, Optional] PSECURITY_DESCRIPTOR ParentDescriptor, [In, Optional] PSECURITY_DESCRIPTOR CreatorDescriptor, out SafePrivateObjectSecurity NewDescriptor, [In, MarshalAs(UnmanagedType.LPArray), Optional] Guid[] ObjectTypes, uint GuidCount, [MarshalAs(UnmanagedType.Bool)] bool IsContainerObject, SEF AutoInheritFlags, HTOKEN Token, in GENERIC_MAPPING GenericMapping); /// /// The CreateRestrictedToken function creates a new access token that is a restricted version of an existing access token. /// The restricted token can have disabled security identifiers (SIDs), deleted privileges, and a list of restricting SIDs. For more /// information, see Restricted Tokens. /// /// /// A handle to a primary or impersonation token. The token can also be a restricted token. The handle must have TOKEN_DUPLICATE /// access to the token. /// /// /// Specifies additional privilege options. This parameter can be zero or a combination of the following values. /// /// /// Value /// Meaning /// /// /// DISABLE_MAX_PRIVILEGE 0x1 /// /// Disables all privileges in the new token except the SeChangeNotifyPrivilege privilege. If this value is specified, the /// DeletePrivilegeCount and PrivilegesToDelete parameters are ignored. /// /// /// /// SANDBOX_INERT 0x2 /// /// If this value is used, the system does not check AppLocker rules or apply Software Restriction Policies. For AppLocker, this flag /// disables checks for all four rule collections: Executable, Windows Installer, Script, and DLL. When creating a setup program that /// must run extracted DLLs during installation, use the flag SAFER_TOKEN_MAKE_INERT in the SaferComputeTokenFromLevel function. A /// token can be queried for existence of this flag by using GetTokenInformation. Windows Server 2008 R2, Windows 7, Windows Server /// 2008, Windows Vista, Windows Server 2003 and Windows XP: On systems with KB2532445 installed, the caller must be running as /// LocalSystem or TrustedInstaller or the system ignores this flag. For more information, see "You can circumvent AppLocker rules by /// using an Office macro on a computer that is running Windows 7 or Windows Server 2008 R2" in the Help and Support Knowledge Base /// at http://support.microsoft.com/kb/2532445. Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: AppLocker is /// not supported. AppLocker was introduced in Windows 7 and Windows Server 2008 R2. /// /// /// /// LUA_TOKEN 0x4 /// The new token is a LUA token. Windows Server 2003 and Windows XP: This value is not supported. /// /// /// WRITE_RESTRICTED 0x8 /// /// The new token contains restricting SIDs that are considered only when evaluating write access. Windows XP with SP2 and later: The /// value of this constant is 0x4. For an application to be compatible with Windows XP with SP2 and later operating systems, the /// application should query the operating system by calling the GetVersionEx function to determine which value should be used. /// Windows Server 2003 and Windows XP with SP1 and earlier: This value is not supported. /// /// /// /// /// Specifies the number of entries in the SidsToDisable array. /// /// /// A pointer to an array of SID_AND_ATTRIBUTES structures that specify the deny-only SIDs in the restricted token. The system uses a /// deny-only SID to deny access to a securable object. The absence of a deny-only SID does not allow access. /// /// /// Disabling a SID turns on SE_GROUP_USE_FOR_DENY_ONLY and turns off SE_GROUP_ENABLED and SE_GROUP_ENABLED_BY_DEFAULT. All other /// attributes are ignored. /// /// /// Deny-only attributes apply to any combination of an existing token's SIDs, including the user SID and group SIDs that have the /// SE_GROUP_MANDATORY attribute. To get the SIDs associated with the existing token, use the GetTokenInformation function with the /// TokenUser and TokenGroups flags. The function ignores any SIDs in the array that are not also found in the existing token. /// /// The function ignores the Attributes member of the SID_AND_ATTRIBUTES structure. /// This parameter can be NULL if no SIDs are to be disabled. /// /// Specifies the number of entries in the PrivilegesToDelete array. /// /// A pointer to an array of LUID_AND_ATTRIBUTES structures that specify the privileges to delete in the restricted token. /// /// The GetTokenInformation function can be used with the TokenPrivileges flag to retrieve the privileges held by the existing token. /// The function ignores any privileges in the array that are not held by the existing token. /// /// The function ignores the Attributes members of the LUID_AND_ATTRIBUTES structures. /// This parameter can be NULL if you do not want to delete any privileges. /// If the calling program passes too many privileges in this array, CreateRestrictedToken returns ERROR_INVALID_PARAMETER. /// /// Specifies the number of entries in the SidsToRestrict array. /// /// /// A pointer to an array of SID_AND_ATTRIBUTES structures that specify a list of restricting SIDs for the new token. If the existing /// token is a restricted token, the list of restricting SIDs for the new token is the intersection of this array and the list of /// restricting SIDs for the existing token. No check is performed to remove duplicate SIDs that were placed on the SidsToRestrict /// parameter. Duplicate SIDs allow a restricted token to have redundant information in the restricting SID list. /// /// /// The Attributes member of the SID_AND_ATTRIBUTES structure must be zero. Restricting SIDs are always enabled for access checks. /// /// This parameter can be NULL if you do not want to specify any restricting SIDs. /// /// /// A pointer to a variable that receives a handle to the new restricted token. This handle has the same access rights as /// ExistingTokenHandle. The new token is the same type, primary or impersonation, as the existing token. The handle returned in /// NewTokenHandle can be duplicated. /// /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// /// /// The CreateRestrictedToken function can restrict the token in the following ways: /// /// /// /// Apply the deny-only attribute to SIDs in the token so they cannot be used to access secured objects. For more information about /// the deny-only attribute, see SID Attributes in an Access Token. /// /// /// /// Remove privileges from the token. /// /// /// /// Specify a list of restricting SIDs, which the system uses when it checks the token's access to a securable object. The system /// performs two access checks: one using the token's enabled SIDs, and another using the list of restricting SIDs. Access is granted /// only if both access checks allow the requested access rights. /// /// /// /// /// You can use the restricted token in the CreateProcessAsUser function to create a process that has restricted access rights and /// privileges. If a process calls CreateProcessAsUser using a restricted version of its own token, the calling process does /// not need to have the SE_ASSIGNPRIMARYTOKEN_NAME privilege. /// /// You can use the restricted token in the ImpersonateLoggedOnUser function. /// /// Caution Applications that use restricted tokens should run the restricted application on desktops other than the default /// desktop. This is necessary to prevent an attack by a restricted application, using SendMessage or PostMessage, to /// unrestricted applications on the default desktop. If necessary, switch between desktops for your application purposes. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-createrestrictedtoken BOOL // CreateRestrictedToken( HANDLE ExistingTokenHandle, DWORD Flags, DWORD DisableSidCount, PSID_AND_ATTRIBUTES SidsToDisable, DWORD // DeletePrivilegeCount, PLUID_AND_ATTRIBUTES PrivilegesToDelete, DWORD RestrictedSidCount, PSID_AND_ATTRIBUTES SidsToRestrict, // PHANDLE NewTokenHandle ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "e087f360-5d1d-4846-b3d6-214a426e5222")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CreateRestrictedToken(HTOKEN ExistingTokenHandle, [Optional] RestrictedPrivilegeOptions Flags, [Optional] uint DisableSidCount, [In, MarshalAs(UnmanagedType.LPArray), Optional] SID_AND_ATTRIBUTES[] SidsToDisable, [Optional] uint DeletePrivilegeCount, [In, MarshalAs(UnmanagedType.LPArray), Optional] LUID_AND_ATTRIBUTES[] PrivilegesToDelete, [Optional] uint RestrictedSidCount, [In, MarshalAs(UnmanagedType.LPArray), Optional] SID_AND_ATTRIBUTES[] SidsToRestrict, out SafeHTOKEN NewTokenHandle); /// /// A tracing function for publishing events when an attempted security vulnerability exploit is detected in your user-mode application. /// /// A pointer to the CVE ID associated with the vulnerability for which this event is being raised. /// /// A pointer to a string giving additional details that the event producer may want to provide to the consumer of this event. /// /// /// Returns ERROR_SUCCESS if successful or one of the following values on error. /// /// /// Return code /// Description /// /// /// ERROR_INVALID_PARAMETER /// One or more of the parameters is not valid. /// /// /// ERROR_ARITHMETIC_OVERFLOW /// The event size is larger than the allowed maximum (64k - header). /// /// /// ERROR_MORE_DATA /// The session buffer size is too small for the event. /// /// /// ERROR_NOT_ENOUGH_MEMORY /// /// Occurs when filled buffers are trying to flush to disk, but disk IOs are not happening fast enough. This happens when the disk is /// slow and event traffic is heavy. Eventually, there are no more free (empty) buffers and the event is dropped. /// /// /// /// STATUS_LOG_FILE_FULL /// /// The real-time playback file is full. Events are not logged to the session until a real-time consumer consumes the events from the /// playback file. Do not stop logging events based on this error code. /// /// /// /// /// /// /// The CveEventWrite function publishes a CVE-based event. This function should be called only in scenarios where an attempt to /// exploit a known, patched vulnerability is detected by the application. Ideally, this function call should be added as part of the /// fix (update) itself. /// /// /// The default consumer for this event is EventLog-Application. To enable another consumer, the provider can be added to the /// consumer session. /// /// Provider GUID: 85a62a0d-7e17-485f-9d4f-749a287193a6 /// Source Name: Microsoft-Windows-Audit-CVE or Audit-CVE /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-cveeventwrite LONG CveEventWrite( PCWSTR // CveId, PCWSTR AdditionalDetails ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "81CDC4A8-67B3-40AE-B492-89EF47BC5C4D")] public static extern Win32Error CveEventWrite([MarshalAs(UnmanagedType.LPWStr)] string CveId, [Optional, MarshalAs(UnmanagedType.LPWStr)] string AdditionalDetails); /// The DeleteAce function deletes an access control entry (ACE) from an access control list (ACL). /// A pointer to an ACL. The ACE specified by the dwAceIndex parameter is removed from this ACL. /// /// The ACE to delete. A value of zero corresponds to the first ACE in the ACL, a value of one to the second ACE, and so on. /// /// /// If the function succeeds, the function returns nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// /// /// An application can use the ACL_SIZE_INFORMATION structure retrieved by the GetAclInformation function to discover the size of the /// ACL and the number of ACEs it contains. The GetAce function retrieves information about an individual ACE. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-deleteace BOOL DeleteAce( PACL pAcl, DWORD // dwAceIndex ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "02ce45ad-3d51-4548-848e-a62bf4bf72a8")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool DeleteAce(PACL pAcl, uint dwAceIndex); /// /// This function constructs two arrays of SIDs out of a capability name. One is an array group SID with NT Authority, and the other /// is an array of capability SIDs with AppAuthority. /// /// Name of the capability in string form. /// The GroupSids with NTAuthority. /// The count of GroupSids in the array. /// CapabilitySids with AppAuthority. /// The count of CapabilitySid with AppAuthority. /// /// If the function succeeds, it returns TRUE. /// If the function fails, it returns FALSE. To get extended error information, call GetLastError. /// /// /// The caller is expected to free the individual SIDs returned in each array by calling LocalFree. as well as memory allocated for /// the array itself. /// // https://docs.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-derivecapabilitysidsfromname BOOL // DeriveCapabilitySidsFromName( LPCWSTR CapName, PSID **CapabilityGroupSids, DWORD *CapabilityGroupSidCount, PSID **CapabilitySids, // DWORD *CapabilitySidCount ); [DllImport(Lib.KernelBase, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "1A911FCC-6D11-4185-B532-20FE6C7C4B0B")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool DeriveCapabilitySidsFromName([MarshalAs(UnmanagedType.LPWStr)] string CapName, out SafePSIDArray CapabilityGroupSids, out int CapabilityGroupSidCount, out SafePSIDArray CapabilitySids, out int CapabilitySidCount); /// /// The DestroyPrivateObjectSecurity function deletes a private object's security descriptor. For background information, see /// the Security Descriptors for Private Objects topic. /// /// /// A pointer to a pointer to the SECURITY_DESCRIPTOR structure to be deleted. This security descriptor must have been created by a /// call to the CreatePrivateObjectSecurity function. /// /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-destroyprivateobjectsecurity BOOL // DestroyPrivateObjectSecurity( PSECURITY_DESCRIPTOR *ObjectDescriptor ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "4ef10852-8229-41de-a4d7-d2845e4c92ce")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool DestroyPrivateObjectSecurity(in PSECURITY_DESCRIPTOR ObjectDescriptor); /// The DuplicateToken function creates a new access token that duplicates one already in existence. /// A handle to an access token opened with TOKEN_DUPLICATE access. /// /// Specifies a SECURITY_IMPERSONATION_LEVEL enumerated type that supplies the impersonation level of the new token. /// /// /// /// A pointer to a variable that receives a handle to the duplicate token. This handle has TOKEN_IMPERSONATE and TOKEN_QUERY access /// to the new token. /// /// When you have finished using the new token, call the CloseHandle function to close the token handle. /// /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// // BOOL WINAPI DuplicateToken( _In_ HANDLE ExistingTokenHandle, _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, _Out_ PHANDLE // DuplicateTokenHandle); https://msdn.microsoft.com/en-us/library/windows/desktop/aa446616(v=vs.85).aspx [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "aa446616")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool DuplicateToken(HTOKEN ExistingTokenHandle, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, out SafeHTOKEN DuplicateTokenHandle); /// /// The DuplicateTokenEx function creates a new access token that duplicates an existing token. This function can create /// either a primary token or an impersonation token. /// /// A handle to an access token opened with TOKEN_DUPLICATE access. /// /// /// Specifies the requested access rights for the new token. The DuplicateTokenEx function compares the requested access /// rights with the existing token's discretionary access control list (DACL) to determine which rights are granted or denied. To /// request the same access rights as the existing token, specify zero. To request all access rights that are valid for the caller, /// specify MAXIMUM_ALLOWED. /// /// For a list of access rights for access tokens, see Access Rights for Access-Token Objects. /// /// /// /// A pointer to a SECURITY_ATTRIBUTES structure that specifies a security descriptor for the new token and determines whether /// child processes can inherit the token. If lpTokenAttributes is NULL, the token gets a default security descriptor and the /// handle cannot be inherited. If the security descriptor contains a system access control list (SACL), the token gets /// ACCESS_SYSTEM_SECURITY access right, even if it was not requested in dwDesiredAccess. /// /// /// To set the owner in the security descriptor for the new token, the caller's process token must have the SE_RESTORE_NAME /// privilege set. /// /// /// /// Specifies a value from the SECURITY_IMPERSONATION_LEVEL enumeration that indicates the impersonation level of the new token. /// /// /// Specifies one of the following values from the TOKEN_TYPE enumeration. /// /// /// /// Value /// Meaning /// /// /// TokenPrimary /// The new token is a primary token that you can use in the CreateProcessAsUser function. /// /// /// TokenImpersonation /// The new token is an impersonation token. /// /// /// /// /// /// A pointer to a HANDLE variable that receives the new token. /// When you have finished using the new token, call the CloseHandle function to close the token handle. /// /// /// If the function succeeds, the function returns a nonzero value. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// // BOOL WINAPI DuplicateTokenEx( _In_ HANDLE hExistingToken, _In_ DWORD dwDesiredAccess, _In_opt_ LPSECURITY_ATTRIBUTES // lpTokenAttributes, _In_ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, _In_ TOKEN_TYPE TokenType, _Out_ PHANDLE phNewToken); https://msdn.microsoft.com/en-us/library/windows/desktop/aa446617(v=vs.85).aspx [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "aa446617")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool DuplicateTokenEx(HTOKEN hExistingToken, TokenAccess dwDesiredAccess, [In, Optional] SECURITY_ATTRIBUTES lpTokenAttributes, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, TOKEN_TYPE TokenType, out SafeHTOKEN phNewToken); /// The FindFirstFreeAce function retrieves a pointer to the first free byte in an access control list (ACL). /// A pointer to an ACL. /// /// The address of a pointer to the first free position in the ACL created when the function returns. If the ACL is not valid, this /// parameter is NULL. If the ACL is full, this parameter points to the byte immediately following the ACL. /// /// /// If the function succeeds, the function returns nonzero. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-findfirstfreeace BOOL FindFirstFreeAce( // PACL pAcl, LPVOID *pAce ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "bf770761-008a-4a35-b31f-b781d5a8622b")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool FindFirstFreeAce(PACL pAcl, out PACE pAce); /// 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 a pointer that the function sets to the address of the ACE. /// /// If the function succeeds, the function returns nonzero. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-getace BOOL GetAce( PACL pAcl, DWORD // dwAceIndex, LPVOID *pAce ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "5b5d8751-20d7-40a2-bd70-cfbe956aaa03")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetAce(PACL pAcl, uint dwAceIndex, out PACE pAce); /// The GetAclInformation function retrieves information about an access control list (ACL). /// /// A pointer to an ACL. The function retrieves information about this ACL. If a null value is passed, the function causes an access violation. /// /// /// A pointer to a buffer to receive the requested information. The structure that is placed into the buffer depends on the /// information class requested in the dwAclInformationClass parameter. /// /// The size, in bytes, of the buffer pointed to by the pAclInformation parameter. /// /// A value of the ACL_INFORMATION_CLASS enumeration that indicates the class of information requested. This parameter can be one of /// two values from this enumeration: /// /// /// /// If the value is AclRevisionInformation, the function fills the buffer pointed to by the pAclInformation parameter with an /// ACL_REVISION_INFORMATION structure. /// /// /// /// If the value is AclSizeInformation, the function fills the buffer pointed to by the pAclInformation parameter with an /// ACL_SIZE_INFORMATION structure. /// /// /// /// /// /// If the function succeeds, the function returns nonzero. If the function fails, it returns zero. To get extended error /// information, call GetLastError. /// [DllImport(Lib.AdvApi32, ExactSpelling = true, SetLastError = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "aa446635")] public static extern bool GetAclInformation(PACL pAcl, IntPtr pAclInformation, uint nAclInformationLength, ACL_INFORMATION_CLASS dwAclInformationClass); /// The GetAclInformation function retrieves information about an access control list (ACL). /// /// A pointer to an ACL. The function retrieves information about this ACL. If a null value is passed, the function causes an access violation. /// /// /// A pointer to a buffer to receive the requested information. The structure that is placed into the buffer depends on the /// information class requested in the dwAclInformationClass parameter. /// /// The size, in bytes, of the buffer pointed to by the pAclInformation parameter. /// /// A value of the ACL_INFORMATION_CLASS enumeration that indicates the class of information requested. This parameter can be one of /// two values from this enumeration: /// /// /// /// If the value is AclRevisionInformation, the function fills the buffer pointed to by the pAclInformation parameter with an /// ACL_REVISION_INFORMATION structure. /// /// /// /// If the value is AclSizeInformation, the function fills the buffer pointed to by the pAclInformation parameter with an /// ACL_SIZE_INFORMATION structure. /// /// /// /// /// /// If the function succeeds, the function returns nonzero. If the function fails, it returns zero. To get extended error /// information, call GetLastError. /// [DllImport(Lib.AdvApi32, ExactSpelling = true, SetLastError = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "aa446635")] public static extern bool GetAclInformation(PACL pAcl, out ACL_REVISION_INFORMATION pAclInformation, uint nAclInformationLength = 4, ACL_INFORMATION_CLASS dwAclInformationClass = ACL_INFORMATION_CLASS.AclRevisionInformation); /// The GetAclInformation function retrieves information about an access control list (ACL). /// /// A pointer to an ACL. The function retrieves information about this ACL. If a null value is passed, the function causes an access violation. /// /// /// A pointer to a buffer to receive the requested information. The structure that is placed into the buffer depends on the /// information class requested in the dwAclInformationClass parameter. /// /// The size, in bytes, of the buffer pointed to by the pAclInformation parameter. /// /// A value of the ACL_INFORMATION_CLASS enumeration that indicates the class of information requested. This parameter can be one of /// two values from this enumeration: /// /// /// /// If the value is AclRevisionInformation, the function fills the buffer pointed to by the pAclInformation parameter with an /// ACL_REVISION_INFORMATION structure. /// /// /// /// If the value is AclSizeInformation, the function fills the buffer pointed to by the pAclInformation parameter with an /// ACL_SIZE_INFORMATION structure. /// /// /// /// /// /// If the function succeeds, the function returns nonzero. If the function fails, it returns zero. To get extended error /// information, call GetLastError. /// [DllImport(Lib.AdvApi32, ExactSpelling = true, SetLastError = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "aa446635")] public static extern bool GetAclInformation(PACL pAcl, out ACL_SIZE_INFORMATION pAclInformation, uint nAclInformationLength = 12, ACL_INFORMATION_CLASS dwAclInformationClass = ACL_INFORMATION_CLASS.AclSizeInformation); /// The GetAclInformation function retrieves information about an access control list (ACL). /// /// A pointer to an ACL. The function retrieves information about this ACL. If a null value is passed, the function causes an access violation. /// /// /// The requested information. The structure that is returned depends on the information class requested in the dwAclInformationClass parameter. /// public static T GetAclInformation(this PACL pAcl) where T : struct { if (!CorrespondingTypeAttribute.CanGet(out var c)) throw new ArgumentException("Cannot retrieve value of type T."); using var mem = new SafeCoTaskMemHandle(12); return GetAclInformation(pAcl, mem, (uint)Marshal.SizeOf(typeof(T)), c) ? mem.ToStructure() : throw new Win32Exception(); } /// The GetKernelObjectSecurity function retrieves a copy of the security descriptor that protects a kernel object. /// A handle to a kernel object. /// Specifies a SECURITY_INFORMATION value that identifies the security information being requested. /// /// A pointer to a buffer the function fills with a copy of the security descriptor of the specified object. The calling process must /// have the right to view the specified aspects of the object's security status. The SECURITY_DESCRIPTOR structure is returned in /// self-relative format. /// /// Specifies the size, in bytes, of the buffer pointed to by the pSecurityDescriptor parameter. /// /// A pointer to a variable that receives the number of bytes required for the buffer pointed to by the pSecurityDescriptor /// parameter. If this variable's value is greater than the value of the nLength parameter when the function returns, none of the /// security descriptor is copied to the buffer. /// /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// /// /// /// To read the owner, group, or DACL from the kernel object's security descriptor, the calling process must have been granted /// READ_CONTROL access when the handle was opened. To get READ_CONTROL access, the caller must be the owner of the object or the /// object's DACL must grant the access. /// /// /// To read the SACL from the security descriptor, the calling process must have been granted ACCESS_SYSTEM_SECURITY access when the /// handle was opened. The proper way to get this access is to enable the SE_SECURITY_NAME privilege in the caller's current token, /// open the handle for ACCESS_SYSTEM_SECURITY access, and then disable the privilege. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-getkernelobjectsecurity BOOL // GetKernelObjectSecurity( HANDLE Handle, SECURITY_INFORMATION RequestedInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD // nLength, LPDWORD lpnLengthNeeded ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "276e9657-5729-48cb-9531-14bfd08b7868")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetKernelObjectSecurity(HANDLE Handle, SECURITY_INFORMATION RequestedInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor, uint nLength, out uint lpnLengthNeeded); /// The GetPrivateObjectSecurity function retrieves information from a private object's security descriptor. /// A pointer to a SECURITY_DESCRIPTOR structure. This is the security descriptor to be queried. /// /// A set of bit flags that indicate the parts of the security descriptor to retrieve. This parameter can be a combination of the /// SECURITY_INFORMATION bit flags. /// /// /// A pointer to a buffer that receives a copy of the requested information from the specified security descriptor. The /// SECURITY_DESCRIPTOR structure is returned in self-relative format. /// /// Specifies the size, in bytes, of the buffer pointed to by the ResultantDescriptor parameter. /// /// A pointer to a variable the function sets to zero if the descriptor is copied successfully. If the buffer is too small for the /// security descriptor, this variable receives the number of bytes required. If this variable's value is greater than the value of /// the DescriptorLength parameter when the function returns, the function returns FALSE and none of the security descriptor is /// copied to the buffer. /// /// /// If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error /// information, call GetLastError. /// [DllImport(Lib.AdvApi32, ExactSpelling = true, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] [PInvokeData("securitybaseapi.h", MSDNShortId = "aa446646")] public static extern bool GetPrivateObjectSecurity(PSECURITY_DESCRIPTOR ObjectDescriptor, SECURITY_INFORMATION SecurityInformation, SafePSECURITY_DESCRIPTOR ResultantDescriptor, uint DescriptorLength, out uint ReturnLength); /// The GetPrivateObjectSecurity function retrieves information from a private object's security descriptor. /// A pointer to a SECURITY_DESCRIPTOR structure. This is the security descriptor to be queried. /// /// A set of bit flags that indicate the parts of the security descriptor to retrieve. This parameter can be a combination of the /// SECURITY_INFORMATION bit flags. /// /// /// The requested information from the specified security descriptor. The SECURITY_DESCRIPTOR structure is returned in self-relative format. /// public static SafePSECURITY_DESCRIPTOR GetPrivateObjectSecurity(this PSECURITY_DESCRIPTOR ObjectDescriptor, SECURITY_INFORMATION SecurityInformation) { var pResSD = SafePSECURITY_DESCRIPTOR.Null; if (!GetPrivateObjectSecurity(ObjectDescriptor, SecurityInformation, pResSD, 0, out var ret) && ret == 0) Win32Error.ThrowLastError(); pResSD = new SafePSECURITY_DESCRIPTOR((int)ret); if (!pResSD.IsInvalid && !GetPrivateObjectSecurity(ObjectDescriptor, SecurityInformation, pResSD, ret, out _)) Win32Error.ThrowLastError(); return pResSD; } /// The GetPrivateObjectSecurity function retrieves information from a private object's security descriptor. /// A pointer to a SECURITY_DESCRIPTOR structure. This is the security descriptor to be queried. /// /// A set of bit flags that indicate the parts of the security descriptor to retrieve. This parameter can be a combination of the /// SECURITY_INFORMATION bit flags. /// /// /// The requested information from the specified security descriptor. The SECURITY_DESCRIPTOR structure is returned in self-relative format. /// public static SafePSECURITY_DESCRIPTOR GetPrivateObjectSecurity(this SafePSECURITY_DESCRIPTOR ObjectDescriptor, SECURITY_INFORMATION SecurityInformation) => GetPrivateObjectSecurity((PSECURITY_DESCRIPTOR)ObjectDescriptor, SecurityInformation); /// /// Gets the required size of an ACE of the type specified by with the supplied security identifier (SID). /// /// The type of the ACE structure. /// The security identifier (SID) structure pointer. /// On return, the offset within the structure where the SID should be copied. /// The required size, in bytes, for this ACE. public static int GetRequiredAceSize(PSID pSid, out int sidOffset) where TAceStruct : struct { sidOffset = GetSize() - GetSize(); return sidOffset + pSid.Length(); } /// /// The GetSecurityDescriptorControl function retrieves a security descriptor control and revision information. /// /// /// A pointer to a SECURITY_DESCRIPTOR structure whose control and revision information the function retrieves. /// /// /// A pointer to a SECURITY_DESCRIPTOR_CONTROL structure that receives the security descriptor's control information. /// /// /// /// A pointer to a variable that receives the security descriptor's revision value. This value is always set, even when /// GetSecurityDescriptorControl returns an error. /// /// /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-getsecuritydescriptorcontrol BOOL // GetSecurityDescriptorControl( PSECURITY_DESCRIPTOR pSecurityDescriptor, PSECURITY_DESCRIPTOR_CONTROL pControl, LPDWORD // lpdwRevision ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "d66682f2-8017-4245-9d93-5f8332a5b483")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetSecurityDescriptorControl(PSECURITY_DESCRIPTOR pSecurityDescriptor, out SECURITY_DESCRIPTOR_CONTROL pControl, out SDDL_REVISION lpdwRevision); /// /// The GetSecurityDescriptorDacl function retrieves a pointer to the discretionary access control list (DACL) in a specified /// security descriptor. /// /// /// A pointer to the SECURITY_DESCRIPTOR structure that contains the DACL. The function retrieves a pointer to it. /// /// /// A pointer to a value that indicates the presence of a DACL in the specified security descriptor. If lpbDaclPresent is TRUE, the /// security descriptor contains a DACL, and the remaining output parameters in this function receive valid values. If lpbDaclPresent /// is FALSE, the security descriptor does not contain a DACL, and the remaining output parameters do not receive valid values. /// /// A value of TRUE for lpbDaclPresent does not mean that pDacl is not NULL. That is, lpbDaclPresent can be TRUE while pDacl is NULL, /// meaning that a NULL DACL is in effect. A NULL DACL implicitly allows all access to an object and is not the same as an empty /// DACL. An empty DACL permits no access to an object. For information about creating a proper DACL, see Creating a DACL. /// /// /// /// A pointer to a pointer to an access control list (ACL). If a DACL exists, the function sets the pointer pointed to by pDacl to /// the address of the security descriptor's DACL. If a DACL does not exist, no value is stored. /// /// If the function stores a NULL value in the pointer pointed to by pDacl, the security descriptor has a NULL DACL. A NULL DACL /// implicitly allows all access to an object. /// /// /// If an application expects a non-NULL DACL but encounters a NULL DACL, the application should fail securely and not allow access. /// /// /// /// A pointer to a flag set to the value of the SE_DACL_DEFAULTED flag in the SECURITY_DESCRIPTOR_CONTROL structure if a DACL exists /// for the security descriptor. If this flag is TRUE, the DACL was retrieved by a default mechanism; if FALSE, the DACL was /// explicitly specified by a user. /// /// /// If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error /// information, call GetLastError. /// [DllImport(Lib.AdvApi32, ExactSpelling = true, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] [PInvokeData("securitybaseapi.h", MSDNShortId = "aa446648")] public static extern bool GetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, [MarshalAs(UnmanagedType.Bool)] out bool lpbDaclPresent, out PACL pDacl, [MarshalAs(UnmanagedType.Bool)] out bool lpbDaclDefaulted); /// /// The GetSecurityDescriptorGroup function retrieves the primary group information from a security descriptor. /// /// /// A pointer to a SECURITY_DESCRIPTOR structure whose primary group information the function retrieves. /// /// /// /// A pointer to a pointer to a security identifier (SID) that identifies the primary group when the function returns. If the /// security descriptor does not contain a primary group, the function sets the pointer pointed to by pGroup to NULL and /// ignores the remaining output parameter, lpbGroupDefaulted. If the security descriptor contains a primary group, the function sets /// the pointer pointed to by pGroup to the address of the security descriptor's group SID and provides a valid value for the /// variable pointed to by lpbGroupDefaulted. /// /// /// /// /// A pointer to a flag that is set to the value of the SE_GROUP_DEFAULTED flag in the SECURITY_DESCRIPTOR_CONTROL structure when the /// function returns. If the value stored in the variable pointed to by the pGroup parameter is NULL, no value is set. /// /// /// /// If the function succeeds, the function returns nonzero. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-getsecuritydescriptorgroup BOOL // GetSecurityDescriptorGroup( PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID *pGroup, LPBOOL lpbGroupDefaulted ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "a920b49e-a4c2-4e49-b529-88c12205d995")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR pSecurityDescriptor, out PSID pGroup, [MarshalAs(UnmanagedType.Bool)] out bool lpbGroupDefaulted); /// /// The GetSecurityDescriptorLength function returns the length, in bytes, of a structurally valid security descriptor. The /// length includes the length of all associated structures. /// /// /// A pointer to the SECURITY_DESCRIPTOR structure whose length the function returns. The pointer is assumed to be valid. /// /// /// If the function succeeds, the function returns the length, in bytes, of the SECURITY_DESCRIPTOR structure. /// If the SECURITY_DESCRIPTOR structure is not valid, the return value is undefined. /// /// /// /// The minimum length of a security descriptor is SECURITY_DESCRIPTOR_MIN_LENGTH. A security descriptor of this length has no /// associated security identifiers (SIDs) or access control lists (ACLs). /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-getsecuritydescriptorlength DWORD // GetSecurityDescriptorLength( PSECURITY_DESCRIPTOR pSecurityDescriptor ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "eb331839-ff3e-4f4b-b93b-18da2ea72697")] public static extern uint GetSecurityDescriptorLength(PSECURITY_DESCRIPTOR pSecurityDescriptor); /// The GetSecurityDescriptorOwner function retrieves the owner information from a security descriptor. /// A pointer to a SECURITY_DESCRIPTOR structure whose owner information the function retrieves. /// /// A pointer to a pointer to a security identifier (SID) that identifies the owner when the function returns. If the security /// descriptor does not contain an owner, the function sets the pointer pointed to by pOwner to NULL and ignores the remaining output /// parameter, lpbOwnerDefaulted. If the security descriptor contains an owner, the function sets the pointer pointed to by pOwner to /// the address of the security descriptor's owner SID and provides a valid value for the variable pointed to by lpbOwnerDefaulted. /// /// /// A pointer to a flag that is set to the value of the SE_OWNER_DEFAULTED flag in the SECURITY_DESCRIPTOR_CONTROL structure when the /// function returns. If the value stored in the variable pointed to by the pOwner parameter is NULL, no value is set. /// /// /// If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error /// information, call GetLastError. /// [DllImport(Lib.AdvApi32, ExactSpelling = true, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] [PInvokeData("securitybaseapi.h", MSDNShortId = "aa446651")] public static extern bool GetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR pSecurityDescriptor, out PSID pOwner, [MarshalAs(UnmanagedType.Bool)] out bool lpbOwnerDefaulted); /// The GetSecurityDescriptorRMControl function retrieves the resource manager control bits. /// /// A pointer to a SECURITY_DESCRIPTOR structure that contains the resource manager control bits. The value of the Control /// member is set to SE_RM_CONTROL_VALID. /// /// A pointer to a buffer that receives the resource manager control bits. /// /// If the function succeeds, the return value is ERROR_SUCCESS. /// If the function fails, the following value is returned. /// /// /// Return code /// Description /// /// /// ERROR_INVALID_DATA /// The SE_RM_CONTROL_VALID bit flag is not set in the specified SECURITY_DESCRIPTOR structure. /// /// /// /// /// The resource manager control bits are eight bits in the Sbz1 member of the SECURITY_DESCRIPTOR structure that contains /// information specific to the resource manager accessing the structure. These bits should be accessed only through the /// GetSecurityDescriptorRMControl and SetSecurityDescriptorRMControl functions. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-getsecuritydescriptorrmcontrol DWORD // GetSecurityDescriptorRMControl( PSECURITY_DESCRIPTOR SecurityDescriptor, PUCHAR RMControl ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "a1e2ce12-586b-4011-a82d-e246d5544367")] public static extern uint GetSecurityDescriptorRMControl(PSECURITY_DESCRIPTOR SecurityDescriptor, out byte RMControl); /// /// /// The GetSecurityDescriptorSacl function retrieves a pointer to the system access control list (SACL) in a specified /// security descriptor. /// /// /// /// A pointer to the SECURITY_DESCRIPTOR structure that contains the SACL to which the function retrieves a pointer. /// /// /// /// A pointer to a flag the function sets to indicate the presence of a SACL in the specified security descriptor. If this parameter /// is TRUE, the security descriptor contains a SACL, and the remaining output parameters in this function receive valid /// values. If this parameter is FALSE, the security descriptor does not contain a SACL, and the remaining output parameters /// do not receive valid values. /// /// /// /// /// A pointer to a pointer to an access control list (ACL). If a SACL exists, the function sets the pointer pointed to by pSacl to /// the address of the security descriptor's SACL. If a SACL does not exist, no value is stored. /// /// /// If the function stores a NULL value in the pointer pointed to by pSacl, the security descriptor has a NULL SACL. /// /// /// /// /// A pointer to a flag that is set to the value of the SE_SACL_DEFAULTED flag in the SECURITY_DESCRIPTOR_CONTROL structure if a SACL /// exists for the security descriptor. /// /// /// /// If the function succeeds, the function returns nonzero. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-getsecuritydescriptorsacl BOOL // GetSecurityDescriptorSacl( PSECURITY_DESCRIPTOR pSecurityDescriptor, LPBOOL lpbSaclPresent, PACL *pSacl, LPBOOL lpbSaclDefaulted ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "6bf59735-aaa3-4751-8c98-00cc197df4e5")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetSecurityDescriptorSacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, [MarshalAs(UnmanagedType.Bool)] out bool lpbSaclPresent, out PACL pSacl, [MarshalAs(UnmanagedType.Bool)] out bool lpbSaclDefaulted); /// /// /// The GetTokenInformation function retrieves a specified type of information about an access token. The calling process /// must have appropriate access rights to obtain the information. /// /// /// To determine if a user is a member of a specific group, use the CheckTokenMembership function. To determine group membership for /// app container tokens, use the CheckTokenMembershipEx function. /// /// /// /// A handle to an access token from which information is retrieved. If TokenInformationClass specifies TokenSource, the handle must /// have TOKEN_QUERY_SOURCE access. For all other TokenInformationClass values, the handle must have TOKEN_QUERY access. /// /// /// Specifies a value from the TOKEN_INFORMATION_CLASS enumerated type to identify the type of information the function retrieves. /// Any callers who check the TokenIsAppContainer and have it return 0 should also verify that the caller token is not an /// identify level impersonation token. If the current token is not an app container but is an identity level token, you should /// return AccessDenied. /// /// /// A pointer to a buffer the function fills with the requested information. The structure put into this buffer depends upon the /// type of information specified by the TokenInformationClass parameter. /// /// /// Specifies the size, in bytes, of the buffer pointed to by the TokenInformation parameter. If TokenInformation is NULL, /// this parameter must be zero. /// /// /// /// A pointer to a variable that receives the number of bytes needed for the buffer pointed to by the TokenInformation parameter. If /// this value is larger than the value specified in the TokenInformationLength parameter, the function fails and stores no data in /// the buffer. /// /// /// If the value of the TokenInformationClass parameter is TokenDefaultDacl and the token has no default DACL, the function sets the /// variable pointed to by ReturnLength to /// sizeof( /// TOKEN_DEFAULT_DACL /// ) /// and sets the DefaultDacl member of the TOKEN_DEFAULT_DACL structure to NULL. /// /// /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-gettokeninformation // BOOL GetTokenInformation( HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength, PDWORD ReturnLength ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [return: MarshalAs(UnmanagedType.Bool)] [PInvokeData("securitybaseapi.h", MSDNShortId = "NF:securitybaseapi.GetTokenInformation")] public static extern bool GetTokenInformation(HTOKEN TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, IntPtr TokenInformation, int TokenInformationLength, out int ReturnLength); /// /// /// The GetTokenInformation function retrieves a specified type of information about an access token. The calling process /// must have appropriate access rights to obtain the information. /// /// /// To determine if a user is a member of a specific group, use the CheckTokenMembership function. To determine group membership for /// app container tokens, use the CheckTokenMembershipEx function. /// /// /// The type of the structure to retrive. /// /// A handle to an access token from which information is retrieved. If TokenInformationClass specifies TokenSource, the handle must /// have TOKEN_QUERY_SOURCE access. For all other TokenInformationClass values, the handle must have TOKEN_QUERY access. /// /// /// Specifies a value from the TOKEN_INFORMATION_CLASS enumerated type to identify the type of information the function retrieves. /// Any callers who check the TokenIsAppContainer and have it return 0 should also verify that the caller token is not an /// identity level impersonation token. If the current token is not an app container but is an identity level token, you should /// return AccessDenied. /// /// If this value is , the value returned will be the first member of TOKEN_INFORMATION_CLASS that /// returns the type specified in . /// /// /// The requested information. /// // https://docs.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-gettokeninformation // BOOL GetTokenInformation( HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength, PDWORD ReturnLength ); [PInvokeData("securitybaseapi.h", MSDNShortId = "NF:securitybaseapi.GetTokenInformation")] public static T GetTokenInformation(HTOKEN TokenHandle, TOKEN_INFORMATION_CLASS? TokenInformationClass = null) where T : struct { if (!CorrespondingTypeAttribute.CanGet(TokenInformationClass, out var ti)) throw new InvalidCastException(); // Get information size if (!GetTokenInformation(TokenHandle, ti, default, 0, out var cbSize)) { var e = Win32Error.GetLastError(); if (e != Win32Error.ERROR_INSUFFICIENT_BUFFER && e != Win32Error.ERROR_BAD_LENGTH) e.ThrowIfFailed(); } // Retrieve token information. using var pType = new SafeCoTaskMemStruct(cbSize); Win32Error.ThrowLastErrorIfFalse(GetTokenInformation(TokenHandle, ti, pType, cbSize, out _)); return pType.Value; } /// /// The ImpersonateAnonymousToken function enables the specified thread to impersonate the system's anonymous logon token. To /// ensure that a token matches the operating system's concept of anonymous access, this function should be called before attempting /// network access to generate an anonymous token on the remote server. /// /// A handle to the thread to impersonate the system's anonymous logon token. /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// /// An error of ACCESS_DENIED may indicate that the token is for a restricted process. Use OpenProcessToken and IsTokenRestricted to /// check if the process is restricted. /// /// /// /// /// Anonymous tokens do not include the Everyone Group SID unless the system default has been overridden by setting the /// HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\EveryoneIncludesAnonymous registry value to DWORD=1. /// /// To cancel the impersonation call RevertToSelf. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-impersonateanonymoustoken BOOL // ImpersonateAnonymousToken( HANDLE ThreadHandle ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "98d1072e-f569-4c8c-9254-fa558054c7ec")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool ImpersonateAnonymousToken(HTHREAD ThreadHandle); /// /// /// The ImpersonateLoggedOnUser function lets the calling thread impersonate the security context of a logged-on user. The /// user is represented by a token handle. /// /// /// /// /// A handle to a primary or impersonation access token that represents a logged-on user. This can be a token handle returned by a /// call to LogonUser, CreateRestrictedToken, DuplicateToken, DuplicateTokenEx, OpenProcessToken, or OpenThreadToken functions. If /// hToken is a handle to a primary token, the token must have TOKEN_QUERY and TOKEN_DUPLICATE access. If hToken is a /// handle to an impersonation token, the token must have TOKEN_QUERY and TOKEN_IMPERSONATE access. /// /// /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// /// /// The impersonation lasts until the thread exits or until it calls RevertToSelf. /// The calling thread does not need to have any particular privileges to call ImpersonateLoggedOnUser. /// /// If the call to ImpersonateLoggedOnUser fails, the client connection is not impersonated and the client request is made in /// the security context of the process. If the process is running as a highly privileged account, such as LocalSystem, or as a /// member of an administrative group, the user may be able to perform actions they would otherwise be disallowed. Therefore, it is /// important to always check the return value of the call, and if it fails, raise an error; do not continue execution of the client request. /// /// /// All impersonate functions, including ImpersonateLoggedOnUser allow the requested impersonation if one of the following is true: /// /// /// /// /// The requested impersonation level of the token is less than SecurityImpersonation, such as SecurityIdentification /// or SecurityAnonymous. /// /// /// /// The caller has the SeImpersonatePrivilege privilege. /// /// /// /// A process (or another process in the caller's logon session) created the token using explicit credentials through LogonUser or /// LsaLogonUser function. /// /// /// /// The authenticated identity is same as the caller. /// /// /// Windows XP with SP1 and earlier: The SeImpersonatePrivilege privilege is not supported. /// For more information about impersonation, see Client Impersonation. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-impersonateloggedonuser BOOL // ImpersonateLoggedOnUser( HANDLE hToken ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "cf5c31ae-6749-45c2-888f-697060cc8c75")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool ImpersonateLoggedOnUser(HTOKEN hToken); /// /// The ImpersonateSelf function obtains an access token that impersonates the security context of the calling process. The /// token is assigned to the calling thread. /// /// /// Specifies a SECURITY_IMPERSONATION_LEVEL enumerated type that supplies the impersonation level of the new token. /// /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// /// /// /// The ImpersonateSelf function is used for tasks such as enabling a privilege for a single thread rather than for the entire /// process or for changing the default discretionary access control list (DACL) for a single thread. /// /// The server can call the RevertToSelf function when the impersonation is complete. /// For this function to succeed, the DACL protecting the process token must grant the TOKEN_DUPLICATE right to itself. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-impersonateself BOOL ImpersonateSelf( // SECURITY_IMPERSONATION_LEVEL ImpersonationLevel ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "f909e3a7-6c7f-4c05-aa2e-e637113804c9")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel); /// The InitializeAcl function initializes a new ACL structure. /// /// A pointer to an ACL structure to be initialized by this function. Allocate memory for pAcl before calling this function. /// /// /// The length, in bytes, of the buffer pointed to by the pAcl parameter. This value must be large enough to contain the ACL header /// and all of the access control entries (ACEs) to be stored in the ACL. In addition, this value must be /// DWORD-aligned. For more information about calculating the size of an ACL, see Remarks. /// /// /// The revision level of the ACL structure being created. /// /// This value can be ACL_REVISION or ACL_REVISION_DS. Use ACL_REVISION_DS if the access control list (ACL) supports object-specific ACEs. /// /// /// /// If the function succeeds, the function returns nonzero. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// /// /// /// The InitializeAcl function creates an empty ACL structure; the ACL contains no ACEs. Applying an empty ACL /// to an object denies all access to that object. /// /// /// The initial size of the ACL depends on the number of ACEs you plan to add to the ACL before you use it. For example, if /// the ACL is to contain an ACE for a user and group, you would initialize the ACL based on two ACEs. For details /// about modifying an existing ACL, see Modifying the ACLs of an Object. /// /// To calculate the initial size of an ACL, add the following together, and then align the result to the nearest DWORD: /// /// /// Size of the ACL structure. /// /// /// Size of each ACE structure that the ACL is to contain minus the SidStart member ( DWORD) of the ACE. /// /// /// Length of the SID that each ACE is to contain. /// /// /// Examples /// /// The following example calls the InitializeAcl function. The size of the ACL is based on three allow-access ACEs. As an /// option, you can use security descriptor definition language (SDDL) to create the ACL. For details, see Creating a DACL. /// /// /// The example also omits a step for simplification. For more information, see the Taking Object Ownership example. You must call /// the FreeSid function at the end of the example code due to calling the AllocateAndInitializeSid function. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-initializeacl BOOL InitializeAcl( PACL // pAcl, DWORD nAclLength, DWORD dwAclRevision ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "b990a7bd-7840-4c10-baf8-68b3862147f4")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool InitializeAcl(PACL pAcl, uint nAclLength, uint dwAclRevision); /// The InitializeSecurityDescriptor function initializes a new security descriptor. /// A pointer to a SECURITY_DESCRIPTOR structure that the function initializes. /// The revision level to assign to the security descriptor. This parameter must be SECURITY_DESCRIPTOR_REVISION. /// /// If the function succeeds, the function returns nonzero. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// /// /// /// The InitializeSecurityDescriptor function initializes a security descriptor in absolute format, rather than self-relative format. /// /// /// The InitializeSecurityDescriptor function initializes a security descriptor to have no system access control list (SACL), /// no discretionary access control list (DACL), no owner, no primary group, and all control flags set to FALSE ( /// NULL). Thus, except for its revision level, it is empty. /// /// Examples /// For an example that uses this function, see Creating a Security Descriptor for a New Object. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-initializesecuritydescriptor BOOL // InitializeSecurityDescriptor( PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "234fcda4-7d30-4c3f-a036-7ace58ca8a3c")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor, uint dwRevision); /// /// The InsertAccessAllowedAce function inserts an access-allowed access control entry (ACE) into a discretionary access /// control list (DACL). /// /// /// A pointer to a DACL. The AddAccessAllowedAceEx function adds an access-allowed ACE to the end of this DACL. The ACE is in /// the form of an ACCESS_ALLOWED_ACE structure. /// /// /// Specifies the revision level of the DACL being modified. This value can be ACL_REVISION or ACL_REVISION_DS. Use ACL_REVISION_DS /// if the DACL contains object-specific ACEs. /// /// /// Specifies the position in the ACL's list of ACEs at which to add new ACEs. A value of zero inserts the ACEs at the beginning of /// the list. A value of MAXDWORD appends the ACEs to the end of the list. /// /// /// /// A set of bit flags that control ACE inheritance. The function sets these flags in the AceFlags member of the ACE_HEADER /// structure of the new ACE. This parameter can be a combination of the following values. /// /// /// /// Value /// Meaning /// /// /// CONTAINER_INHERIT_ACE /// The ACE is inherited by container objects. /// /// /// INHERIT_ONLY_ACE /// /// The ACE does not apply to the object to which the access control list (ACL) is assigned, but it can be inherited by child objects. /// /// /// /// INHERITED_ACE /// /// Indicates an inherited ACE. This flag allows operations that change the security on a tree of objects to modify inherited ACEs /// while not changing ACEs that were directly applied to the object. /// /// /// /// NO_PROPAGATE_INHERIT_ACE /// The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE bits are not propagated to an inherited ACE. /// /// /// OBJECT_INHERIT_ACE /// The ACE is inherited by non-container objects. /// /// /// /// /// A set of bit flags that use the ACCESS_MASK format. These flags specify the access rights that the new ACE allows for the /// specified security identifier (SID). /// /// A pointer to a SID that identifies the user, group, or logon session to which the new ACE allows access. /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. The following are possible /// error values. /// /// /// /// Return code /// Description /// /// /// ERROR_ALLOTTED_SPACE_EXCEEDED /// The new ACE does not fit into the ACL. A larger ACL buffer is required. /// /// /// ERROR_INVALID_ACL /// The specified ACL is not properly formed. /// /// /// ERROR_INVALID_FLAGS /// The AceFlags parameter is not valid. /// /// /// ERROR_INVALID_SID /// The specified SID is not structurally valid. /// /// /// ERROR_REVISION_MISMATCH /// The specified revision is not known or is incompatible with that of the ACL. /// /// /// ERROR_SUCCESS /// The ACE was successfully added. /// /// /// /// /// The caller must ensure that ACEs are added to the DACL in the correct order. For more information, see Order of ACEs in a DACL. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-addaccessallowedaceex BOOL // AddAccessAllowedAceEx( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, PSID pSid ); [PInvokeData("securitybaseapi.h", MSDNShortId = "6ddec01f-237f-4b6a-8ea8-a126017b30c5")] public static bool InsertAccessAllowedAce(PACL pAcl, uint dwAceRevision, uint dwStartingAceIndex, AceFlags AceFlags, ACCESS_MASK AccessMask, PSID pSid) { using var aceMem = new SafeHeapBlock(GetRequiredAceSize(pSid, out var offset)); // Build ACE var ace = new ACCESS_ALLOWED_ACE { Header = new ACE_HEADER(AceType.AccessAllowed, AceFlags, aceMem.Size), Mask = AccessMask }; Marshal.StructureToPtr(ace, aceMem, false); if (!CopySid(pSid.Length(), ((IntPtr)aceMem).Offset(offset), pSid)) return false; // Insert return AddAce(pAcl, dwAceRevision, dwStartingAceIndex, aceMem, aceMem.Size); } /// /// The InsertAccessAllowedObjectAce function inserts an access-allowed access control entry (ACE) intto a discretionary /// access control list (DACL). The new ACE can grant access to an object, or to a property set or property on an object. You can /// also use InsertAccessAllowedObjectAce to add an ACE that only a specified type of child object can inherit. /// /// /// A pointer to a DACL. The AddAccessAllowedObjectAce function adds an access-allowed ACE to the end of this DACL. The ACE is /// in the form of an ACCESS_ALLOWED_OBJECT_ACE structure. /// /// /// Specifies the revision level of the DACL being modified. This value must be ACL_REVISION_DS. If the DACL's revision level is /// lower than ACL_REVISION_DS, the function changes it to ACL_REVISION_DS. /// /// /// Specifies the position in the ACL's list of ACEs at which to add new ACEs. A value of zero inserts the ACEs at the beginning of /// the list. A value of MAXDWORD appends the ACEs to the end of the list. /// /// /// /// A set of bit flags that control ACE inheritance. The function sets these flags in the AceFlags member of the ACE_HEADER /// structure of the new ACE. This parameter can be a combination of the following values. /// /// /// /// Value /// Meaning /// /// /// CONTAINER_INHERIT_ACE /// The ACE is inherited by container objects. /// /// /// INHERIT_ONLY_ACE /// /// The ACE does not apply to the object to which the access control list (ACL) is assigned, but it can be inherited by child objects. /// /// /// /// INHERITED_ACE /// /// Indicates an inherited ACE. This flag allows operations that change the security on a tree of objects to modify inherited ACEs, /// while not changing ACEs that were directly applied to the object. /// /// /// /// NO_PROPAGATE_INHERIT_ACE /// The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE bits are not propagated to an inherited ACE. /// /// /// OBJECT_INHERIT_ACE /// The ACE is inherited by non-container objects. /// /// /// /// /// A set of bit flags that use the ACCESS_MASK format. These flags specify the access rights that the new ACE allows for the /// specified security identifier (SID). /// /// /// A pointer to a GUID structure that identifies the type of object, property set, or property protected by the new ACE. If this /// parameter is NULL, the new ACE protects the object to which the DACL is assigned. /// /// /// A pointer to a GUID structure that identifies the type of object that can inherit the new ACE. If this parameter is non- /// NULL, only the specified object type can inherit the ACE. If NULL, any type of child object can inherit the ACE. In /// either case, inheritance is also controlled by the value of the AceFlags parameter, as well as by any protection against /// inheritance placed on the child objects. /// /// A pointer to a SID that identifies the user, group, or logon session to which the new ACE allows access. /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. The following are possible /// error values. /// /// /// /// Return code /// Description /// /// /// ERROR_ALLOTTED_SPACE_EXCEEDED /// The new ACE does not fit into the ACL. A larger ACL buffer is required. /// /// /// ERROR_INVALID_ACL /// The specified ACL is not properly formed. /// /// /// ERROR_INVALID_FLAGS /// The AceFlags parameter is not valid. /// /// /// ERROR_INVALID_SID /// The specified SID is not structurally valid. /// /// /// ERROR_REVISION_MISMATCH /// The specified revision is not known or is incompatible with that of the ACL. /// /// /// ERROR_SUCCESS /// The ACE was successfully added. /// /// /// /// /// /// If both ObjectTypeGuid and InheritedObjectTypeGuid are NULL, use the AddAccessAllowedAceEx function rather than /// AddAccessAllowedObjectAce. This is suggested because an ACCESS_ALLOWED_ACE is smaller and more efficient than an ACCESS_ALLOWED_OBJECT_ACE. /// /// /// The caller must ensure that ACEs are added to the DACL in the correct order. For more information, see Order of ACEs in a DACL. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-addaccessallowedobjectace BOOL // AddAccessAllowedObjectAce( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, GUID *ObjectTypeGuid, GUID // *InheritedObjectTypeGuid, PSID pSid ); [PInvokeData("securitybaseapi.h", MSDNShortId = "ccf83e95-ba6f-49f5-a312-52eac90f209a")] public static bool InsertAccessAllowedObjectAce(PACL pAcl, uint dwAceRevision, uint dwStartingAceIndex, AceFlags AceFlags, ACCESS_MASK AccessMask, Guid? ObjectTypeGuid, Guid? InheritedObjectTypeGuid, PSID pSid) { using var aceMem = new SafeHeapBlock(GetRequiredAceSize(pSid, out var offset)); // Build ACE var ace = new ACCESS_ALLOWED_OBJECT_ACE { Header = new ACE_HEADER(AceType.AccessAllowedObject, AceFlags, aceMem.Size), Mask = AccessMask, Flags = (ObjectTypeGuid.HasValue ? ObjectAceFlags.ACE_OBJECT_TYPE_PRESENT : 0) | (InheritedObjectTypeGuid.HasValue ? ObjectAceFlags.ACE_INHERITED_OBJECT_TYPE_PRESENT : 0), ObjectType = ObjectTypeGuid.GetValueOrDefault(), InheritedObjectType = InheritedObjectTypeGuid.GetValueOrDefault(), }; Marshal.StructureToPtr(ace, aceMem, false); if (!CopySid(pSid.Length(), ((IntPtr)aceMem).Offset(offset), pSid)) return false; // Insert return AddAce(pAcl, dwAceRevision, dwStartingAceIndex, aceMem, aceMem.Size); } /// /// The InsertAccessDeniedAce function inserts an access-denied access control entry (ACE) into a discretionary access control /// list (DACL). /// /// A pointer to a DACL. The ACE is in the form of an ACCESS_DENIED_ACE structure. /// /// Specifies the revision level of the DACL being modified. This value can be ACL_REVISION or ACL_REVISION_DS. Use ACL_REVISION_DS /// if the DACL contains object-specific ACEs. /// /// /// Specifies the position in the ACL's list of ACEs at which to add new ACEs. A value of zero inserts the ACEs at the beginning of /// the list. A value of MAXDWORD appends the ACEs to the end of the list. /// /// /// /// A set of bit flags that control ACE inheritance. The function sets these flags in the AceFlags member of the ACE_HEADER /// structure of the new ACE. This parameter can be a combination of the following values. /// /// /// /// Value /// Meaning /// /// /// CONTAINER_INHERIT_ACE /// The ACE is inherited by container objects. /// /// /// INHERIT_ONLY_ACE /// /// The ACE does not apply to the object to which the access control list (ACL) is assigned, but it can be inherited by child objects. /// /// /// /// INHERITED_ACE /// /// Indicates an inherited ACE. This flag allows operations that change the security on a tree of objects to modify inherited ACEs, /// while not changing ACEs that were directly applied to the object. /// /// /// /// NO_PROPAGATE_INHERIT_ACE /// The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE bits are not propagated to an inherited ACE. /// /// /// OBJECT_INHERIT_ACE /// The ACE is inherited by non-container objects. /// /// /// /// /// A set of bit flags that use the ACCESS_MASK format to specify the access rights that the new ACE denies to the specified security /// identifier (SID). /// /// A pointer to a SID that identifies the user, group, or logon session to which the new ACE denies access. /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. The following are possible /// error values. /// /// /// /// Return code /// Description /// /// /// ERROR_ALLOTTED_SPACE_EXCEEDED /// The new ACE does not fit into the ACL. A larger ACL buffer is required. /// /// /// ERROR_INVALID_ACL /// The specified ACL is not properly formed. /// /// /// ERROR_INVALID_FLAGS /// The AceFlags parameter is not valid. /// /// /// ERROR_INVALID_SID /// The specified SID is not structurally valid. /// /// /// ERROR_REVISION_MISMATCH /// The specified revision is not known or is incompatible with that of the ACL. /// /// /// ERROR_SUCCESS /// The ACE was successfully added. /// /// /// /// /// Although the AddAccessDeniedAceEx function adds the new ACE to the end of the DACL, access-denied ACEs should appear at /// the beginning of a DACL. The caller must ensure that ACEs are added to the DACL in the correct order. For more information, see /// Order of ACEs in a DACL. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-addaccessdeniedaceex BOOL // AddAccessDeniedAceEx( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, PSID pSid ); [PInvokeData("securitybaseapi.h", MSDNShortId = "e353c88c-f82e-40c0-b676-38f0060acc81")] public static bool InsertAccessDeniedAce(PACL pAcl, uint dwAceRevision, uint dwStartingAceIndex, AceFlags AceFlags, ACCESS_MASK AccessMask, PSID pSid) { using var aceMem = new SafeHeapBlock(GetRequiredAceSize(pSid, out var offset)); // Build ACE var ace = new ACCESS_DENIED_ACE { Header = new ACE_HEADER(AceType.AccessDenied, AceFlags, aceMem.Size), Mask = AccessMask, }; Marshal.StructureToPtr(ace, aceMem, false); if (!CopySid(pSid.Length(), ((IntPtr)aceMem).Offset(offset), pSid)) return false; // Insert return AddAce(pAcl, dwAceRevision, dwStartingAceIndex, aceMem, aceMem.Size); } /// /// The InsertAccessDeniedObjectAce function inserts an access-denied access control entry (ACE) into a discretionary access /// control list (DACL). The new ACE can deny access to an object, or to a property set or property on an object. You can also use /// AddAccessDeniedObjectAce to add an ACE that only a specified type of child object can inherit. /// /// /// A pointer to a DACL. The AddAccessDeniedObjectAce function adds an access-denied ACE to the end of this DACL. The ACE is /// in the form of an ACCESS_DENIED_OBJECT_ACE structure. /// /// /// Specifies the revision level of the DACL being modified. This value must be ACL_REVISION_DS. If the DACL's revision level is /// lower than ACL_REVISION_DS, the function changes it to ACL_REVISION_DS. /// /// /// Specifies the position in the ACL's list of ACEs at which to add new ACEs. A value of zero inserts the ACEs at the beginning of /// the list. A value of MAXDWORD appends the ACEs to the end of the list. /// /// /// /// A set of bit flags that control ACE inheritance. The function sets these flags in the AceFlags member of the ACE_HEADER /// structure of the new ACE. This parameter can be a combination of the following values. /// /// /// /// Value /// Meaning /// /// /// CONTAINER_INHERIT_ACE /// The ACE is inherited by container objects. /// /// /// INHERIT_ONLY_ACE /// /// The ACE does not apply to the object to which the access control list (ACL) is assigned, but it can be inherited by child objects. /// /// /// /// INHERITED_ACE /// /// Indicates an inherited ACE. This flag allows operations that change the security on a tree of objects to modify inherited ACEs, /// while not changing ACEs that were directly applied to the object. /// /// /// /// NO_PROPAGATE_INHERIT_ACE /// The OBJECT_INHERIT_ACE and CONTAINER_INHERIT_ACE bits are not propagated to an inherited ACE. /// /// /// OBJECT_INHERIT_ACE /// The ACE is inherited by non-container objects. /// /// /// /// /// A set of bit flags that use the ACCESS_MASK format to specify the access rights that the new ACE denies to the specified security /// identifier (SID). /// /// /// A pointer to a GUID structure that identifies the type of object, property set, or property protected by the new ACE. If this /// parameter is NULL, the new ACE protects the object to which the ACL is assigned. /// /// /// A pointer to a GUID structure that identifies the type of object that can inherit the new ACE. If this parameter is non- /// NULL, only the specified object type can inherit the ACE. If NULL, any type of child object can inherit the ACE. In /// either case, inheritance is also controlled by the value of the AceFlags parameter, as well as by any protection against /// inheritance placed on the child objects. /// /// A pointer to a SID that identifies the user, group, or logon session to which the new ACE allows access. /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. The following are possible /// error values. /// /// /// /// Return code /// Description /// /// /// ERROR_ALLOTTED_SPACE_EXCEEDED /// The new ACE does not fit into the ACL. A larger ACL buffer is required. /// /// /// ERROR_INVALID_ACL /// The specified ACL is not properly formed. /// /// /// ERROR_INVALID_FLAGS /// The AceFlags parameter is not valid. /// /// /// ERROR_INVALID_SID /// The specified SID is not structurally valid. /// /// /// ERROR_REVISION_MISMATCH /// The specified revision is not known or is incompatible with that of the ACL. /// /// /// ERROR_SUCCESS /// The ACE was successfully added. /// /// /// /// /// /// If both ObjectTypeGuid and InheritedObjectTypeGuid are NULL, use the AddAccessDeniedAceEx function rather than /// AddAccessDeniedObjectAce. This is suggested because an ACCESS_DENIED_ACE is smaller and more efficient than an ACCESS_DENIED_OBJECT_ACE. /// /// /// Although the AddAccessDeniedObjectAce function adds the new ACE to the end of the ACL, access-denied ACEs should appear at /// the beginning of an ACL. The caller must ensure that ACEs are added to the DACL in the correct order. For more information, see /// Order of ACEs in a DACL. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-addaccessdeniedobjectace BOOL // AddAccessDeniedObjectAce( PACL pAcl, DWORD dwAceRevision, DWORD AceFlags, DWORD AccessMask, GUID *ObjectTypeGuid, GUID // *InheritedObjectTypeGuid, PSID pSid ); [PInvokeData("securitybaseapi.h", MSDNShortId = "1427c908-92b6-46b2-9189-a2fd93c470b1")] public static bool InsertAccessDeniedObjectAce(PACL pAcl, uint dwAceRevision, uint dwStartingAceIndex, AceFlags AceFlags, ACCESS_MASK AccessMask, Guid? ObjectTypeGuid, Guid? InheritedObjectTypeGuid, PSID pSid) { using var aceMem = new SafeHeapBlock(GetRequiredAceSize(pSid, out var offset)); // Build ACE var ace = new ACCESS_DENIED_OBJECT_ACE { Header = new ACE_HEADER(AceType.AccessDeniedObject, AceFlags, aceMem.Size), Mask = AccessMask, Flags = (ObjectTypeGuid.HasValue ? ObjectAceFlags.ACE_OBJECT_TYPE_PRESENT : 0) | (InheritedObjectTypeGuid.HasValue ? ObjectAceFlags.ACE_INHERITED_OBJECT_TYPE_PRESENT : 0), ObjectType = ObjectTypeGuid.GetValueOrDefault(), InheritedObjectType = InheritedObjectTypeGuid.GetValueOrDefault(), }; Marshal.StructureToPtr(ace, aceMem, false); if (!CopySid(pSid.Length(), ((IntPtr)aceMem).Offset(offset), pSid)) return false; // Insert return AddAce(pAcl, dwAceRevision, dwStartingAceIndex, aceMem, aceMem.Size); } /// /// The IsTokenRestricted function indicates whether a token contains a list of restricted security identifiers (SIDs). /// /// A handle to an access token to test. /// /// If the token contains a list of restricting SIDs, the return value is nonzero. /// If the token does not contain a list of restricting SIDs, the return value is zero. /// If an error occurs, the return value is zero. To get extended error information, call GetLastError. /// /// /// The CreateRestrictedToken function can restrict a token by disabling SIDs, deleting privileges, and specifying a list of /// restricting SIDs. The IsTokenRestricted function checks only for the list of restricting SIDs. If a token does not have /// any restricting SIDs, IsTokenRestricted returns FALSE, even though the token was created by a call to CreateRestrictedToken. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-istokenrestricted BOOL IsTokenRestricted( // HANDLE TokenHandle ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "eaa63bb9-3084-4246-b2ab-f913bb7348fb")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool IsTokenRestricted(HTOKEN TokenHandle); /// The IsValidAcl function validates an access control list (ACL). /// A pointer to an ACL structure validated by this function. This value must not be NULL. /// /// If the ACL is valid, the function returns nonzero. /// /// If the ACL is not valid, the function returns zero. There is no extended error information for this function; do not call GetLastError. /// /// /// /// /// This function checks the revision level of the ACL and verifies that the number of access control entries (ACEs) specified in the /// AceCount member of the ACL structure fits the space specified by the AclSize member of the ACL structure. /// /// If pAcl is NULL, the application will fail with an access violation. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-isvalidacl BOOL IsValidAcl( PACL pAcl ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "3ae9f147-4e90-44df-a1af-cf6ebad92aea")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool IsValidAcl(PACL pAcl); /// The IsValidSecurityDescriptor function determines whether the components of a security descriptor are valid. /// A pointer to a SECURITY_DESCRIPTOR structure that the function validates. /// /// If the components of the security descriptor are valid, the return value is nonzero. /// /// If any of the components of the security descriptor are not valid, the return value is zero. There is no extended error /// information for this function; do not call GetLastError. /// /// /// /// The IsValidSecurityDescriptor function checks the validity of the components that are present in the security descriptor. /// It does not verify whether certain components are present nor does it verify the contents of the individual ACE or ACL. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-isvalidsecuritydescriptor BOOL // IsValidSecurityDescriptor( PSECURITY_DESCRIPTOR pSecurityDescriptor ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "24a98229-11e4-45ef-988b-c2cf831275e7")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool IsValidSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor); /// /// The MakeAbsoluteSD function creates a security descriptor in absolute format by using a security descriptor in /// self-relative format as a template. /// /// /// A pointer to a SECURITY_DESCRIPTOR structure in self-relative format. The function creates an absolute-format version of this /// security descriptor without modifying the original security descriptor. /// /// /// A pointer to a buffer that the function fills with the main body of an absolute-format security descriptor. This information is /// formatted as a SECURITY_DESCRIPTOR structure. /// /// /// A pointer to a variable that specifies the size of the buffer pointed to by the pAbsoluteSD parameter. If the buffer is not large /// enough for the security descriptor, the function fails and sets this variable to the minimum required size. /// /// /// A pointer to a buffer the function fills with the discretionary access control list (DACL) of the absolute-format security /// descriptor. The main body of the absolute-format security descriptor references this pointer. /// /// /// A pointer to a variable that specifies the size of the buffer pointed to by the pDacl parameter. If the buffer is not large /// enough for the access control list (ACL), the function fails and sets this variable to the minimum required size. /// /// /// A pointer to a buffer the function fills with the system access control list (SACL) of the absolute-format security descriptor. /// The main body of the absolute-format security descriptor references this pointer. /// /// /// A pointer to a variable that specifies the size of the buffer pointed to by the pSacl parameter. If the buffer is not large /// enough for the ACL, the function fails and sets this variable to the minimum required size. /// /// /// A pointer to a buffer the function fills with the security identifier (SID) of the owner of the absolute-format security /// descriptor. The main body of the absolute-format security descriptor references this pointer. /// /// /// A pointer to a variable that specifies the size of the buffer pointed to by the pOwner parameter. If the buffer is not large /// enough for the SID, the function fails and sets this variable to the minimum required size. /// /// /// A pointer to a buffer the function fills with the SID of the absolute-format security descriptor's primary group. The main body /// of the absolute-format security descriptor references this pointer. /// /// /// A pointer to a variable that specifies the size of the buffer pointed to by the pPrimaryGroup parameter. If the buffer is not /// large enough for the SID, the function fails and sets this variable to the minimum required size. /// /// /// If the function succeeds, the function returns nonzero. /// /// If the function fails, it returns zero. To get extended error information, call GetLastError. Possible return codes include, but /// are not limited to, the following. /// /// /// /// Return code/value /// Description /// /// /// ERROR_INSUFFICIENT_BUFFER 0x7A /// One or more of the buffers is too small. /// /// /// /// /// /// A security descriptor in absolute format contains pointers to the information it contains, rather than the information itself. A /// security descriptor in self-relative format contains the information in a contiguous block of memory. In a self-relative security /// descriptor, a SECURITY_DESCRIPTOR structure always starts the information, but the security descriptor's other components can /// follow the structure in any order. Instead of using memory addresses, the components of the self-relative security descriptor are /// identified by offsets from the beginning of the security descriptor. This format is useful when a security descriptor must be /// stored on a floppy disk or transmitted by means of a communications protocol. /// /// /// A server that copies secured objects to various media can use the MakeAbsoluteSD function to create an absolute security /// descriptor from a self-relative security descriptor and the MakeSelfRelativeSD function to create a self-relative security /// descriptor from an absolute security descriptor. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-makeabsolutesd BOOL MakeAbsoluteSD( // PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor, LPDWORD // lpdwAbsoluteSecurityDescriptorSize, PACL pDacl, LPDWORD lpdwDaclSize, PACL pSacl, LPDWORD lpdwSaclSize, PSID pOwner, LPDWORD // lpdwOwnerSize, PSID pPrimaryGroup, LPDWORD lpdwPrimaryGroupSize ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "47c75071-f10d-43cf-a841-2dd49fc39afa")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool MakeAbsoluteSD([In] PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, [In, Out] SafePSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor, ref uint lpdwAbsoluteSecurityDescriptorSize, SafePACL pDacl, ref uint lpdwDaclSize, SafePACL pSacl, ref uint lpdwSaclSize, SafePSID pOwner, ref uint lpdwOwnerSize, SafePSID pPrimaryGroup, ref uint lpdwPrimaryGroupSize); /// /// The MakeSelfRelativeSD function creates a security descriptor in self-relative format by using a security descriptor in /// absolute format as a template. /// /// /// A pointer to a SECURITY_DESCRIPTOR structure in absolute format. The function creates a version of this security descriptor in /// self-relative format without modifying the original. /// /// /// A pointer to a buffer the function fills with a security descriptor in self-relative format. /// /// /// A pointer to a variable specifying the size of the buffer pointed to by the pSelfRelativeSD parameter. If the buffer is not large /// enough for the security descriptor, the function fails and sets this variable to the minimum required size. /// /// /// If the function succeeds, the return value is nonzero. /// /// If the function fails, the return value is zero. To get extended error information, call GetLastError. Possible return codes /// include, but are not limited to, the following. /// /// /// /// Return code/value /// Description /// /// /// ERROR_INSUFFICIENT_BUFFER 0x7A /// One or more of the buffers is too small. /// /// /// /// /// /// A security descriptor in absolute format contains pointers to the information it contains, rather than containing the information /// itself. A security descriptor in self-relative format contains the information in a contiguous block of memory. In a /// self-relative security descriptor, a SECURITY_DESCRIPTOR structure always starts the information, but the security descriptor's /// other components can follow the structure in any order. Instead of using memory addresses, the components of the security /// descriptor are identified by offsets from the beginning of the security descriptor. This format is useful when a security /// descriptor must be stored on a floppy disk or transmitted by means of a communications protocol. /// /// /// A server that copies secured objects to various media can use the MakeSelfRelativeSD function to create a self-relative /// security descriptor from an absolute security descriptor and the MakeAbsoluteSD function to create an absolute security /// descriptor from a self-relative security descriptor. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-makeselfrelativesd BOOL // MakeSelfRelativeSD( PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor, PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, // LPDWORD lpdwBufferLength ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "497c7e2f-75b7-41b9-9693-37e041b7af58")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool MakeSelfRelativeSD(PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor, SafePSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, ref uint lpdwBufferLength); /// /// The MapGenericMask function maps the generic access rights in an access mask to specific and standard access rights. The function /// applies a mapping supplied in a structure. /// /// A pointer to an access mask. /// /// A pointer to a structure specifying a mapping of generic access types to specific and standard /// access types. /// [DllImport(Lib.AdvApi32, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "aa379266")] public static extern void MapGenericMask(ref ACCESS_MASK AccessMask, in GENERIC_MAPPING GenericMapping); /// /// The PrivilegeCheck function determines whether a specified set of privileges are enabled in an access token. The PrivilegeCheck /// function is typically called by a server application to check the privileges of a client's access token. /// /// /// A handle to an access token representing a client process. This handle must have been obtained by opening the token of a thread /// impersonating the client. The token must be open for TOKEN_QUERY access. /// /// /// A pointer to a PRIVILEGE_SET structure. The Privilege member of this structure is an array of LUID_AND_ATTRIBUTES structures. /// Before calling PrivilegeCheck, use the Privilege array to indicate the set of privileges to check. Set the Control member to /// PRIVILEGE_SET_ALL_NECESSARY if all of the privileges must be enabled; or set it to zero if it is sufficient that any one of the /// privileges be enabled. /// /// When PrivilegeCheck returns, the Attributes member of each LUID_AND_ATTRIBUTES structure is set to SE_PRIVILEGE_USED_FOR_ACCESS /// if the corresponding privilege is enabled. /// /// /// /// A pointer to a value the function sets to indicate whether any or all of the specified privileges are enabled in the access /// token. If the Control member of the PRIVILEGE_SET structure specifies PRIVILEGE_SET_ALL_NECESSARY, this value is TRUE only if all /// the privileges are enabled; otherwise, this value is TRUE if any of the privileges are enabled. /// /// /// If the function succeeds, the function returns nonzero. If the function fails, it returns zero. To get extended error /// information, call GetLastError. /// [PInvokeData("securitybaseapi.h", MSDNShortId = "aa379304")] [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool PrivilegeCheck(HTOKEN ClientToken, [In, Out, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PRIVILEGE_SET.Marshaler))] PRIVILEGE_SET RequiredPrivileges, [MarshalAs(UnmanagedType.Bool)] out bool pfResult); /// /// The QuerySecurityAccessMask function creates an access mask that represents the access permissions necessary to query the /// specified object security information. /// /// A SECURITY_INFORMATION structure that specifies the security information to be queried. /// A pointer to the access mask that this function creates. // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-querysecurityaccessmask void // QuerySecurityAccessMask( SECURITY_INFORMATION SecurityInformation, LPDWORD DesiredAccess ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "70379640-28b7-4503-9ba8-789786078d4a")] public static extern void QuerySecurityAccessMask(SECURITY_INFORMATION SecurityInformation, out ACCESS_MASK DesiredAccess); /// The RevertToSelf function terminates the impersonation of a client application. /// /// If the function succeeds, the function returns nonzero. If the function fails, it returns zero. To get extended error /// information, call GetLastError. /// [DllImport(Lib.AdvApi32, ExactSpelling = true, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] [PInvokeData("securitybaseapi.h", MSDNShortId = "aa379317")] public static extern bool RevertToSelf(); /// The SetAclInformation function sets information about an access control list (ACL). /// A pointer to an ACL. The function sets information in this ACL. /// /// A pointer to a buffer that contains the information to be set. This must be a pointer to an ACL_REVISION_INFORMATION structure. /// /// The size, in bytes, of the buffer pointed to by the pAclInfo parameter. /// /// An ACL_INFORMATION_CLASS enumerated type that gives the class of information requested. /// /// Currently, this parameter can be AclRevisionInformation. This means that the buffer pointed to by the pAclInformation /// parameter contains an ACL_REVISION_INFORMATION structure. /// /// /// /// If the function succeeds, the function returns nonzero. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-setaclinformation BOOL SetAclInformation( // PACL pAcl, LPVOID pAclInformation, DWORD nAclInformationLength, ACL_INFORMATION_CLASS dwAclInformationClass ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "bb4dd7f9-2f15-4a27-89c9-1675f4fb8d92")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetAclInformation(PACL pAcl, in ACL_REVISION_INFORMATION pAclInformation, uint nAclInformationLength = 4, ACL_INFORMATION_CLASS dwAclInformationClass = ACL_INFORMATION_CLASS.AclRevisionInformation); /// The SetAclInformation function sets information about an access control list (ACL). /// A pointer to an ACL. The function sets information in this ACL. /// /// A pointer to a buffer that contains the information to be set. This must be a pointer to an ACL_REVISION_INFORMATION structure. /// /// The size, in bytes, of the buffer pointed to by the pAclInfo parameter. /// /// An ACL_INFORMATION_CLASS enumerated type that gives the class of information requested. /// /// Currently, this parameter can be AclRevisionInformation. This means that the buffer pointed to by the pAclInformation /// parameter contains an ACL_REVISION_INFORMATION structure. /// /// /// /// If the function succeeds, the function returns nonzero. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-setaclinformation BOOL SetAclInformation( // PACL pAcl, LPVOID pAclInformation, DWORD nAclInformationLength, ACL_INFORMATION_CLASS dwAclInformationClass ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "bb4dd7f9-2f15-4a27-89c9-1675f4fb8d92")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetAclInformation(PACL pAcl, IntPtr pAclInformation, uint nAclInformationLength, ACL_INFORMATION_CLASS dwAclInformationClass); /// /// The SetKernelObjectSecurity function sets the security of a kernel object. For example, this can be a process, thread, or event. /// /// A handle to a kernel object for which security information is set. /// /// A set of bit flags that indicate the type of security information to set. This parameter can be a combination of the /// SECURITY_INFORMATION bit flags. /// /// A pointer to a SECURITY_DESCRIPTOR structure that contains the new security information. /// /// If the function succeeds, the function returns nonzero. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-setkernelobjectsecurity BOOL // SetKernelObjectSecurity( HANDLE Handle, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "2a70483e-245d-4bc7-b90a-58d143364ce1")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetKernelObjectSecurity(HANDLE Handle, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor); /// /// The SetPrivateObjectSecurity function modifies a private object's security descriptor. /// /// To specify whether the protected server supports automatic inheritance of access control entries (ACEs), use the /// SetPrivateObjectSecurityEx function. /// /// /// /// Indicates the parts of the security descriptor to set. This value can be a combination of the SECURITY_INFORMATION bit flags. /// /// /// A pointer to a SECURITY_DESCRIPTOR structure. The parts of this security descriptor indicated by the SecurityInformation /// parameter are applied to the ObjectsSecurityDescriptor security descriptor. /// /// /// /// A pointer to a pointer to a SECURITY_DESCRIPTOR structure. This security descriptor must be in self-relative form. The memory /// for the security descriptor must be allocated from the process heap (GetProcessHeap) with the HeapAlloc function. /// /// /// On input, this is the current security descriptor of the private object. The function modifies it to produce the new security /// descriptor. If necessary, the SetPrivateObjectSecurity function allocates additional memory to produce a larger security descriptor. /// /// /// /// A pointer to a GENERIC_MAPPING structure that specifies the specific and standard access rights that correspond to each of the /// generic access rights. /// /// /// A handle to the access token for the client on whose behalf the private object's security is being modified. This parameter is /// required to ensure that the client has provided a legitimate value for a new owner security identifier (SID). The token must be /// open for TOKEN_QUERY access. /// /// /// If the function succeeds, the function returns nonzero. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// /// /// /// This function is intended for use by resource managers only. To implement the standard access control semantics for updating /// security descriptors, a resource manager should verify that the following conditions are met before calling SetPrivateObjectSecurity: /// /// /// /// If the object's owner is being set, the calling process must have either WRITE_OWNER permission or be the object's owner. /// /// /// /// If the object's discretionary access control list (DACL) is being set, the calling process must have either WRITE_DAC permission /// or be the object's owner. /// /// /// /// /// If the object's system access control list (SACL) is being set, the SE_SECURITY_NAME privilege must be enabled for the calling process. /// /// /// /// /// If the preceding conditions are not met, a call to this function does not fail; however, standard access policy is not enforced. /// /// /// The process calling this function should not be impersonating a client because clients do not typically have appropriate /// privileges required for underlying token operations. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-setprivateobjectsecurity BOOL // SetPrivateObjectSecurity( SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor, // PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, PGENERIC_MAPPING GenericMapping, HANDLE Token ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "726994c8-7813-4f1a-b7d7-a25e79202c33")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetPrivateObjectSecurity(SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor, ref PSECURITY_DESCRIPTOR ObjectsSecurityDescriptor, in GENERIC_MAPPING GenericMapping, HTOKEN Token); /// /// The SetPrivateObjectSecurity function modifies a private object's security descriptor. /// /// To specify whether the protected server supports automatic inheritance of access control entries (ACEs), use the /// SetPrivateObjectSecurityEx function. /// /// /// /// Indicates the parts of the security descriptor to set. This value can be a combination of the SECURITY_INFORMATION bit flags. /// /// /// A pointer to a SECURITY_DESCRIPTOR structure. The parts of this security descriptor indicated by the SecurityInformation /// parameter are applied to the ObjectsSecurityDescriptor security descriptor. /// /// /// /// A pointer to a pointer to a SECURITY_DESCRIPTOR structure. This security descriptor must be in self-relative form. The memory /// for the security descriptor must be allocated from the process heap (GetProcessHeap) with the HeapAlloc function. /// /// /// On input, this is the current security descriptor of the private object. The function modifies it to produce the new security /// descriptor. If necessary, the SetPrivateObjectSecurity function allocates additional memory to produce a larger security descriptor. /// /// /// /// A pointer to a GENERIC_MAPPING structure that specifies the specific and standard access rights that correspond to each of the /// generic access rights. /// /// /// A handle to the access token for the client on whose behalf the private object's security is being modified. This parameter is /// required to ensure that the client has provided a legitimate value for a new owner security identifier (SID). The token must be /// open for TOKEN_QUERY access. /// /// /// If the function succeeds, the function returns nonzero. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// /// /// /// This function is intended for use by resource managers only. To implement the standard access control semantics for updating /// security descriptors, a resource manager should verify that the following conditions are met before calling SetPrivateObjectSecurity: /// /// /// /// If the object's owner is being set, the calling process must have either WRITE_OWNER permission or be the object's owner. /// /// /// /// If the object's discretionary access control list (DACL) is being set, the calling process must have either WRITE_DAC permission /// or be the object's owner. /// /// /// /// /// If the object's system access control list (SACL) is being set, the SE_SECURITY_NAME privilege must be enabled for the calling process. /// /// /// /// /// If the preceding conditions are not met, a call to this function does not fail; however, standard access policy is not enforced. /// /// /// The process calling this function should not be impersonating a client because clients do not typically have appropriate /// privileges required for underlying token operations. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-setprivateobjectsecurity BOOL // SetPrivateObjectSecurity( SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor, // PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, PGENERIC_MAPPING GenericMapping, HANDLE Token ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "726994c8-7813-4f1a-b7d7-a25e79202c33")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetPrivateObjectSecurity(SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor, ref IntPtr ObjectsSecurityDescriptor, in GENERIC_MAPPING GenericMapping, HTOKEN Token); /// /// The SetPrivateObjectSecurityEx function modifies the security descriptor of a private object maintained by the resource /// manager calling this function. The SetPrivateObjectSecurityEx function has a flags parameter that specifies whether the /// resource manager supports automatic inheritance of access control entries (ACEs). /// /// /// The parts of the security descriptor to set. This value can be a combination of the SECURITY_INFORMATION bit flags. /// /// /// A pointer to a SECURITY_DESCRIPTOR structure. The parts of this security descriptor indicated by the SecurityInformation /// parameter are applied to the ObjectsSecurityDescriptor security descriptor. /// /// /// /// A pointer to a pointer to a SECURITY_DESCRIPTOR structure. This security descriptor must be in self-relative form. The memory /// for the security descriptor must be allocated from the process heap (GetProcessHeap) with the HeapAlloc function. /// /// /// On input, this is the current security descriptor of the private object. The function modifies it to produce the new security /// descriptor. If necessary, the SetPrivateObjectSecurityEx function allocates additional memory to produce a larger security descriptor. /// /// /// /// /// Specifies automatic inheritance of ACEs. If the protected server does not implement automatic inheritance, it should specify /// zero; otherwise, it can specify a combination of the following values, defined in Winnt.h. /// /// /// /// Value /// Meaning /// /// /// SEF_DACL_AUTO_INHERIT 0x01 /// /// The new discretionary access control list (DACL) contains ACEs inherited from the DACL of the object's parent, as well as any /// explicit ACEs specified in the DACL of ModificationDescriptor. If this flag is not set, the new DACL does not inherit ACEs. /// /// /// /// SEF_SACL_AUTO_INHERIT 0x02 /// /// The new system access control list (SACL) contains ACEs inherited from the SACL of the security descriptor associated with the /// object's parent, as well as any explicit ACEs specified in the SACL of ModificationDescriptor. If this flag is not set, the new /// SACL does not inherit ACEs. /// /// /// /// SEF_AVOID_PRIVILEGE_CHECK 0x08 /// /// The function does not perform privilege checking. If the SEF_AVOID_OWNER_CHECK flag is also set, the Token parameter can be NULL. /// Use this flag when implementing automatic inheritance to avoid checking privileges on each child updated. /// /// /// /// SEF_AVOID_OWNER_CHECK 0x10 /// /// The function does not check the validity of the owner in the resultant ObjectsSecurityDescriptor as described in Remarks. If the /// SEF_AVOID_PRIVILEGE_CHECK flag is also set, the Token parameter can be NULL. /// /// /// /// SEF_DEFAULT_OWNER_FROM_PARENT 0x20 /// /// The owner of ObjectsSecurityDescriptor defaults to the owner of the object's parent. If this flag is not set, the owner of /// ObjectsSecurityDescriptor defaults to the owner of the token specified by the Token parameter. The owner of the token is /// specified in the token itself. In either case, if the ModificationDescriptor parameter is not NULL, the ObjectsSecurityDescriptor /// owner is set to the owner from ModificationDescriptor. /// /// /// /// SEF_DEFAULT_GROUP_FROM_PARENT 0x40 /// /// The group of ObjectsSecurityDescriptor defaults to the group from the owner of the object's parent. If this flag is not set, the /// group of ObjectsSecurityDescriptor defaults to the group of the token specified by the Token parameter. The group of the token is /// specified in the token itself. In either case, if the ModificationDescriptor parameter is not NULL, the ObjectsSecurityDescriptor /// group is set to the group from ModificationDescriptor. /// /// /// /// SEF_MACL_NO_WRITE_UP 0x100 /// A principal with a mandatory level lower than that of the object cannot write to the object. /// /// /// SEF_MACL_NO_READ_UP 0x200 /// A principal with a mandatory level lower than that of the object cannot read the object. /// /// /// SEF_MACL_NO_EXECUTE_UP 0x400 /// A principal with a mandatory level lower than that of the object cannot execute the object. /// /// /// SEF_AVOID_OWNER_RESTRICTION 0x1000 /// /// Any restrictions specified by the owner of the object's parent that would limit the caller's ability to specify a DACL in the /// ObjectsSecurityDescriptor are ignored. /// /// /// /// /// /// A pointer to a GENERIC_MAPPING structure that specifies the specific and standard access rights that correspond to each of the /// generic access rights. /// /// /// Identifies the access token for the client on whose behalf the private object's security is being modified. This parameter is /// required to ensure that the client has provided a legitimate value for a new owner security identifier (SID). The token must be /// open for TOKEN_QUERY access. /// /// /// If the function succeeds, the function returns nonzero. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// /// /// /// If the AutoInheritFlags parameter is zero, SetPrivateObjectSecurityEx is identical to the SetPrivateObjectSecurity function. /// /// /// This function is intended for use by resource managers only. To implement the standard Windows access control semantics for /// updating security descriptors, a resource manager should verify that the following conditions are met before calling SetPrivateObjectSecurityEx: /// /// /// /// If the object's owner is being set, the calling process must have either WRITE_OWNER permission or be the object's owner. /// /// /// If the object's DACL is being set, the calling process must have either WRITE_DAC permission or be the object's owner. /// /// /// If the object's SACL is being set, the SE_SECURITY_NAME privilege must be enabled for the calling process. /// /// /// /// If the preceding conditions are not met, a call to this function does not fail, however, standard Windows access policy is not enforced. /// /// /// The process calling this function should not be impersonating a client because clients do not typically have appropriate /// privileges required for underlying token operations. /// /// /// If AutoInheritFlags specifies the SEF_DACL_AUTO_INHERIT bit, the function applies the following rules to the DACL to create the /// new security descriptor from the current descriptor: /// /// /// /// /// If the SE_DACL_PROTECTED flag is not set in the control bits of either the current security descriptor or the /// ModificationDescriptor, the function constructs the output security descriptor from the inherited ACEs of the current security /// descriptor and noninherited ACEs of ModificationDescriptor. That is, it is impossible to change an inherited ACE by changing the /// access control list (ACL) on an object. This behavior preserves the inherited ACEs as they were inherited from the parent container. /// /// /// /// /// If SE_DACL_PROTECTED is set in ModificationDescriptor, the current security descriptor is ignored. The output security descriptor /// is built as a copy of ModificationDescriptor with any INHERITED_ACE bits turned off. /// /// /// /// /// If SE_DACL_PROTECTED is set in the current security descriptor and not in ModificationDescriptor, the current security descriptor /// is ignored. The output security descriptor is built as a copy of ModificationDescriptor. It is the caller's responsibility to /// ensure that the correct ACEs have the INHERITED_ACE bit turned on. /// /// /// /// If AutoInheritFlags specifies the SEF_SACL_AUTO_INHERIT bit, the function applies similar rules to the new SACL. /// /// For both DACLs and SACLs, certain types of ACEs in the input ObjectsSecurityDescriptor and in ModificationDescriptor will be /// replaced by two ACEs in the output ObjectsSecurityDescriptor. Specifically, an inheritable ACE that contains at least one of the /// following mappable elements will result in two ACEs in the output ObjectsSecurityDescriptor. Mappable elements include: /// /// /// /// Generic access rights in the ACCESS_MASK structure /// /// /// Creator Owner SID or Creator Group SID as the ACE subject identifier /// /// /// ACEs with any of these mappable elements will result in the following two ACEs in the output ObjectsSecurityDescriptor: /// /// /// An ACE that is a copy of the original, but with the INHERIT_ONLY flag set /// /// /// An ACE in which the INHERITED_ACE bit is turned on and the generic elements are mapped to specific elements: /// /// /// /// If AutoInheritFlags does not specify the SEF_AVOID_PRIVILEGE_CHECK bit, owner validity checking is performed according to the /// following rules. The Owner in ModificationDescriptor: /// /// /// /// Must be a legally formed SID /// /// /// Must match the TokenUser in Token /// /// /// Or /// /// /// Must match a group in the TokenGroups in Token where the attributes on the group: /// /// /// /// A resource manager that is setting the Owner on a subtree of objects can avoid the overhead of redundant owner validity checking. /// If the Owner in ModificationDescriptor and Token remain the same for iterative calls to this function, the /// SEF_AVOID_PRIVILEGE_CHECK bit may be set in AutoInheritFlags for calls subsequent to an initial call in which owner validity /// checking is performed. Callers that do not have access to the token of the client that will ultimately be setting the owner /// should also choose to skip owner validation checking. /// /// /// Note The SEF_AVOID_PRIVILEGE_CHECK bit as used in the SetPrivateObjectSecurityEx function is equivalent to the /// SEF_AVOID_OWNER_CHECK bit used in the CreatePrivateObjectSecurityEx function. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-setprivateobjectsecurityex BOOL // SetPrivateObjectSecurityEx( SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor, // PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, ULONG AutoInheritFlags, PGENERIC_MAPPING GenericMapping, HANDLE Token ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "eb3a751f-741e-448f-b812-5f16a4040b5e")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetPrivateObjectSecurityEx(SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor, ref PSECURITY_DESCRIPTOR ObjectsSecurityDescriptor, SEF AutoInheritFlags, in GENERIC_MAPPING GenericMapping, HTOKEN Token); /// /// The SetSecurityAccessMask function creates an access mask that represents the access permissions necessary to set the /// specified object security information. /// /// A SECURITY_INFORMATION structure that specifies the security information to be set. /// A pointer to the access mask that this function creates. // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-setsecurityaccessmask void // SetSecurityAccessMask( SECURITY_INFORMATION SecurityInformation, LPDWORD DesiredAccess ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "764a4e93-0865-49f8-9b3a-1a178073454d")] public static extern void SetSecurityAccessMask(SECURITY_INFORMATION SecurityInformation, out ACCESS_MASK DesiredAccess); /// /// The SetSecurityDescriptorControl function sets the control bits of a security descriptor. The function can set only the /// control bits that relate to automatic inheritance of ACEs. To set the other control bits of a security descriptor, use the /// functions, such as SetSecurityDescriptorDacl, for modifying the components of a security descriptor. /// /// A pointer to a SECURITY_DESCRIPTOR structure whose control and revision information are set. /// A SECURITY_DESCRIPTOR_CONTROL mask that indicates the control bits to set. /// /// A SECURITY_DESCRIPTOR_CONTROL mask that indicates the new values for the control bits specified by the ControlBitsOfInterest mask. /// /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// /// /// /// The SetSecurityDescriptorControl function specifies the control bit or bits to modify, and whether the bits are on or off. /// /// Examples /// The following example marks the DACL on the security descriptor as protected. /// The following example marks the DACL as not protected. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-setsecuritydescriptorcontrol BOOL // SetSecurityDescriptorControl( PSECURITY_DESCRIPTOR pSecurityDescriptor, SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, // SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "672406af-ae04-4939-82a4-069a91e61b3f")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetSecurityDescriptorControl(PSECURITY_DESCRIPTOR pSecurityDescriptor, SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet); /// /// The SetSecurityDescriptorDacl function sets information in a discretionary access control list (DACL). If a DACL is /// already present in the security descriptor, the DACL is replaced. /// /// /// A pointer to the SECURITY_DESCRIPTOR structure to which the function adds the DACL. This security descriptor must be in absolute /// format, meaning that its members must be pointers to other structures, rather than offsets to contiguous data. /// /// /// A flag that indicates the presence of a DACL in the security descriptor. If this parameter is TRUE, the function sets the /// SE_DACL_PRESENT flag in the SECURITY_DESCRIPTOR_CONTROL structure and uses the values in the pDacl and bDaclDefaulted parameters. /// If this parameter is FALSE, the function clears the SE_DACL_PRESENT flag, and pDacl and bDaclDefaulted are ignored. /// /// /// A pointer to an ACL structure that specifies the DACL for the security descriptor. If this parameter is NULL, a /// NULL DACL is assigned to the security descriptor, which allows all access to the object. The DACL is referenced by, not /// copied into, the security descriptor. /// /// /// A flag that indicates the source of the DACL. If this flag is TRUE, the DACL has been retrieved by some default mechanism. /// If FALSE, the DACL has been explicitly specified by a user. The function stores this value in the SE_DACL_DEFAULTED flag /// of the SECURITY_DESCRIPTOR_CONTROL structure. If this parameter is not specified, the SE_DACL_DEFAULTED flag is cleared. /// /// /// If the function succeeds, the function returns nonzero. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// /// /// /// There is an important difference between an empty and a nonexistent DACL. When a DACL is empty, it contains no access control /// entries (ACEs); therefore, no access rights are explicitly granted. As a result, access to the object is implicitly denied. /// /// /// When an object has no DACL (when the pDacl parameter is NULL), no protection is assigned to the object, and all access /// requests are granted. To help maintain security, restrict access by using a DACL. /// /// There are three possible outcomes in different configurations of the bDaclPresent flag and the pDacl parameter: /// /// /// /// When the pDacl parameter points to a DACL and the bDaclPresent flag is TRUE, a DACL is specified and it must contain /// access-allowed ACEs to allow access to the object. /// /// /// /// /// When the pDacl parameter does not point to a DACL and the bDaclPresent flag is TRUE, a NULL DACL is specified. All /// access is allowed. You should not use a NULL DACL with an object because any user can change the DACL and owner of the /// security descriptor. This will interfere with use of the object. /// /// /// /// /// When the pDacl parameter does not point to a DACL and the bDaclPresent flag is FALSE, a DACL can be provided for the /// object through an inheritance or default mechanism. /// /// /// /// Examples /// For an example that uses this function, see Creating a Security Descriptor for a New Object. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-setsecuritydescriptordacl BOOL // SetSecurityDescriptorDacl( PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl, BOOL bDaclDefaulted ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "a873b803-391e-47e1-af7e-6dad7195968c")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetSecurityDescriptorDacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, [MarshalAs(UnmanagedType.Bool)] bool bDaclPresent, PACL pDacl, [MarshalAs(UnmanagedType.Bool)] bool bDaclDefaulted); /// /// The SetSecurityDescriptorGroup function sets the primary group information of an absolute-format security descriptor, /// replacing any primary group information already present in the security descriptor. /// /// /// A pointer to the SECURITY_DESCRIPTOR structure whose primary group is set by this function. The function replaces any existing /// primary group with the new primary group. /// /// /// A pointer to a SID structure for the security descriptor's new primary group. The SID structure is referenced by, not /// copied into, the security descriptor. If this parameter is NULL, the function clears the security descriptor's primary /// group information. This marks the security descriptor as having no primary group. /// /// /// Indicates whether the primary group information was derived from a default mechanism. If this value is TRUE, it is default /// information, and the function stores this value as the SE_GROUP_DEFAULTED flag in the SECURITY_DESCRIPTOR_CONTROL structure. If /// this parameter is zero, the SE_GROUP_DEFAULTED flag is cleared. /// /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-setsecuritydescriptorgroup BOOL // SetSecurityDescriptorGroup( PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID pGroup, BOOL bGroupDefaulted ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "060c375c-a313-4fa2-8d85-cee9369c26a8")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetSecurityDescriptorGroup(PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID pGroup, [MarshalAs(UnmanagedType.Bool)] bool bGroupDefaulted); /// /// The SetSecurityDescriptorOwner function sets the owner information of an absolute-format security descriptor. It replaces /// any owner information already present in the security descriptor. /// /// /// A pointer to the SECURITY_DESCRIPTOR structure whose owner is set by this function. The function replaces any existing owner with /// the new owner. /// /// /// A pointer to a SID structure for the security descriptor's new primary owner. The SID structure is referenced by, not /// copied into, the security descriptor. If this parameter is NULL, the function clears the security descriptor's owner /// information. This marks the security descriptor as having no owner. /// /// /// Indicates whether the owner information is derived from a default mechanism. If this value is TRUE, it is default /// information. The function stores this value as the SE_OWNER_DEFAULTED flag in the SECURITY_DESCRIPTOR_CONTROL structure. If this /// parameter is zero, the SE_OWNER_DEFAULTED flag is cleared. /// /// /// If the function succeeds, the return value is nonzero. /// If the function fails, the return value is zero. To get extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-setsecuritydescriptorowner BOOL // SetSecurityDescriptorOwner( PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID pOwner, BOOL bOwnerDefaulted ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "cb3ba617-322a-4b8c-a9d5-32910315fb56")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetSecurityDescriptorOwner(PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID pOwner, [MarshalAs(UnmanagedType.Bool)] bool bOwnerDefaulted); /// /// The SetSecurityDescriptorRMControl function sets the resource manager control bits in the SECURITY_DESCRIPTOR structure. /// /// A pointer to a SECURITY_DESCRIPTOR structure that contains the resource manager control bits. /// /// A pointer to the bitfield value that the resource manager control bits in the SECURITY_DESCRIPTOR structure will be set to. If /// the value of this parameter is NULL, the resource manager control bits will be cleared. /// /// The return value is ERROR_SUCCESS. /// /// The resource manager control bits are eight bits in the Sbz1 member of the SECURITY_INFORMATION structure that contains /// information specific to the resource manager accessing the structure. These bits should be accessed only through the /// GetSecurityDescriptorRMControl and SetSecurityDescriptorRMControl functions. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-setsecuritydescriptorrmcontrol DWORD // SetSecurityDescriptorRMControl( PSECURITY_DESCRIPTOR SecurityDescriptor, PUCHAR RMControl ); [DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "fe9c736b-e047-4aa3-a3de-d5f2f2cdab4f")] public static extern uint SetSecurityDescriptorRMControl(PSECURITY_DESCRIPTOR SecurityDescriptor, in byte RMControl); /// /// The SetSecurityDescriptorSacl function sets information in a system access control list (SACL). If there is already a SACL /// present in the security descriptor, it is replaced. /// /// /// A pointer to the SECURITY_DESCRIPTOR structure to which the function adds the SACL. This security descriptor must be in absolute /// format, meaning that its members must be pointers to other structures, rather than offsets to contiguous data. /// /// /// Indicates the presence of a SACL in the security descriptor. If this parameter is TRUE, the function sets the /// SE_SACL_PRESENT flag in the SECURITY_DESCRIPTOR_CONTROL structure and uses the values in the pSacl and bSaclDefaulted parameters. /// If it is FALSE, the function does not set the SE_SACL_PRESENT flag, and pSacl and bSaclDefaulted are ignored. /// /// /// A pointer to an ACL structure that specifies the SACL for the security descriptor. If this parameter is NULL, a /// NULL SACL is assigned to the security descriptor. The SACL is referenced by, not copied into, the security descriptor. /// /// /// Indicates the source of the SACL. If this flag is TRUE, the SACL has been retrieved by some default mechanism. If it is /// FALSE, the SACL has been explicitly specified by a user. The function stores this value in the SE_SACL_DEFAULTED flag of /// the SECURITY_DESCRIPTOR_CONTROL structure. If this parameter is not specified, the SE_SACL_DEFAULTED flag is cleared. /// /// /// If the function succeeds, the function returns nonzero. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-setsecuritydescriptorsacl BOOL // SetSecurityDescriptorSacl( PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bSaclPresent, PACL pSacl, BOOL bSaclDefaulted ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "21615b63-0619-4c0c-a1b8-88ed09a1235c")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetSecurityDescriptorSacl(PSECURITY_DESCRIPTOR pSecurityDescriptor, [MarshalAs(UnmanagedType.Bool)] bool bSaclPresent, PACL pSacl, [MarshalAs(UnmanagedType.Bool)] bool bSaclDefaulted); /// /// The SetTokenInformation function sets various types of information for a specified access token. The information that this /// function sets replaces existing information. The calling process must have appropriate access rights to set the information. /// /// A handle to the access token for which information is to be set. /// /// A value from the TOKEN_INFORMATION_CLASS enumerated type that identifies the type of information the function sets. The valid /// values from TOKEN_INFORMATION_CLASS are described in the TokenInformation parameter. /// /// /// A pointer to a buffer that contains the information set in the access token. The structure of this buffer depends on the type of /// information specified by the TokenInformationClass parameter. /// /// Specifies the length, in bytes, of the buffer pointed to by TokenInformation. /// /// If the function succeeds, the function returns nonzero. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// /// /// /// To set privilege information, an application can call the AdjustTokenPrivileges function. To set a token's groups, an application /// can call the AdjustTokenGroups function. /// /// Token-type information can be set only when an access token is created. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-settokeninformation BOOL // SetTokenInformation( HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD // TokenInformationLength ); [DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)] [PInvokeData("securitybaseapi.h", MSDNShortId = "cdb8af74-540d-4059-ac64-6243f6aabaa6")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetTokenInformation(HTOKEN TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, IntPtr TokenInformation, uint TokenInformationLength); /// /// The SetTokenInformation function sets various types of information for a specified access token. The information that this /// function sets replaces existing information. The calling process must have appropriate access rights to set the information. /// /// A handle to the access token for which information is to be set. /// /// A value from the TOKEN_INFORMATION_CLASS enumerated type that identifies the type of information the function sets. The valid /// values from TOKEN_INFORMATION_CLASS are described in the TokenInformation parameter. /// /// /// A value that contains the information set in the access token. The structure of this buffer depends on the type of information /// specified by the TokenInformationClass parameter. /// /// /// If the function succeeds, the function returns nonzero. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// /// /// /// To set privilege information, an application can call the AdjustTokenPrivileges function. To set a token's groups, an application /// can call the AdjustTokenGroups function. /// /// Token-type information can be set only when an access token is created. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-settokeninformation BOOL // SetTokenInformation( HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD // TokenInformationLength ); [PInvokeData("securitybaseapi.h", MSDNShortId = "cdb8af74-540d-4059-ac64-6243f6aabaa6")] public static bool SetTokenInformation(HTOKEN TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, T TokenInformation) { if (!CorrespondingTypeAttribute.CanSet(TokenInformationClass, typeof(T))) throw new InvalidCastException(); using var mem = SafeHGlobalHandle.CreateFromStructure(TokenInformation); return SetTokenInformation(TokenHandle, TokenInformationClass, mem, mem.Size); } internal static int GetSize() where T : struct { if (!StructSizes.TryGetValue(typeof(T), out var sz)) StructSizes.Add(typeof(T), sz = Marshal.SizeOf(typeof(T))); return sz; } /// /// Provides a to a that releases a created HTOKEN instance at disposal using CloseHandle. /// /// public class SafeHTOKEN : SafeKernelHandle { /// /// Retrieves a pseudo-handle that you can use as a shorthand way to refer to the access token associated with a process. /// /// /// A pseudo-handle is a special constant that can function as the access token for the current process. The calling process can /// use a pseudo-handle to specify the access token for that process whenever a token handle is required. Child processes do not /// inherit pseudo-handles. /// Starting in Windows 8, this pseudo-handle has only TOKEN_QUERY and TOKEN_QUERY_SOURCE access rights. /// /// A process can create a standard handle that is valid in the context of other processes and can be inherited by other /// processes. To create this standard handle, call the DuplicateHandle function and specify the pseudo-handle as the source handle. /// /// /// You do not need to close the pseudo-handle when you no longer need it. If you call the CloseHandle function with a /// pseudo-handle, the function has no effect. If you call DuplicateHandle to duplicate the pseudo-handle, however, you must /// close the duplicate handle. /// /// public static readonly SafeHTOKEN CurrentProcessToken = new((IntPtr)4, false); /// /// Retrieves a pseudo-handle that you can use as a shorthand way to refer to the token that is currently in effect for the /// thread, which is the thread token if one exists and the process token otherwise. /// /// /// A pseudo-handle is a special constant that can function as the access token for the current thread. The calling thread can /// use a pseudo-handle to specify the access token for that thread whenever a token handle is required. Child threads do not /// inherit pseudo-handles. /// Starting in Windows 8, this pseudo-handle has only TOKEN_QUERY and TOKEN_QUERY_SOURCE access rights. /// /// A thread can create a standard handle that is valid in the context of other threads and can be inherited by other threads. To /// create this standard handle, call the DuplicateHandle function and specify the pseudo-handle as the source handle. /// /// /// You do not need to close the pseudo-handle when you no longer need it. If you call the CloseHandle function with a /// pseudo-handle, the function has no effect. If you call DuplicateHandle to duplicate the pseudo-handle, however, you must /// close the duplicate handle. /// /// public static readonly SafeHTOKEN CurrentThreadEffectiveToken = new((IntPtr)6, false); /// /// Retrieves a pseudo-handle that you can use as a shorthand way to refer to the impersonation token that was assigned to the /// current thread. /// /// /// A pseudo-handle is a special constant that can function as the impersonation token for the current thread. The calling thread /// can use a pseudo-handle to specify the impersonation token for that thread whenever a token handle is required. Child threads /// do not inherit pseudo-handles. /// Starting in Windows 8, this pseudo-handle has only TOKEN_QUERY and TOKEN_QUERY_SOURCE access rights. /// /// A thread can create a standard handle that is valid in the context of other threads and can be inherited by other threads. To /// create this standard handle, call the DuplicateHandle function and specify the pseudo-handle as the source handle. /// /// /// You do not need to close the pseudo-handle when you no longer need it. If you call the CloseHandle function with a /// pseudo-handle, the function has no effect. If you call DuplicateHandle to duplicate the pseudo-handle, however, you must /// close the duplicate handle. /// /// public static readonly SafeHTOKEN CurrentThreadToken = new((IntPtr)5, false); /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeHTOKEN(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } private SafeHTOKEN() : base() { } /// Gets a value indicating whether this token is elevated. /// true if this instance is elevated; otherwise, false. public bool IsElevated => GetInfo(TOKEN_INFORMATION_CLASS.TokenElevation).TokenIsElevated; /// Get the token handle instance from a process handle. /// The process handle. /// The desired access. TOKEN_DUPLICATE must usually be included. /// Resulting token handle. public static SafeHTOKEN FromProcess(HPROCESS hProcess, TokenAccess desiredAccess = TokenAccess.TOKEN_DUPLICATE) => !OpenProcessToken(hProcess, desiredAccess, out var val) ? throw new Win32Exception() : val; /// Get the token handle instance from a process instance. /// The process instance. If this value is , the current process will be used. /// The desired access. TOKEN_DUPLICATE must usually be included. /// Resulting token handle. public static SafeHTOKEN FromProcess(System.Diagnostics.Process process, TokenAccess desiredAccess = TokenAccess.TOKEN_DUPLICATE) => FromProcess((process ?? System.Diagnostics.Process.GetCurrentProcess()).Handle, desiredAccess); /// Get the token handle instance from a process handle. /// The thread handle. /// The desired access. TOKEN_DUPLICATE must usually be included. /// if set to true open as self. /// Resulting token handle. public static SafeHTOKEN FromThread(HTHREAD hThread, TokenAccess desiredAccess = TokenAccess.TOKEN_DUPLICATE, bool openAsSelf = true) { if (!OpenThreadToken(hThread, desiredAccess, openAsSelf, out var val)) { if (Marshal.GetLastWin32Error() == Win32Error.ERROR_NO_TOKEN) { using var pval = FromProcess(null); val = pval.DuplicateImpersonate(SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TokenAccess.TOKEN_IMPERSONATE | desiredAccess); if (!SetThreadToken(IntPtr.Zero, val)) Win32Error.ThrowLastError(); } else Win32Error.ThrowLastError(); } return val; } /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HTOKEN(SafeHTOKEN h) => h.handle; #if NETSTANDARD2_0 || NETCOREAPP2_0 || NETCOREAPP2_1 /// Conversion operator from SafeHTOKEN to SafeAccessTokenHandle. /// The handle. public static explicit operator Microsoft.Win32.SafeHandles.SafeAccessTokenHandle(SafeHTOKEN h) { var dup = h.DuplicatePrimary(); var ret = new Microsoft.Win32.SafeHandles.SafeAccessTokenHandle(dup.DangerousGetHandle()); dup.ReleaseHandle(); return ret; } #endif /// The Duplicate function creates a new access token that duplicates the current one. /// /// Specifies a SECURITY_IMPERSONATION_LEVEL enumerated type that supplies the impersonation level of the new token. /// /// A new token. public SafeHTOKEN Duplicate(SECURITY_IMPERSONATION_LEVEL level) { if (!DuplicateToken(this, level, out var dup)) Win32Error.ThrowLastError(); return dup; } /// /// The DuplicateImpersonate function creates a new impersonated access token that duplicates an existing token. /// /// /// Specifies a value from the SECURITY_IMPERSONATION_LEVEL enumeration that indicates the impersonation level of the new token. /// /// /// /// Specifies the requested access rights for the new token. The DuplicateTokenEx function compares the requested access /// rights with the existing token's discretionary access control list (DACL) to determine which rights are granted or denied. To /// request the same access rights as the existing token, specify zero. To request all access rights that are valid for the /// caller, specify MAXIMUM_ALLOWED. /// /// For a list of access rights for access tokens, see Access Rights for Access-Token Objects. /// /// /// /// A pointer to a SECURITY_ATTRIBUTES structure that specifies a security descriptor for the new token and determines /// whether child processes can inherit the token. If lpTokenAttributes is NULL, the token gets a default security /// descriptor and the handle cannot be inherited. If the security descriptor contains a system access control list (SACL), the /// token gets ACCESS_SYSTEM_SECURITY access right, even if it was not requested in dwDesiredAccess. /// /// /// To set the owner in the security descriptor for the new token, the caller's process token must have the /// SE_RESTORE_NAME privilege set. /// /// /// A pointer to a SafeHTOKEN variable that receives the new token. public SafeHTOKEN DuplicateImpersonate(SECURITY_IMPERSONATION_LEVEL impersonationLevel = SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TokenAccess desiredAccess = TokenAccess.TOKEN_QUERY | TokenAccess.TOKEN_DUPLICATE | TokenAccess.TOKEN_ASSIGN_PRIMARY | TokenAccess.TOKEN_ADJUST_DEFAULT | TokenAccess.TOKEN_ADJUST_SESSIONID | TokenAccess.TOKEN_IMPERSONATE, SECURITY_ATTRIBUTES tokenAttributes = null) { if (!DuplicateTokenEx(this, desiredAccess, tokenAttributes, impersonationLevel, TOKEN_TYPE.TokenImpersonation, out var dup)) Win32Error.ThrowLastError(); return dup; } /// The DuplicatePrimary function creates a new primary access token that duplicates an existing token. /// /// /// Specifies the requested access rights for the new token. The DuplicateTokenEx function compares the requested access /// rights with the existing token's discretionary access control list (DACL) to determine which rights are granted or denied. To /// request the same access rights as the existing token, specify zero. To request all access rights that are valid for the /// caller, specify MAXIMUM_ALLOWED. /// /// For a list of access rights for access tokens, see Access Rights for Access-Token Objects. /// /// /// Specifies a value from the SECURITY_IMPERSONATION_LEVEL enumeration that indicates the impersonation level of the new token. /// /// /// /// A pointer to a SECURITY_ATTRIBUTES structure that specifies a security descriptor for the new token and determines /// whether child processes can inherit the token. If lpTokenAttributes is NULL, the token gets a default security /// descriptor and the handle cannot be inherited. If the security descriptor contains a system access control list (SACL), the /// token gets ACCESS_SYSTEM_SECURITY access right, even if it was not requested in dwDesiredAccess. /// /// /// To set the owner in the security descriptor for the new token, the caller's process token must have the /// SE_RESTORE_NAME privilege set. /// /// /// A pointer to a SafeHTOKEN variable that receives the new token. public SafeHTOKEN DuplicatePrimary(TokenAccess desiredAccess = TokenAccess.TOKEN_ASSIGN_PRIMARY | TokenAccess.TOKEN_ALL_ACCESS, SECURITY_IMPERSONATION_LEVEL impersonationLevel = SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, SECURITY_ATTRIBUTES tokenAttributes = null) { if (!DuplicateTokenEx(this, desiredAccess, tokenAttributes, impersonationLevel, TOKEN_TYPE.TokenPrimary, out var dup)) Win32Error.ThrowLastError(); return dup; } /// /// Retrieves a specified type of information about an access token cast to supplied type. The calling /// process must have appropriate access rights to obtain the information. The caller is responsible for /// ensuring that the type requested by matches the type information requested by . /// /// /// Specifies a value from the TOKEN_INFORMATION_CLASS enumerated type to identify the type of information the function /// retrieves. Any callers who check the TokenIsAppContainer and have it return 0 should also verify that the caller token is not /// an identify level impersonation token. If the current token is not an application container but is an identity level token, /// you should return AccessDenied. /// public T GetInfo(TOKEN_INFORMATION_CLASS? tokenInfoClass = null) where T : struct => GetTokenInformation(this, tokenInfoClass); /// /// Retrieves a specified type of information about an access token. The calling process must have appropriate access rights to /// obtain the information. /// /// /// Specifies a value from the TOKEN_INFORMATION_CLASS enumerated type to identify the type of information the function /// retrieves. Any callers who check the TokenIsAppContainer and have it return 0 should also verify that the caller token is not /// an identify level impersonation token. If the current token is not an application container but is an identity level token, /// you should return AccessDenied. /// /// The block of memory containing the requested information. public SafeCoTaskMemHandle GetInfo(TOKEN_INFORMATION_CLASS tokenInfoClass) { // Get information size if (!GetTokenInformation(this, tokenInfoClass, SafeCoTaskMemHandle.Null, 0, out var cbSize)) { var e = Win32Error.GetLastError(); if (e.Failed && e != Win32Error.ERROR_INSUFFICIENT_BUFFER && e != Win32Error.ERROR_BAD_LENGTH) e.ThrowIfFailed(); } // Retrieve token information. var pType = new SafeCoTaskMemHandle(cbSize); if (!GetTokenInformation(this, tokenInfoClass, pType, cbSize, out _)) Win32Error.ThrowLastError(); return pType; } /// /// The SetInfo function sets various types of information for a specified access token. The information that this /// function sets replaces existing information. The calling process must have appropriate access rights to set the information. /// /// /// A value from the TOKEN_INFORMATION_CLASS enumerated type that identifies the type of information the function sets. The valid /// values from TOKEN_INFORMATION_CLASS are described in the TokenInformation parameter. /// /// /// A value that contains the information set in the access token. The structure of this buffer depends on the type of /// information specified by the TokenInformationClass parameter. /// /// /// If the function succeeds, the function returns nonzero. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// /// /// /// To set privilege information, an application can call the AdjustTokenPrivileges function. To set a token's groups, an /// application can call the AdjustTokenGroups function. /// /// Token-type information can be set only when an access token is created. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-settokeninformation BOOL // SetTokenInformation( HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD // TokenInformationLength ); public bool SetInfo(TOKEN_INFORMATION_CLASS TokenInformationClass, T TokenInformation) => SetTokenInformation(this, TokenInformationClass, TokenInformation); /// /// The SetInfo function sets various types of information for a specified access token. The information that this /// function sets replaces existing information. The calling process must have appropriate access rights to set the information. /// /// /// A value that contains the information set in the access token. The structure of this buffer depends on the type of /// information specified by the TokenInformationClass parameter. /// /// /// If the function succeeds, the function returns nonzero. /// If the function fails, it returns zero. To get extended error information, call GetLastError. /// /// /// /// To set privilege information, an application can call the AdjustTokenPrivileges function. To set a token's groups, an /// application can call the AdjustTokenGroups function. /// /// Token-type information can be set only when an access token is created. /// // https://docs.microsoft.com/en-us/windows/desktop/api/securitybaseapi/nf-securitybaseapi-settokeninformation BOOL // SetTokenInformation( HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD // TokenInformationLength ); public bool SetInfo(T TokenInformation) => CorrespondingTypeAttribute.CanSet(out var ti) ? SetTokenInformation(this, ti, TokenInformation) : throw new InvalidCastException("Cannot get this type."); } /// Provides a for that is disposed using . public class SafePrivateObjectSecurity : SafeHANDLE { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafePrivateObjectSecurity(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Initializes a new instance of the class. private SafePrivateObjectSecurity() : base() { } /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator PSECURITY_DESCRIPTOR(SafePrivateObjectSecurity h) => h.handle; /// Gets the raw handle instance for this SafeHandle. Be very careful!!. This should only be used with . /// The native handle, usually retrieved by . public ref IntPtr DangerousGetRefHandle() => ref handle; /// protected override bool InternalReleaseHandle() => DestroyPrivateObjectSecurity(this); } } }