Vanara/PInvoke/Security/AdvApi32/NTSecApi.Lsa.cs

3402 lines
172 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using Vanara.Extensions;
using Vanara.InteropServices;
using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
namespace Vanara.PInvoke
{
public static partial class AdvApi32
{
/// <summary>Flags that provide more information about the collision.</summary>
[PInvokeData("ntsecapi.h", MSDNShortId = "9f9d2f57-0e7f-4222-be35-e3f026b60e93")]
[Flags]
public enum CollisionFlags
{
2020-03-13 17:43:39 -04:00
/// <summary>The top-level name trust record is disabled during initial creation.</summary>
LSA_TLN_DISABLED_NEW = 0x00000001,
2020-03-13 17:43:39 -04:00
/// <summary>The top-level name trust record is disabled by the domain administrator.</summary>
LSA_TLN_DISABLED_ADMIN = 0x00000002,
2020-03-13 17:43:39 -04:00
/// <summary>The top-level name trust record is disabled due to a conflict.</summary>
LSA_TLN_DISABLED_CONFLICT = 0x00000004,
2020-03-13 17:43:39 -04:00
/// <summary>The domain information trust record is disabled by the domain administrator.</summary>
LSA_SID_DISABLED_ADMIN = 0x00000001,
2020-03-13 17:43:39 -04:00
/// <summary>The domain information trust record is disabled due to a conflict.</summary>
LSA_SID_DISABLED_CONFLICT = 0x00000002,
2020-03-13 17:43:39 -04:00
/// <summary>The domain information trust record is disabled by the domain administrator.</summary>
LSA_NB_DISABLED_ADMIN = 0x00000004,
2020-03-13 17:43:39 -04:00
/// <summary>The domain information trust record is disabled due to a conflict.</summary>
LSA_NB_DISABLED_CONFLICT = 0x00000008,
2020-03-13 17:43:39 -04:00
/// <summary>The domain information trust record is disabled.</summary>
LSA_FTRECORD_DISABLED_REASONS = 0x0000FFFF,
}
/// <summary>
/// <para>
/// The <c>LSA_FOREST_TRUST_COLLISION_RECORD_TYPE</c> enumeration defines the types of collision that can occur between Local
/// Security Authority forest trust records.
/// </para>
/// </summary>
/// <remarks>
/// <para>This enumeration is used by the LSA_FOREST_TRUST_COLLISION_RECORD structure.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/ne-ntsecapi-lsa_forest_trust_collision_record_type typedef enum {
// CollisionTdo, CollisionXref, CollisionOther } ;
[PInvokeData("ntsecapi.h", MSDNShortId = "67c89d75-2c2d-4980-a1c9-32e7f64a7b49")]
public enum LSA_FOREST_TRUST_COLLISION_RECORD_TYPE
{
/// <summary>Collision between TrustedDomain objects. This indicates a collision with a namespace element of another forest.</summary>
CollisionTdo,
/// <summary>Collision between cross-references. This indicates a collision with a domain in the same forest.</summary>
CollisionXref,
/// <summary>Collision that is not a collision between TrustedDomain objects or cross-references.</summary>
CollisionOther,
}
/// <summary>
/// <para>The <c>LSA_FOREST_TRUST_RECORD_TYPE</c> enumeration defines the type of a Local Security Authority forest trust record.</para>
/// </summary>
/// <remarks>
/// <para>This enumeration is used by the LSA_FOREST_TRUST_RECORD structure.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/ne-ntsecapi-lsa_forest_trust_record_type typedef enum
// LSA_FOREST_TRUST_RECORD_TYPE { ForestTrustTopLevelName , ForestTrustTopLevelNameEx , ForestTrustDomainInfo ,
// ForestTrustRecordTypeLast } ;
[PInvokeData("ntsecapi.h", MSDNShortId = "8a4a7080-fab0-4ab2-a0b4-e929cce21f0c")]
public enum LSA_FOREST_TRUST_RECORD_TYPE
{
/// <summary>Record contains an included top-level name.</summary>
ForestTrustTopLevelName,
/// <summary>Record contains an excluded top-level name.</summary>
ForestTrustTopLevelNameEx,
/// <summary>Record contains an LSA_FOREST_TRUST_DOMAIN_INFO structure.</summary>
ForestTrustDomainInfo,
/// <summary>Marks the end of an enumeration.</summary>
ForestTrustRecordTypeLast,
}
/// <summary>Flags used by LSA_FOREST_TRUST_RECORD.</summary>
[PInvokeData("ntsecapi.h", MSDNShortId = "19b4ee56-664f-4f37-bfc9-129032ebeb22")]
[Flags]
public enum LSA_TLN
{
/// <summary>
/// The top-level name trust record is disabled during initial creation. <note type="note">This flag MUST be used only with
/// forest trust record types of ForestTrustTopLevelName and ForestTrustTopLevelNameEx.</note>
/// </summary>
LSA_TLN_DISABLED_NEW = 0x00000001,
/// <summary>
/// The top-level name trust record is disabled by the domain administrator. <note type="note">This flag MUST be used only with
/// forest trust record types of ForestTrustTopLevelName and ForestTrustTopLevelNameEx.</note>
/// </summary>
LSA_TLN_DISABLED_ADMIN = 0x00000002,
/// <summary>
/// The top-level name trust record is disabled due to a conflict. <note type="note">This flag MUST be used only with forest
/// trust record types of ForestTrustTopLevelName and ForestTrustTopLevelNameEx.</note>
/// </summary>
LSA_TLN_DISABLED_CONFLICT = 0x00000004,
/// <summary>
/// The domain information trust record is disabled by the domain administrator. <note type="note">This flag MUST be used only
/// with a forest trust record type of ForestTrustDomainInfo.</note>
/// </summary>
LSA_SID_DISABLED_ADMIN = 0x00000001,
/// <summary>
/// The domain information trust record is disabled due to a conflict. <note type="note">This flag MUST be used only with a
/// forest trust record type of ForestTrustDomainInfo.</note>
/// </summary>
LSA_SID_DISABLED_CONFLICT = 0x00000002,
/// <summary>
/// The domain information trust record is disabled by the domain administrator. <note type="note">This flag MUST be used only
/// with a forest trust record type of ForestTrustDomainInfo.</note>
/// </summary>
LSA_NB_DISABLED_ADMIN = 0x00000004,
/// <summary>
/// The domain information trust record is disabled due to a conflict. <note type="note">This flag MUST be used only with a
/// forest trust record type of ForestTrustDomainInfo.</note>
/// </summary>
LSA_NB_DISABLED_CONFLICT = 0x00000008,
/// <summary>
/// The domain information trust record is disabled. <note type="note">This set of flags is reserved; for current and future
/// reasons, the trust is disabled.</note>
/// </summary>
LSA_FTRECORD_DISABLED_REASONS = 0x0000FFFF,
}
/// <summary>The Policy object has the following object-specific access types:</summary>
[Flags]
[PInvokeData("ntsecapi.h")]
public enum LsaPolicyRights : uint
{
/// <summary>
/// This access type is needed to read the target system's miscellaneous security policy information. This includes the default
/// quota, auditing, server state and role information, and trust information. This access type is also needed to enumerate
/// trusted domains, accounts, and privileges.
/// </summary>
POLICY_VIEW_LOCAL_INFORMATION = 1,
/// <summary>This access type is needed to view audit trail or audit requirements information.</summary>
POLICY_VIEW_AUDIT_INFORMATION = 2,
/// <summary>
/// This access type is needed to view sensitive information, such as the names of accounts established for trusted domain relationships.
/// </summary>
POLICY_GET_PRIVATE_INFORMATION = 4,
/// <summary>This access type is needed to change the account domain or primary domain information.</summary>
POLICY_TRUST_ADMIN = 8,
/// <summary>This access type is needed to create a new Account object.</summary>
POLICY_CREATE_ACCOUNT = 0x10,
/// <summary>This access type is needed to create a new Private Data object.</summary>
POLICY_CREATE_SECRET = 0x20,
/// <summary>Not yet supported.</summary>
POLICY_CREATE_PRIVILEGE = 0x40,
/// <summary>Set the default system quotas that are applied to user accounts.</summary>
POLICY_SET_DEFAULT_QUOTA_LIMITS = 0x80,
/// <summary>This access type is needed to update the auditing requirements of the system.</summary>
POLICY_SET_AUDIT_REQUIREMENTS = 0x100,
/// <summary>
/// This access type is needed to change the characteristics of the audit trail such as its maximum size or the retention period
/// for audit records, or to clear the log.
/// </summary>
POLICY_AUDIT_LOG_ADMIN = 0x200,
/// <summary>
/// This access type is needed to modify the server state or role (master/replica) information. It is also needed to change the
/// replica source and account name information.
/// </summary>
POLICY_SERVER_ADMIN = 0x400,
/// <summary>This access type is needed to translate between names and SIDs.</summary>
POLICY_LOOKUP_NAMES = 0x800,
/// <summary>The policy notification</summary>
POLICY_NOTIFICATION = 0x1000,
/// <summary>All access</summary>
POLICY_ALL_ACCESS = ACCESS_MASK.STANDARD_RIGHTS_REQUIRED |
POLICY_VIEW_LOCAL_INFORMATION |
POLICY_VIEW_AUDIT_INFORMATION |
POLICY_GET_PRIVATE_INFORMATION |
POLICY_TRUST_ADMIN |
POLICY_CREATE_ACCOUNT |
POLICY_CREATE_SECRET |
POLICY_CREATE_PRIVILEGE |
POLICY_SET_DEFAULT_QUOTA_LIMITS |
POLICY_SET_AUDIT_REQUIREMENTS |
POLICY_AUDIT_LOG_ADMIN |
POLICY_SERVER_ADMIN |
POLICY_LOOKUP_NAMES,
/// <summary>Read access</summary>
POLICY_READ = ACCESS_MASK.STANDARD_RIGHTS_READ |
POLICY_VIEW_AUDIT_INFORMATION |
POLICY_GET_PRIVATE_INFORMATION,
/// <summary>Write access</summary>
POLICY_WRITE = ACCESS_MASK.STANDARD_RIGHTS_WRITE |
POLICY_TRUST_ADMIN |
POLICY_CREATE_ACCOUNT |
POLICY_CREATE_SECRET |
POLICY_CREATE_PRIVILEGE |
POLICY_SET_DEFAULT_QUOTA_LIMITS |
POLICY_SET_AUDIT_REQUIREMENTS |
POLICY_AUDIT_LOG_ADMIN |
POLICY_SERVER_ADMIN,
/// <summary>Execute access</summary>
POLICY_EXECUTE = ACCESS_MASK.STANDARD_RIGHTS_EXECUTE |
POLICY_VIEW_LOCAL_INFORMATION |
POLICY_LOOKUP_NAMES,
}
/// <summary>
/// The <c>LsaAddAccountRights</c> function assigns one or more privileges to an account. If the account does not exist,
/// <c>LsaAddAccountRights</c> creates it.
/// </summary>
/// <param name="PolicyHandle">
/// A handle to a Policy object. The handle must have the POLICY_LOOKUP_NAMES access right. If the account identified by the
/// AccountSid parameter does not exist, the handle must have the POLICY_CREATE_ACCOUNT access right. For more information, see
/// Opening a Policy Object Handle.
/// </param>
/// <param name="AccountSid">Pointer to the SID of the account to which the function assigns privileges.</param>
/// <param name="UserRights">
/// Pointer to an array of LSA_UNICODE_STRING structures. Each structure contains the name of a privilege to add to the account. For
/// a list of privilege names, see Privilege Constants.
/// </param>
/// <param name="CountOfRights">Specifies the number of elements in the UserRights array.</param>
/// <returns>
/// <para>If the function succeeds, the return value is STATUS_SUCCESS.</para>
/// <para>
/// If the function fails, the return value is an NTSTATUS code, which can be the following value or one of the LSA Policy Function
/// Return Values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_NO_SUCH_PRIVILEGE</term>
/// <term>One of the privilege names is not valid.</term>
/// </item>
/// </list>
/// <para>You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code.</para>
/// </returns>
/// <remarks>
/// <para>If you specify privileges already granted to the account, they are ignored.</para>
/// <para>For an example that demonstrates calling this function, see Managing Account Permissions.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-lsaaddaccountrights NTSTATUS LsaAddAccountRights(
// LSA_HANDLE PolicyHandle, PSID AccountSid, PLSA_UNICODE_STRING UserRights, ULONG CountOfRights );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "66b78404-02c2-48e9-92c3-d27b68f77c23")]
public static extern NTStatus LsaAddAccountRights(LSA_HANDLE PolicyHandle, PSID AccountSid,
[In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringArrayMarshaler))] string[] UserRights, uint CountOfRights);
/// <summary>
/// The <c>LsaAddAccountRights</c> function assigns one or more privileges to an account. If the account does not exist,
/// <c>LsaAddAccountRights</c> creates it.
/// </summary>
/// <param name="PolicyHandle">
/// A handle to a Policy object. The handle must have the POLICY_LOOKUP_NAMES access right. If the account identified by the
/// AccountSid parameter does not exist, the handle must have the POLICY_CREATE_ACCOUNT access right. For more information, see
/// Opening a Policy Object Handle.
/// </param>
/// <param name="AccountSid">Pointer to the SID of the account to which the function assigns privileges.</param>
/// <param name="UserRights">
/// Pointer to an array of LSA_UNICODE_STRING structures. Each structure contains the name of a privilege to add to the account. For
/// a list of privilege names, see Privilege Constants.
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is STATUS_SUCCESS.</para>
/// <para>
/// If the function fails, the return value is an NTSTATUS code, which can be the following value or one of the LSA Policy Function
/// Return Values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_NO_SUCH_PRIVILEGE</term>
/// <term>One of the privilege names is not valid.</term>
/// </item>
/// </list>
/// <para>You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code.</para>
/// </returns>
/// <remarks>
/// <para>If you specify privileges already granted to the account, they are ignored.</para>
/// <para>For an example that demonstrates calling this function, see Managing Account Permissions.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-lsaaddaccountrights NTSTATUS LsaAddAccountRights(
// LSA_HANDLE PolicyHandle, PSID AccountSid, PLSA_UNICODE_STRING UserRights, ULONG CountOfRights );
[PInvokeData("ntsecapi.h", MSDNShortId = "66b78404-02c2-48e9-92c3-d27b68f77c23")]
public static NTStatus LsaAddAccountRights(LSA_HANDLE PolicyHandle, PSID AccountSid,
[In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringArrayMarshaler))] params string[] UserRights) =>
LsaAddAccountRights(PolicyHandle, AccountSid, UserRights, (uint)UserRights?.Length);
/// <summary>Undocumented function for creating an account.</summary>
/// <param name="PolicyHandle">A handle to a Policy object. For more information, see Opening a Policy Object Handle.</param>
/// <param name="AccountSid">Pointer to the SID of the account for which to enumerate privileges.</param>
/// <param name="DesiredAccess">The desired access.</param>
/// <param name="AccountHandle">The account handle.</param>
/// <returns>
/// If the function succeeds, the return value is STATUS_SUCCESS. If the function fails, the return value is an NTSTATUS code.For
/// more information, see LSA Policy Function Return Values. You can use the LsaNtStatusToWinError function to convert the NTSTATUS
/// code to a Windows error code.
/// </returns>
[PInvokeData("ntlsa.h")]
[DllImport(Lib.AdvApi32, ExactSpelling = true)]
public static extern NTStatus LsaCreateAccount(LSA_HANDLE PolicyHandle, PSID AccountSid, LsaAccountAccessMask DesiredAccess, out SafeLSA_HANDLE AccountHandle);
/// <summary>The <c>LsaCreateTrustedDomainEx</c> function establishes a new trusted domain by creating a new TrustedDomain object.</summary>
/// <param name="PolicyHandle">
/// A handle to a Policy object. For the object to be created, the caller must have permission to create children on the
/// <c>System</c> container. For information about policy object handles, see Opening a Policy Object Handle.
/// </param>
/// <param name="TrustedDomainInformation">
/// Pointer to a TRUSTED_DOMAIN_INFORMATION_EX structure that contains the name and SID of the new trusted domain.
/// </param>
/// <param name="AuthenticationInformation">
/// Pointer to a TRUSTED_DOMAIN_AUTH_INFORMATION structure that contains authentication information for the new trusted domain.
/// </param>
/// <param name="DesiredAccess">An ACCESS_MASK structure that specifies the accesses to be granted for the new trusted domain.</param>
/// <param name="TrustedDomainHandle">
/// <para>
/// Receives the LSA policy handle of the remote trusted domain. You can pass this handle into LSA function calls to manage the LSA
/// policy of the trusted domain.
/// </para>
/// <para>When your application no longer needs this handle, it should call LsaClose to delete the handle.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the function returns STATUS_SUCCESS.</para>
/// <para>
/// If the function fails, it returns an <c>NTSTATUS</c> code, which can be one of the following values or one of the LSA Policy
/// Function Return Values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_DIRECTORY_SERVICE_REQUIRED</term>
/// <term>The target system (specified in the TrustedDomainInformation parameter) for the TrustedDomain object is not a domain controller.</term>
/// </item>
/// <item>
/// <term>STATUS_INVALID_SID</term>
/// <term>The specified SID is not valid.</term>
/// </item>
/// <item>
/// <term>STATUS_UNSUCCESSFUL</term>
/// <term>Unable to determine whether the target system is a domain controller.</term>
/// </item>
/// </list>
/// <para>You can use the LsaNtStatusToWinError function to convert the <c>NTSTATUS</c> code to a Windows error code.</para>
/// </returns>
/// <remarks>
/// <c>LsaCreateTrustedDomainEx</c> does not check whether the specified domain name matches the specified SID or whether the SID and
/// name represent an actual domain.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsacreatetrusteddomainex NTSTATUS
// LsaCreateTrustedDomainEx( LSA_HANDLE PolicyHandle, PTRUSTED_DOMAIN_INFORMATION_EX TrustedDomainInformation,
// PTRUSTED_DOMAIN_AUTH_INFORMATION AuthenticationInformation, ACCESS_MASK DesiredAccess, PLSA_HANDLE TrustedDomainHandle );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "2f458098-9498-4f08-bd13-ac572678d734")]
public static extern NTStatus LsaCreateTrustedDomainEx(LSA_HANDLE PolicyHandle, in TRUSTED_DOMAIN_INFORMATION_EX TrustedDomainInformation,
in TRUSTED_DOMAIN_AUTH_INFORMATION AuthenticationInformation, ACCESS_MASK DesiredAccess, out SafeLSA_HANDLE TrustedDomainHandle);
/// <summary>
/// The <c>LsaDeleteTrustedDomain</c> function removes a trusted domain from the list of trusted domains for a system and deletes the
/// associated TrustedDomain object.
/// </summary>
/// <param name="PolicyHandle">A handle to a Policy object. For more information, see Opening a Policy Object Handle.</param>
/// <param name="TrustedDomainSid">Pointer to the SID of the trusted domain to be removed.</param>
/// <returns>
/// <para>If the function succeeds, the return value is STATUS_SUCCESS.</para>
/// <para>If the function fails, the return value is an NTSTATUS code. For more information, see LSA Policy Function Return Values.</para>
/// <para>You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsadeletetrusteddomain NTSTATUS LsaDeleteTrustedDomain(
// LSA_HANDLE PolicyHandle, PSID TrustedDomainSid );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "4a7afa28-1786-4a58-a955-d2d8b12e62e4")]
public static extern NTStatus LsaDeleteTrustedDomain(LSA_HANDLE PolicyHandle, PSID TrustedDomainSid);
/// <summary>
/// <para>The <c>LsaEnumerateAccountRights</c> function enumerates the privileges assigned to an account.</para>
/// </summary>
/// <param name="PolicyHandle">
/// <para>
/// A handle to a Policy object. The handle must have the POLICY_LOOKUP_NAMES access right. For more information, see Opening a
/// Policy Object Handle.
/// </para>
/// </param>
/// <param name="AccountSid">
/// <para>Pointer to the SID of the account for which to enumerate privileges.</para>
/// </param>
/// <param name="UserRights">
/// <para>
/// Receives a pointer to an array of LSA_UNICODE_STRING structures. Each structure contains the name of a privilege held by the
/// account. For a list of privilege names, see Privilege Constants
/// </para>
/// <para>When you no longer need the information, pass the returned pointer to LsaFreeMemory.</para>
/// </param>
/// <param name="CountOfRights">
/// <para>Pointer to a variable that receives the number of privileges in the UserRights array.</para>
/// </param>
/// <returns>
/// <para>If at least one account right is found, the function succeeds and returns STATUS_SUCCESS.</para>
/// <para>
/// If no account rights are found or if the function fails for any other reason, the function returns an NTSTATUS code such as
/// FILE_NOT_FOUND. For more information, see LSA Policy Function Return Values. Use the LsaNtStatusToWinError function to convert
/// the NTSTATUS code to a Windows error code.
/// </para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsaenumerateaccountrights NTSTATUS
// LsaEnumerateAccountRights( LSA_HANDLE PolicyHandle, PSID AccountSid, PLSA_UNICODE_STRING *UserRights, PULONG CountOfRights );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "3f4a4a9a-66ca-410a-8bdc-c390e8b966e3")]
public static extern NTStatus LsaEnumerateAccountRights(
LSA_HANDLE PolicyHandle,
PSID AccountSid,
out SafeLsaMemoryHandle UserRights,
out uint CountOfRights);
/// <summary>The LsaEnumerateAccountRights function enumerates the privileges assigned to an account.</summary>
/// <param name="PolicyHandle">
/// A handle to a Policy object. The handle must have the POLICY_LOOKUP_NAMES access right. For more information, see Opening a
/// Policy Object Handle.
/// </param>
/// <param name="AccountSid">Pointer to the SID of the account for which to enumerate privileges.</param>
/// <returns>
/// An enumeration of strings containing the names of privileges held by the account. For a list of privilege names, see Privilege Constants.
/// </returns>
public static IEnumerable<string> LsaEnumerateAccountRights(LSA_HANDLE PolicyHandle, PSID AccountSid)
{
var ret = LsaEnumerateAccountRights(PolicyHandle, AccountSid, out var mem, out var cnt);
var winErr = LsaNtStatusToWinError(ret);
if (winErr == Win32Error.ERROR_FILE_NOT_FOUND) return new string[0];
winErr.ThrowIfFailed();
return mem.DangerousGetHandle().ToIEnum<LSA_UNICODE_STRING>((int)cnt).Select(u => (string)u.ToString().Clone()).ToArray();
}
/// <summary>
/// <para>
/// The <c>LsaEnumerateAccountsWithUserRight</c> function returns the accounts in the database of a Local Security Authority (LSA)
/// Policy object that hold a specified privilege. The accounts returned by this function hold the specified privilege directly
/// through the user account, not as part of membership to a group.
/// </para>
/// </summary>
/// <param name="PolicyHandle">
/// <para>
/// A handle to a Policy object. The handle must have POLICY_LOOKUP_NAMES and POLICY_VIEW_LOCAL_INFORMATION user rights. For more
/// information, see Opening a Policy Object Handle.
/// </para>
/// </param>
/// <param name="UserRight">
/// <para>
/// Pointer to an LSA_UNICODE_STRING structure that specifies the name of a privilege. For a list of privileges, see Privilege
/// Constants and Account Rights Constants.
/// </para>
/// <para>
/// If this parameter is <c>NULL</c>, the function enumerates all accounts in the LSA database of the system associated with the
/// Policy object.
/// </para>
/// </param>
/// <param name="Buffer">
/// <para>
/// Pointer to a variable that receives a pointer to an array of LSA_ENUMERATION_INFORMATION structures. The <c>Sid</c> member of
/// each structure is a pointer to the security identifier (SID) of an account that holds the specified privilege.
/// </para>
/// <para>When you no longer need the information, free the memory by passing the returned pointer to the LsaFreeMemory function.</para>
/// </param>
/// <param name="CountReturned">
/// <para>Pointer to a variable that receives the number of entries returned in the EnumerationBuffer parameter.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the function returns STATUS_SUCCESS.</para>
/// <para>
/// If the function fails, it returns an <c>NTSTATUS</c> code, which can be one of the following values or one of the LSA Policy
/// Function Return Values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_NO_SUCH_PRIVILEGE</term>
/// <term>The privilege string specified was not a valid privilege.</term>
/// </item>
/// <item>
/// <term>STATUS_NO_MORE_ENTRIES</term>
/// <term>There were no accounts with the specified privilege.</term>
/// </item>
/// </list>
/// <para>You can use the LsaNtStatusToWinError function to convert the <c>NTSTATUS</c> code to a Windows error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsaenumerateaccountswithuserright NTSTATUS
// LsaEnumerateAccountsWithUserRight( LSA_HANDLE PolicyHandle, PLSA_UNICODE_STRING UserRight, PVOID *Buffer, PULONG CountReturned );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "97e7180e-4edb-4edd-915e-0477e7e7a9ff")]
// public static extern NTSTATUS LsaEnumerateAccountsWithUserRight(LSA_HANDLE PolicyHandle, PLSA_UNICODE_STRING UserRight, ref IntPtr
// Buffer, ref uint CountReturned);
public static extern NTStatus LsaEnumerateAccountsWithUserRight(
LSA_HANDLE PolicyHandle,
[In, Optional, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringMarshaler))] string UserRight,
out SafeLsaMemoryHandle Buffer,
out int CountReturned);
/// <summary>
/// The LsaEnumerateAccountsWithUserRight function returns the accounts in the database of a Local Security Authority (LSA) Policy
/// object that hold a specified privilege. The accounts returned by this function hold the specified privilege directly through the
/// user account, not as part of membership to a group.
/// </summary>
/// <param name="PolicyHandle">
/// A handle to a Policy object. The handle must have POLICY_LOOKUP_NAMES and POLICY_VIEW_LOCAL_INFORMATION user rights. For more
/// information, see Opening a Policy Object Handle.
/// </param>
/// <param name="UserRights">
/// A string that specifies the name of a privilege. For a list of privileges, see Privilege Constants and Account Rights Constants.
/// <para>
/// If this parameter is NULL, the function enumerates all accounts in the LSA database of the system associated with the Policy object.
/// </para>
/// </param>
/// <returns>An enumeration of security identifiers (SID) of accounts that holds the specified privilege.</returns>
public static IEnumerable<PSID> LsaEnumerateAccountsWithUserRight(LSA_HANDLE PolicyHandle, [Optional] string UserRights)
{
var ret = LsaEnumerateAccountsWithUserRight(PolicyHandle, UserRights, out var mem, out var cnt);
if (ret == NTStatus.STATUS_NO_MORE_ENTRIES) return new PSID[0];
LsaNtStatusToWinError(ret).ThrowIfFailed();
return mem.DangerousGetHandle().ToIEnum<LSA_ENUMERATION_INFORMATION>(cnt).Select(u => u.Sid).ToArray();
}
/// <summary>
/// <para>
/// The <c>LsaEnumerateTrustedDomains</c> function retrieves the names and SIDs of domains trusted to authenticate logon credentials.
/// <c>LsaEnumerateTrustedDomains</c> is intended for use on systems running Windows NT 4.0 or earlier versions of Windows NT. Use
/// DsEnumerateDomainTrusts for any other trust enumeration purpose. Specifically, <c>LsaEnumerateTrustedDomains</c> can only be used
/// if one or more of the following is true:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>The calling system is running Windows NT 4.0 or an earlier version of Windows NT.</term>
/// </item>
/// <item>
/// <term>
/// The target system (specified using the PolicyHandle parameter), is a domain controller running Windows NT 4.0 or an earlier version.
/// </term>
/// </item>
/// <item>
/// <term>
/// The calling system is running Windows NT 4.0 or earlier version and is not a domain controller, and the target system is a domain
/// controller in the calling system's domain. The target system can be running any version of Windows NT, including Windows 2000 and
/// Windows XP.
/// </term>
/// </item>
/// </list>
/// </summary>
/// <param name="PolicyHandle">
/// A handle to a Policy object. The handle must have the POLICY_VIEW_LOCAL_INFORMATION access right. For more information, see
/// Opening a Policy Object Handle.
/// </param>
/// <param name="EnumerationContext">
/// Pointer to an enumeration handle that enables you to make multiple calls to enumerate all the trusted domains. On the first call
/// to <c>LsaEnumerateTrustedDomains</c>, EnumerationContext must point to a variable that has been initialized to zero. On
/// subsequent calls to <c>LsaEnumerateTrustedDomains</c>, EnumerationContext must point to the enumeration handle returned by the
/// previous call.
/// </param>
/// <param name="Buffer">
/// <para>
/// Receives a pointer to an array of LSA_TRUST_INFORMATION structures that contain the names and SIDs of one or more trusted domains.
/// </para>
/// <para>When you no longer need the information, pass the returned pointer to LsaFreeMemory.</para>
/// </param>
/// <param name="PreferedMaximumLength">
/// Specifies the preferred maximum size, in bytes, of the returned buffer. This information is approximate; the actual number of
/// bytes returned may be greater than this value.
/// </param>
/// <param name="CountReturned">Pointer to a variable that receives the number of elements returned in the Buffer parameter.</param>
/// <returns>
/// <para>If the function is successful, the return value is one of the following NTSTATUS values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_SUCCESS</term>
/// <term>The enumeration has been successfully completed.</term>
/// </item>
/// <item>
/// <term>STATUS_MORE_ENTRIES</term>
/// <term>
/// The call was successful, but there are more trusted domains to be enumerated. Call LsaEnumerateTrustedDomains again, passing the
/// value returned in the EnumerationContext parameter.
/// </term>
/// </item>
/// <item>
/// <term>STATUS_NO_MORE_ENTRIES</term>
/// <term>There are no more trusted domains to enumerate.</term>
/// </item>
/// </list>
/// <para>If the function fails, the return value is an NTSTATUS code. For more information, see LSA Policy Function Return Values.</para>
/// <para>You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code.</para>
/// </returns>
/// <remarks>
/// <para>
/// For domains with domain controllers running only Windows NT 4.0 or earlier versions of Windows NT,
/// <c>LsaEnumerateTrustedDomains</c> returns a list of all trusted domains. In releases of Windows NT up to and including release
/// 4.0, all trusted domains are directly trusted.
/// </para>
/// <para>
/// In Windows XP and Windows 2000 mixed-mode domains, domain controllers may be running Windows XP, Windows 2000, or Windows NT.
/// Therefore, in mixed-mode domains, some trusted domains are directly trusted and others are indirectly trusted. When enumerating
/// the trusted domains of a system in a mixed-mode domain, <c>LsaEnumerateTrustedDomains</c> returns only directly trusted domains.
/// </para>
/// <para>
/// In contrast, Windows XP and Windows 2000 native-mode domains contain only Windows 2000 domain controllers, even though there may
/// be members in the domain running Windows NT 4.0 or earlier versions. When enumerating the trusted domains of a system in a
/// native-mode Windows XP and Windows 2000 domain, <c>LsaEnumerateTrustedDomains</c> returns both directly trusted and indirectly
/// trusted domains.
/// </para>
/// <para>
/// Retrieving all trust information may require more than a single <c>LsaEnumerateTrustedDomains</c> call. You can use the
/// EnumerationContext parameter to make multiple calls, as follows: On the first call, set the variable pointed to by
/// EnumerationContext to zero. If <c>LsaEnumerateTrustedDomains</c> returns STATUS_SUCCESS or STATUS_MORE_ENTRIES, call the function
/// again, passing in the EnumerationContext value returned by the previous call. The enumeration is complete when the function
/// returns STATUS_NO_MORE_ENTRIES.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsaenumeratetrusteddomains NTSTATUS
// LsaEnumerateTrustedDomains( LSA_HANDLE PolicyHandle, PLSA_ENUMERATION_HANDLE EnumerationContext, PVOID *Buffer, ULONG
// PreferedMaximumLength, PULONG CountReturned );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "5c371d5a-26cf-4a99-a8e1-006b6b3cc91f")]
public static extern NTStatus LsaEnumerateTrustedDomains(LSA_HANDLE PolicyHandle, ref LSA_ENUMERATION_HANDLE EnumerationContext, out SafeLsaMemoryHandle Buffer, uint PreferedMaximumLength, out uint CountReturned);
/// <summary>
/// <para>
/// The <c>LsaEnumerateTrustedDomains</c> function retrieves the names and SIDs of domains trusted to authenticate logon credentials.
/// <c>LsaEnumerateTrustedDomains</c> is intended for use on systems running Windows NT 4.0 or earlier versions of Windows NT. Use
/// DsEnumerateDomainTrusts for any other trust enumeration purpose. Specifically, <c>LsaEnumerateTrustedDomains</c> can only be used
/// if one or more of the following is true:
/// </para>
/// <list type="bullet">
/// <item>
/// <term>The calling system is running Windows NT 4.0 or an earlier version of Windows NT.</term>
/// </item>
/// <item>
/// <term>
/// The target system (specified using the PolicyHandle parameter), is a domain controller running Windows NT 4.0 or an earlier version.
/// </term>
/// </item>
/// <item>
/// <term>
/// The calling system is running Windows NT 4.0 or earlier version and is not a domain controller, and the target system is a domain
/// controller in the calling system's domain. The target system can be running any version of Windows NT, including Windows 2000 and
/// Windows XP.
/// </term>
/// </item>
/// </list>
/// </summary>
/// <param name="PolicyHandle">
/// A handle to a Policy object. The handle must have the POLICY_VIEW_LOCAL_INFORMATION access right. For more information, see
/// Opening a Policy Object Handle.
/// </param>
/// <returns>An enumeration of LSA_TRUST_INFORMATION structures that contain the names and SIDs of one or more trusted domains.</returns>
[PInvokeData("ntsecapi.h", MSDNShortId = "5c371d5a-26cf-4a99-a8e1-006b6b3cc91f")]
public static IEnumerable<LSA_TRUST_INFORMATION> LsaEnumerateTrustedDomains(LSA_HANDLE PolicyHandle)
{
const uint maxBuf = 4096;
var hEnum = LSA_ENUMERATION_HANDLE.NULL;
NTStatus ret = NTStatus.STATUS_SUCCESS;
while ((ret = LsaEnumerateTrustedDomains(PolicyHandle, ref hEnum, out var buf, maxBuf, out var count)) == NTStatus.STATUS_MORE_ENTRIES)
{
foreach (var i in buf.ToArray<LSA_TRUST_INFORMATION>((int)count))
yield return i;
}
ret.ThrowIfFailed();
}
/// <summary>
/// The <c>LsaEnumerateTrustedDomainsEx</c> function returns information about the domains trusted by the local system.
/// <c>LsaEnumerateTrustedDomainsEx</c> returns information only on direct trusts. DsEnumerateDomainTrusts is recommended for more
/// complete trust enumeration purposes.
/// </summary>
/// <param name="PolicyHandle">
/// A handle to a Policy object. This call requires POLICY_VIEW_LOCAL_INFORMATION access to the <c>Policy</c> object. For more
/// information, see Opening a Policy Object Handle.
/// </param>
/// <param name="EnumerationContext">
/// A pointer to an LSA_ENUMERATION_HANDLE that you can use to make multiple calls to <c>LsaEnumerateTrustedDomainsEx</c> to retrieve
/// all of the trusted domain information. For more information, see Remarks.
/// </param>
/// <param name="Buffer">
/// <para>
/// Pointer to a buffer that receives a list of TRUSTED_DOMAIN_INFORMATION_EX structures that contain information about the
/// enumerated trusted domains.
/// </para>
/// <para>Your application should free this buffer when it is no longer needed by calling LsaFreeMemory.</para>
/// </param>
/// <param name="PreferedMaximumLength">
/// Preferred maximum length, in bytes, of returned data. This is not a hard upper limit, but serves as a guide. Due to data
/// conversion between systems with different natural data sizes, the actual amount of data returned may be greater than this value.
/// </param>
/// <param name="CountReturned">Pointer to a <c>LONG</c> that receives the number of trusted domain objects returned.</param>
/// <returns>
/// <para>If the function succeeds, the function returns STATUS_SUCCESS.</para>
/// <para>
/// If the function fails, it returns an <c>NTSTATUS</c> code, which can be one of the following values or one of the LSA Policy
/// Function Return Values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_ACCESS_DENIED</term>
/// <term>Caller does not have the appropriate access to complete the operation.</term>
/// </item>
/// <item>
/// <term>STATUS_NO_MORE_ENTRIES</term>
/// <term>
/// There are no more entries. This warning is returned if no objects have been enumerated because the EnumerationContext value is
/// too high.
/// </term>
/// </item>
/// </list>
/// <para>You can use the LsaNtStatusToWinError function to convert the <c>NTSTATUS</c> code to a Windows error code.</para>
/// </returns>
/// <remarks>
/// <para>Retrieving all trust information may require more than a single <c>LsaEnumerateTrustedDomainsEx</c> call.</para>
/// <para><c>To use the EnumerationContext parameter to make multiple calls</c></para>
/// <list type="number">
/// <item>
/// <term>Set the variable pointed to by EnumerationContext to zero.</term>
/// </item>
/// <item>
/// <term>
/// If <c>LsaEnumerateTrustedDomainsEx</c> returns STATUS_SUCCESS or STATUS_MORE_ENTRIES, call the function again, passing in the
/// EnumerationContext value returned by the previous call.
/// </term>
/// </item>
/// <item>
/// <term>The enumeration is complete when the function returns STATUS_NO_MORE_ENTRIES.</term>
/// </item>
/// </list>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsaenumeratetrusteddomainsex NTSTATUS
// LsaEnumerateTrustedDomainsEx( LSA_HANDLE PolicyHandle, PLSA_ENUMERATION_HANDLE EnumerationContext, PVOID *Buffer, ULONG
// PreferedMaximumLength, PULONG CountReturned );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "4a203bff-c3e1-4d95-b556-617dc8c2e8c2")]
public static extern NTStatus LsaEnumerateTrustedDomainsEx(LSA_HANDLE PolicyHandle, ref LSA_ENUMERATION_HANDLE EnumerationContext, out SafeLsaMemoryHandle Buffer, uint PreferedMaximumLength, out uint CountReturned);
/// <summary>[Undocumented] Gets system access for an account.</summary>
/// <param name="AccountHandle">The account handle.</param>
/// <param name="SystemAccess">The system access.</param>
/// <returns>If the function succeeds, the function returns one of the following <c>NTSTATUS</c> values.</returns>
[PInvokeData("ntlsa.h")]
[DllImport(Lib.AdvApi32, ExactSpelling = true)]
public static extern NTStatus LsaGetSystemAccessAccount(LSA_HANDLE AccountHandle, out int SystemAccess);
/// <summary>
/// <para>
/// The <c>LsaLookupNames</c> function retrieves the security identifiers (SIDs) that correspond to an array of user, group, or local
/// group names.
/// </para>
/// <para>
/// The <c>LsaLookupNames</c> function is superseded by the LsaLookupNames2 function. Applications should use the
/// <c>LsaLookupNames2</c> function to ensure future compatibility.
/// </para>
/// <para>The <c>LsaLookupNames</c> function can also retrieve computer accounts.</para>
/// </summary>
/// <param name="PolicyHandle">
/// A handle to a Policy object. The handle must have the POLICY_LOOKUP_NAMES access right. For more information, see Opening a
/// Policy Object Handle.
/// </param>
/// <param name="Count">
/// Specifies the number of names in the Names array. This is also the number of entries returned in the Sids array.
/// </param>
/// <param name="Names">
/// <para>
/// Pointer to an array of LSA_UNICODE_STRING structures that contain the names to look up. The strings in these structures can be
/// the names of user, group, or local group accounts, or the names of domains. Domain names can be DNS domain names or NetBIOS
/// domain names.
/// </para>
/// <para>For more information about the format of the name strings, see Remarks.</para>
/// </param>
/// <param name="ReferencedDomains">
/// <para>
/// Receives a pointer to an LSA_REFERENCED_DOMAIN_LIST structure. The <c>Domains</c> member of this structure is an array that
/// contains an entry for each domain in which a name was found. The <c>DomainIndex</c> member of each entry in the Sids array is the
/// index of the <c>Domains</c> array entry for the domain in which the name was found.
/// </para>
/// <para>
/// When you have finished using the returned pointer, free the memory by calling the LsaFreeMemory function. This memory must be
/// freed even when the function fails with the either of the error codes <c>STATUS_NONE_MAPPED</c> or <c>STATUS_SOME_NOT_MAPPED</c>
/// </para>
/// </param>
/// <param name="Sids">
/// <para>
/// Receives a pointer to an array of LSA_TRANSLATED_SID structures. Each entry in the Sids array contains the SID information for
/// the corresponding entry in the Names array.
/// </para>
/// <para>
/// When you have finished using the returned pointer, free the memory by calling the LsaFreeMemory function. This memory must be
/// freed even when the function fails with the either of the error codes <c>STATUS_NONE_MAPPED</c> or <c>STATUS_SOME_NOT_MAPPED</c>
/// </para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the function returns one of the following <c>NTSTATUS</c> values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_SOME_NOT_MAPPED</term>
/// <term>Some of the names could not be translated. This is an informational-level return value.</term>
/// </item>
/// <item>
/// <term>STATUS_SUCCESS</term>
/// <term>All of the names were found and successfully translated.</term>
/// </item>
/// </list>
/// <para>
/// If the function fails, the return value is the following <c>NTSTATUS</c> value or one of the LSA Policy Function Return Values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_NONE_MAPPED</term>
/// <term>None of the names were translated.</term>
/// </item>
/// </list>
/// <para>Use the LsaNtStatusToWinError function to convert the <c>NTSTATUS</c> code to a Windows error code.</para>
/// </returns>
/// <remarks>
/// <para>
/// Use fully qualified account names (for example, domain_name\user_name) instead of isolated names (for example, user_name). Fully
/// qualified names are unambiguous and provide better performance when the lookup is performed. This function also supports fully
/// qualified DNS names (for example, example.example.com\user_name) and user principal names (UPN) (for example, someone@example.com).
/// </para>
/// <para>
/// Translation of isolated names introduces the possibility of name collisions because the same name may be used in multiple
/// domains. The <c>LsaLookupNames</c> function uses the following algorithm to translate isolated names
/// </para>
/// <para><c>To translate isolated names</c></para>
/// <list type="number">
/// <item>
/// <term>
/// If the name is a well-known name, such as Local or Interactive, the function returns the corresponding well-known security
/// identifier (SID).
/// </term>
/// </item>
/// <item>
/// <term>If the name is the name of the built-in domain, the function returns the SID of that domain.</term>
/// </item>
/// <item>
/// <term>If the name is the name of the account domain, the function returns the SID of that domain.</term>
/// </item>
/// <item>
/// <term>If the name is the name of the primary domain, the function returns the SID of that domain.</term>
/// </item>
/// <item>
/// <term>If the name is one of the names of the trusted domain, the function returns the SID of that domain.</term>
/// </item>
/// <item>
/// <term>If the name is a user, group, or local group account in the built-in domain, the function returns the SID of that account.</term>
/// </item>
/// <item>
/// <term>
/// If the name is a user, group, or local group account in the account domain on the local system, the function returns the SID of
/// that account.
/// </term>
/// </item>
/// <item>
/// <term>If the name is a user, group, or a local group in the primary domain, the function returns the SID of that account.</term>
/// </item>
/// <item>
/// <term>After looking in the primary domain, the primary domain looks in each of its trusted domains.</term>
/// </item>
/// <item>
/// <term>Otherwise, the name is not translated.</term>
/// </item>
/// </list>
/// <para>
/// In addition to looking up local accounts, local domain accounts, and explicitly trusted domain accounts, <c>LsaLookupNames</c>
/// can look up the name of any account in any domain in the Windows forest.
/// </para>
/// <para>Examples</para>
/// <para>For an example that calls this function, see Translating Between Names and SIDs.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsalookupnames NTSTATUS LsaLookupNames( LSA_HANDLE
// PolicyHandle, ULONG Count, PLSA_UNICODE_STRING Names, PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains, PLSA_TRANSLATED_SID *Sids );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "867604aa-7a39-4da7-b189-a9183461e9a0")]
public static extern NTStatus LsaLookupNames(LSA_HANDLE PolicyHandle, uint Count, [In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringArrayMarshaler))] string[] Names,
out SafeLsaMemoryHandle ReferencedDomains, out SafeLsaMemoryHandle Sids);
/// <summary>
/// <para>
/// The <c>LsaLookupNames2</c> function retrieves the security identifiers (SIDs) for specified account names. <c>LsaLookupNames2</c>
/// can look up the SID for any account in any domain in a Windows forest.
/// </para>
/// <para>
/// The LsaLookupNames function is superseded by the <c>LsaLookupNames2</c> function. Applications should use the
/// <c>LsaLookupNames2</c> function to ensure future compatibility.
/// </para>
/// <para>
/// This function differs from the LsaLookupNames function in that <c>LsaLookupNames2</c> returns each SID as a single element, while
/// <c>LsaLookupNames</c> divides each SID into an RID/domain pair.
/// </para>
/// </summary>
/// <param name="PolicyHandle">
/// <para>
/// A handle to a Policy object. The handle must have the POLICY_LOOKUP_NAMES access right. For more information, see Opening a
/// Policy Object Handle.
/// </para>
/// </param>
/// <param name="Flags">
/// <para>Values that control the behavior of this function. The following value is currently defined.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>LSA_LOOKUP_ISOLATED_AS_LOCAL 0x80000000</term>
/// <term>
/// The function searches only on the local systems for names that do not specify a domain. The function does search on remote
/// systems for names that do specify a domain.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="Count">
/// <para>Specifies the number of names in the Names array. This is also the number of entries returned in the Sids array.</para>
/// </param>
/// <param name="Names">
/// <para>
/// Pointer to an array of LSA_UNICODE_STRING structures that contain the names to look up. These strings can be the names of user,
/// group, or local group accounts, or the names of domains. Domain names can be DNS domain names or NetBIOS domain names.
/// </para>
/// <para>For more information about the format of the name strings, see Remarks.</para>
/// </param>
/// <param name="ReferencedDomains">
/// <para>
/// Receives a pointer to an LSA_REFERENCED_DOMAIN_LIST structure. The <c>Domains</c> member of this structure is an array that
/// contains an entry for each domain in which a name was found. The <c>DomainIndex</c> member of each entry in the Sids array is the
/// index of the <c>Domains</c> array entry for the domain in which the name was found.
/// </para>
/// <para>
/// When you have finished using the returned pointer, free it by calling the LsaFreeMemory function. This memory must be freed even
/// when the function fails with the either of the error codes <c>STATUS_NONE_MAPPED</c> or <c>STATUS_SOME_NOT_MAPPED</c>
/// </para>
/// </param>
/// <param name="Sids">
/// <para>
/// Receives a pointer to an array of LSA_TRANSLATED_SID2 structures. Each entry in the Sids array contains the SID information for
/// the corresponding entry in the Names array.
/// </para>
/// <para>
/// When you have finished using the returned pointer, free it by calling the LsaFreeMemory function. This memory must be freed even
/// when the function fails with the either of the error codes <c>STATUS_NONE_MAPPED</c> or <c>STATUS_SOME_NOT_MAPPED</c>
/// </para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the function returns one of the following <c>NTSTATUS</c> values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_SOME_NOT_MAPPED</term>
/// <term>Some of the names could not be translated. This is an informational-level return value.</term>
/// </item>
/// <item>
/// <term>STATUS_SUCCESS</term>
/// <term>All of the names were found and successfully translated.</term>
/// </item>
/// </list>
/// <para>
/// If the function fails, the return value is the following <c>NTSTATUS</c> value or one of the LSA Policy Function Return Values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_NONE_MAPPED</term>
/// <term>None of the names were translated.</term>
/// </item>
/// </list>
/// <para>Use the LsaNtStatusToWinError function to convert the <c>NTSTATUS</c> code to a Windows error code.</para>
/// </returns>
/// <remarks>
/// <para>
/// Use fully qualified account names (for example, DomainName&lt;i&gt;UserName) instead of isolated names (for example, UserName).
/// Fully qualified names are unambiguous and provide better performance when the lookup is performed. This function also supports
/// fully qualified DNS names (for example, Example.Example.com&lt;i&gt;UserName) and user principal names (UPN) (for example, Someone@Example.com).
/// </para>
/// <para>
/// Translation of isolated names introduces the possibility of name collisions because the same name may be used in multiple
/// domains. The <c>LsaLookupNames2</c> function uses the following algorithm to translate isolated names.
/// </para>
/// <para><c>To translate isolated names</c></para>
/// <list type="number">
/// <item>
/// <term>
/// If the name is a well-known name, such as Local or Interactive, the function returns the corresponding well-known security
/// identifier (SID).
/// </term>
/// </item>
/// <item>
/// <term>If the name is the name of the built-in domain, the function returns the SID of that domain.</term>
/// </item>
/// <item>
/// <term>If the name is the name of the account domain, the function returns the SID of that domain.</term>
/// </item>
/// <item>
/// <term>If the name is the name of the primary domain, the function returns the SID of that domain.</term>
/// </item>
/// <item>
/// <term>If the name is one of the names of the trusted domain, the function returns the SID of that domain.</term>
/// </item>
/// <item>
/// <term>If the name is a user, group, or local group account in the built-in domain, the function returns the SID of that account.</term>
/// </item>
/// <item>
/// <term>
/// If the name is a user, group, or local group account in the account domain on the local system, the function returns the SID of
/// that account.
/// </term>
/// </item>
/// <item>
/// <term>If the name is a user, group, or a local group in the primary domain, the function returns the SID of that account.</term>
/// </item>
/// <item>
/// <term>After looking in the primary domain, the function looks in each of the primary domain's trusted domains.</term>
/// </item>
/// <item>
/// <term>Otherwise, the name is not translated.</term>
/// </item>
/// </list>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsalookupnames2 NTSTATUS LsaLookupNames2( LSA_HANDLE
// PolicyHandle, ULONG Flags, ULONG Count, PLSA_UNICODE_STRING Names, PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains,
// PLSA_TRANSLATED_SID2 *Sids );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true, CharSet = CharSet.Unicode)]
[PInvokeData("ntsecapi.h", MSDNShortId = "fe219070-6a00-4b8c-b2e4-2ad290a1cb9c")]
// public static extern NTSTATUS LsaLookupNames2(LSA_HANDLE PolicyHandle, uint Flags, uint Count, PLSA_UNICODE_STRING Names, ref
// PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains, ref PLSA_TRANSLATED_SID2 Sids);
public static extern NTStatus LsaLookupNames2(
LSA_HANDLE PolicyHandle,
LsaLookupNamesFlags Flags,
uint Count,
[In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringArrayMarshaler))]
string[] Names,
out SafeLsaMemoryHandle ReferencedDomains,
out SafeLsaMemoryHandle Sids);
/// <summary>
/// <para>
/// [ <c>LsaLookupSids</c> is available for use in the operating systems specified in the Requirements section. It may be altered or
/// unavailable in subsequent versions. Instead, use LsaLookupSids2.]
/// </para>
/// <para>
/// The <c>LsaLookupSids</c> function looks up the names that correspond to an array of security identifiers (SIDs). If
/// <c>LsaLookupSids</c> cannot find a name that corresponds to a SID, the function returns the SID in character form.
/// </para>
/// </summary>
/// <param name="PolicyHandle">
/// A handle to a Policy object. This handle must have the POLICY_LOOKUP_NAMES access right. For more information, see Opening a
/// Policy Object Handle.
/// </param>
/// <param name="Count">
/// Specifies the number of SIDs in the Sids array. This is also the number of entries returned in the Names array.
/// </param>
/// <param name="Sids">
/// Pointer to an array of SID pointers to look up. The SIDs can be well-known SIDs, user, group, or local group account SIDs, or
/// domain SIDs.
/// </param>
/// <param name="ReferencedDomains">
/// <para>
/// Receives a pointer to a pointer to a LSA_REFERENCED_DOMAIN_LIST structure. The <c>Domains</c> member of this structure is an
/// array that contains an entry for each domain in which a SID was found. The entry for each domain contains the SID and flat name
/// of the domain. For Windows domains, the flat name is the NetBIOS name. For links with nonWindows domains, the flat name is the
/// identifying name of that domain, or it is <c>NULL</c>.
/// </para>
/// <para>
/// When you no longer need the information, pass the returned pointer to LsaFreeMemory. This memory must be freed even when the
/// function fails with the either of the error codes <c>STATUS_NONE_MAPPED</c> or <c>STATUS_SOME_NOT_MAPPED</c>
/// </para>
/// </param>
/// <param name="Names">
/// <para>
/// Receives a pointer to an array of LSA_TRANSLATED_NAME structures. Each entry in the Names array contains the name information for
/// the corresponding entry in the Sids array. For account SIDs, the <c>Name</c> member of each structure contains the isolated name
/// of the account. For domain SIDs, the <c>Name</c> member is not valid.
/// </para>
/// <para>
/// The <c>DomainIndex</c> member of each entry in the Names array is the index of an entry in the <c>Domains</c> array returned in
/// the ReferencedDomains parameter. The index identifies the <c>Domains</c> array for the domain in which the SID was found.
/// </para>
/// <para>
/// When you no longer need the information, pass the returned pointer to LsaFreeMemory. This memory must be freed even when the
/// function fails with the either of the error codes <c>STATUS_NONE_MAPPED</c> or <c>STATUS_SOME_NOT_MAPPED</c>
/// </para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is one of the following <c>NTSTATUS</c> values.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_SOME_NOT_MAPPED</term>
/// <term>Some of the SIDs could not be translated. This is an informational-level return value.</term>
/// </item>
/// <item>
/// <term>STATUS_SUCCESS</term>
/// <term>All of the SIDs were found and successfully translated.</term>
/// </item>
/// </list>
/// <para>
/// If the function fails, the return value is an <c>NTSTATUS</c> code, which can be one of the following values or one of the LSA
/// Policy Function Return Values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_NONE_MAPPED</term>
/// <term>None of the SIDs were translated. This is an error-level return value.</term>
/// </item>
/// </list>
/// <para>You can use the LsaNtStatusToWinError function to convert the <c>NTSTATUS</c> code to a Windows error code.</para>
/// </returns>
/// <remarks>
/// <para>
/// For account SIDs, the string returned in the <c>Name</c> member is the isolated name of the account (for example, user_name). If
/// you need the composite name of the account (for example, Acctg\user_name), get the domain name from the ReferencedDomains buffer
/// and append a backslash and the isolated name.
/// </para>
/// <para>If the <c>LsaLookupSids</c> function cannot translate a SID, the function uses the following algorithm:</para>
/// <list type="number">
/// <item>
/// <term>
/// If the SID's domain is known, the ReferencedDomains buffer contains an entry for the domain, and the string returned in the Names
/// parameter is a Unicode representation of the account's relative identifier (RID) from the SID.
/// </term>
/// </item>
/// <item>
/// <term>
/// If the SID's domain is not known, the string returned in the Names parameter is a Unicode representation of the entire SID, and
/// there is no domain record for this SID in the ReferencedDomains buffer.
/// </term>
/// </item>
/// </list>
/// <para>
/// In addition to looking up SIDs for local accounts, local domain accounts, and explicitly trusted domain accounts,
/// <c>LsaLookupSids</c> can look up SIDs for any account in any domain in the Windows forest, including SIDs that appear only in the
/// <c>SIDhistory</c> field of an account in the forest. The <c>SIDhistory</c> field stores the former SIDs of an account that has
/// been moved from another domain. To perform these searches, the function queries the global catalog of the forest.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsalookupsids NTSTATUS LsaLookupSids( LSA_HANDLE
// PolicyHandle, ULONG Count, PSID *Sids, PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains, PLSA_TRANSLATED_NAME *Names );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "69051bad-91e7-469d-9010-48ac3d20f8af")]
public static extern NTStatus LsaLookupSids(LSA_HANDLE PolicyHandle, uint Count, [In] PSID[] Sids, out SafeLsaMemoryHandle ReferencedDomains, out SafeLsaMemoryHandle Names);
/// <summary>
/// <para>
/// The <c>LsaLookupSids2</c> function looks up the names that correspond to an array of security identifiers (SIDs) and supports
/// Internet provider identities. If <c>LsaLookupSids2</c> cannot find a name that corresponds to a SID, the function returns the SID
/// in character form. You should use this function instead of the LsaLookupSids function.
/// </para>
/// </summary>
/// <param name="PolicyHandle">
/// <para>
/// A handle to a Policy object. This handle must have the POLICY_LOOKUP_NAMES access right. For more information, see Opening a
/// Policy Object Handle.
/// </para>
/// </param>
/// <param name="LookupOptions">
/// <para>Flags that modify the lookup behavior.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>LSA_LOOKUP_DISALLOW_CONNECTED_ACCOUNT_INTERNET_SID</term>
/// <term>
/// Internet SIDs from identity providers for connected accounts are disallowed. Connected accounts are those accounts which have a
/// corresponding shadow account in the local SAM database connected to an online identity provider. For example, MicrosoftAccount is
/// a connected account.
/// </term>
/// </item>
/// <item>
/// <term>LSA_LOOKUP_PREFER_INTERNET_NAMES</term>
/// <term>
/// Returns the internet names. Otherwise the NT4 style name (domain\username) is returned. The exception is if the Microsoft Account
/// internet SID is specified, in which case the internet name is returned unless LSA_LOOKUP_DISALLOW_NON_WINDOWS_INTERNET_SID is specified.
/// </term>
/// </item>
/// <item>
/// <term>LSA_LOOKUP_RETURN_LOCAL_NAMES</term>
/// <term>Always returns local SAM account names even for Internet provider identities.</term>
/// </item>
/// </list>
/// </param>
/// <param name="Count">
/// <para>Specifies the number of SIDs in the Sids array. This is also the number of entries returned in the Names array.</para>
/// </param>
/// <param name="Sids">
/// <para>
/// Pointer to an array of SID pointers to look up. The SIDs can be well-known SIDs, user, group, or local group account SIDs, or
/// domain SIDs.
/// </para>
/// </param>
/// <param name="ReferencedDomains">
/// <para>
/// Receives a pointer to a pointer to a LSA_REFERENCED_DOMAIN_LIST structure. The <c>Domains</c> member of this structure is an
/// array that contains an entry for each domain in which a SID was found. The entry for each domain contains the SID and flat name
/// of the domain. For Windows domains, the flat name is the NetBIOS name. For links with nonWindows domains, the flat name is the
/// identifying name of that domain, or it is <c>NULL</c>.
/// </para>
/// <para>
/// When you no longer need the information, pass the returned pointer to LsaFreeMemory. This memory must be freed even when the
/// function fails with the either of the error codes <c>STATUS_NONE_MAPPED</c> or <c>STATUS_SOME_NOT_MAPPED</c>
/// </para>
/// </param>
/// <param name="Names">
/// <para>
/// Receives a pointer to an array of LSA_TRANSLATED_NAME structures. Each entry in the Names array contains the name information for
/// the corresponding entry in the Sids array. For account SIDs, the <c>Name</c> member of each structure contains the isolated name
/// of the account. For domain SIDs, the <c>Name</c> member is not valid.
/// </para>
/// <para>
/// The <c>DomainIndex</c> member of each entry in the Names array is the index of an entry in the <c>Domains</c> array returned in
/// the ReferencedDomains parameter. The index identifies the <c>Domains</c> array for the domain in which the SID was found.
/// </para>
/// <para>
/// When you no longer need the information, pass the returned pointer to LsaFreeMemory. This memory must be freed even when the
/// function fails with the either of the error codes <c>STATUS_NONE_MAPPED</c> or <c>STATUS_SOME_NOT_MAPPED</c>
/// </para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is one of the following <c>NTSTATUS</c> values.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_SOME_NOT_MAPPED</term>
/// <term>Some of the SIDs could not be translated. This is an informational-level return value.</term>
/// </item>
/// <item>
/// <term>STATUS_SUCCESS</term>
/// <term>All of the SIDs were found and successfully translated.</term>
/// </item>
/// </list>
/// <para>
/// If the function fails, the return value is an <c>NTSTATUS</c> code, which can be one of the following values or one of the LSA
/// Policy Function Return Values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_NONE_MAPPED</term>
/// <term>None of the SIDs were translated. This is an error-level return value.</term>
/// </item>
/// </list>
/// <para>You can use the LsaNtStatusToWinError function to convert the <c>NTSTATUS</c> code to a Windows error code.</para>
/// </returns>
/// <remarks>
/// <para>
/// The flag LSA_LOOKUP_PREFER_INTERNET_NAMES should be used for internet accounts such as MicrosoftAccount and Azure Active
/// Directory accounts. When this flag is specified then SID-Name lookup returns the UPN of the account in the form
/// MicrosoftAccount\foo@outlook.com or AzureAD\foo@contoso.com. For Microsoft Accounts both the local SAM SID and the internet SID
/// result in the UPN being returned if this flag is specified. If LSA_LOOKUP_PREFER_INTERNET_NAMES is not specified then for AAD
/// accounts the NT4 style name of the form AzureAD\foo is returned. The NT4 style name is machine specific and its usage should be
/// carefully evaluated and if possible should be avoided. For MicrosoftAccounts if LSA_LOOKUP_PREFER_INTERNET_NAMES is not specified
/// then the local SID of the account translates to the local SAM name, and the internet SID translates to the UPN name.
/// </para>
/// <para>
/// For account SIDs, the string returned in the <c>Name</c> member is the isolated name of the account (for example, user_name). If
/// you need the composite name of the account (for example, Acctg\user_name), get the domain name from the ReferencedDomains buffer
/// and append a backslash and the isolated name.
/// </para>
/// <para>If the <c>LsaLookupSids2</c> function cannot translate a SID, the function uses the following algorithm:</para>
/// <list type="number">
/// <item>
/// <term>
/// If the SID's domain is known, the ReferencedDomains buffer contains an entry for the domain, and the string returned in the Names
/// parameter is a Unicode representation of the account's relative identifier (RID) from the SID.
/// </term>
/// </item>
/// <item>
/// <term>
/// If the SID's domain is not known, the string returned in the Names parameter is a Unicode representation of the entire SID, and
/// there is no domain record for this SID in the ReferencedDomains buffer.
/// </term>
/// </item>
/// </list>
/// <para>
/// In addition to looking up SIDs for local accounts, local domain accounts, and explicitly trusted domain accounts,
/// <c>LsaLookupSids2</c> can look up SIDs for any account in any domain in the Windows forest, including SIDs that appear only in
/// the <c>SIDhistory</c> field of an account in the forest. The <c>SIDhistory</c> field stores the former SIDs of an account that
/// has been moved from another domain. To perform these searches, the function queries the global catalog of the forest.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsalookupsids2 NTSTATUS LsaLookupSids2( LSA_HANDLE
// PolicyHandle, ULONG LookupOptions, ULONG Count, PSID *Sids, PLSA_REFERENCED_DOMAIN_LIST *ReferencedDomains, PLSA_TRANSLATED_NAME
// *Names ); public static extern NTSTATUS LsaLookupSids2(LSA_HANDLE PolicyHandle, uint LookupOptions, uint Count, ref PSID Sids, ref
// PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains, ref PLSA_TRANSLATED_NAME Names);
[PInvokeData("ntsecapi.h", MSDNShortId = "6B30D1FF-35DC-44E8-A765-36A5761EC0CE")]
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true, CharSet = CharSet.Unicode)]
public static extern NTStatus LsaLookupSids2(
LSA_HANDLE PolicyHandle,
LsaLookupSidsFlags LookupOptions,
uint Count,
[In, MarshalAs(UnmanagedType.LPArray)] PSID[] Sids,
out SafeLsaMemoryHandle ReferencedDomains,
out SafeLsaMemoryHandle Names);
/// <summary>
/// The <c>LsaNtStatusToWinError</c> function converts an NTSTATUS code returned by an LSA function to a Windows error code.
/// </summary>
/// <param name="Status">An NTSTATUS code returned by an LSA function call. This value will be converted to a System error code.</param>
/// <returns>
/// The return value is the Windows error code that corresponds to the Status parameter. If there is no corresponding Windows error
/// code, the return value is ERROR_MR_MID_NOT_FOUND.
/// </returns>
// https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-lsantstatustowinerror ULONG LsaNtStatusToWinError(
// NTSTATUS Status );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "fa91794c-c502-4b36-84cc-a8d77c8e9d9f")]
public static extern Win32Error LsaNtStatusToWinError(NTStatus Status);
/// <summary>[Undocumented] Opens an account.</summary>
/// <param name="PolicyHandle">The policy handle.</param>
/// <param name="AccountSid">The account sid.</param>
/// <param name="DesiredAccess">The desired access.</param>
/// <param name="AccountHandle">The account handle.</param>
/// <returns>NTSTATUS</returns>
[PInvokeData("ntlsa.h")]
[DllImport(Lib.AdvApi32, ExactSpelling = true)]
public static extern NTStatus LsaOpenAccount(LSA_HANDLE PolicyHandle, PSID AccountSid, LsaAccountAccessMask DesiredAccess, out SafeLSA_HANDLE AccountHandle);
/// <summary>
/// <para>The <c>LsaOpenPolicy</c> function opens a handle to the Policy object on a local or remote system.</para>
/// <para>You must run the process "As Administrator" so that the call doesn't fail with ERROR_ACCESS_DENIED.</para>
/// </summary>
/// <param name="SystemName">
/// <para>
/// A pointer to an LSA_UNICODE_STRING structure that contains the name of the target system. The name can have the form
/// "ComputerName" or "\ComputerName". If this parameter is <c>NULL</c>, the function opens the Policy object on the local system.
/// </para>
/// </param>
/// <param name="ObjectAttributes">
/// <para>
/// A pointer to an LSA_OBJECT_ATTRIBUTES structure that specifies the connection attributes. The structure members are not used;
/// initialize them to <c>NULL</c> or zero.
/// </para>
/// </param>
/// <param name="DesiredAccess">
/// <para>
/// An ACCESS_MASK that specifies the requested access rights. The function fails if the DACL of the target system does not allow the
/// caller the requested access. To determine the access rights that you need, see the documentation for the LSA functions with which
/// you want to use the policy handle.
/// </para>
/// </param>
/// <param name="PolicyHandle">
/// <para>A pointer to an LSA_HANDLE variable that receives a handle to the Policy object.</para>
/// <para>When you no longer need this handle, pass it to the LsaClose function to close it.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the function returns STATUS_SUCCESS.</para>
/// <para>If the function fails, it returns an <c>NTSTATUS</c> code. For more information, see LSA Policy Function Return Values.</para>
/// <para>You can use the LsaNtStatusToWinError function to convert the <c>NTSTATUS</c> code to a Windows error code.</para>
/// </returns>
/// <remarks>
/// <para>
/// To administer the local security policy of a local or remote system, you must call the <c>LsaOpenPolicy</c> function to establish
/// a session with that system's LSA subsystem. <c>LsaOpenPolicy</c> connects to the LSA of the target system and returns a handle to
/// the Policy object of that system. You can use this handle in subsequent LSA function calls to administer the local security
/// policy information of the target system.
/// </para>
/// <para>For an example that demonstrates calling this function see Opening a Policy Object Handle.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsaopenpolicy NTSTATUS LsaOpenPolicy(
// PLSA_UNICODE_STRING SystemName, PLSA_OBJECT_ATTRIBUTES ObjectAttributes, ACCESS_MASK DesiredAccess, PLSA_HANDLE PolicyHandle );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "361bc962-1e97-4606-a835-cbce37692c55")]
// public static extern NTSTATUS LsaOpenPolicy(PLSA_UNICODE_STRING SystemName, PLSA_OBJECT_ATTRIBUTES ObjectAttributes, ACCESS_MASK
// DesiredAccess, PLSA_HANDLE PolicyHandle);
public static extern NTStatus LsaOpenPolicy(
[In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringMarshaler))] string SystemName,
in LSA_OBJECT_ATTRIBUTES ObjectAttributes,
LsaPolicyRights DesiredAccess,
out SafeLSA_HANDLE PolicyHandle);
/// <summary>
/// The LsaOpenPolicy function opens a handle to the Policy object on a local or remote system. You must run the process "As
/// Administrator" so that the call doesn't fail with ERROR_ACCESS_DENIED.
/// </summary>
/// <param name="DesiredAccess">
/// An ACCESS_MASK that specifies the requested access rights. The function fails if the DACL of the target system does not allow the
/// caller the requested access. To determine the access rights that you need, see the documentation for the LSA functions with which
/// you want to use the policy handle.
/// </param>
/// <param name="SystemName">
/// Name of the target system. The name can have the form "ComputerName" or "\\ComputerName". If this parameter is NULL, the function
/// opens the Policy object on the local system.
/// </param>
/// <returns>A pointer to an LSA_HANDLE variable that receives a handle to the Policy object.</returns>
[PInvokeData("ntsecapi.h", MSDNShortId = "361bc962-1e97-4606-a835-cbce37692c55")]
public static SafeLSA_HANDLE LsaOpenPolicy(LsaPolicyRights DesiredAccess, string SystemName = null)
{
LsaNtStatusToWinError(LsaOpenPolicy(SystemName, LSA_OBJECT_ATTRIBUTES.Empty, DesiredAccess, out var handle)).ThrowIfFailed();
return handle;
}
/// <summary>
/// The <c>LsaOpenTrustedDomainByName</c> function opens the LSA policy handle of a remote trusted domain. You can pass this handle
/// into LSA function calls in order to set or query the LSA policy of the remote machine.
/// </summary>
/// <param name="PolicyHandle">
/// A handle to a Policy object. This is the policy handle of the local machine. For more information, see Opening a Policy Object Handle.
/// </param>
/// <param name="TrustedDomainName">
/// Name of the trusted domain. This name can be either the flat name, or the Domain Name System (DNS) domain name.
/// </param>
/// <param name="DesiredAccess">
/// An ACCESS_MASK structure that specifies the access permissions requested on the remote trusted domain object.
/// </param>
/// <param name="TrustedDomainHandle">
/// <para>
/// Pointer that receives the address of the LSA policy handle of the remote trusted domain. You can pass this handle into LSA
/// function calls in order to query and manage the LSA policy of the remote machine.
/// </para>
/// <para>When your application no longer needs this handle, it should call LsaClose to delete the handle.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is STATUS_SUCCESS.</para>
/// <para>
/// If the function fails, the return value is an NTSTATUS code, which can be one of the following values or one of the LSA Policy
/// Function Return Values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_ACCESS_DENIED</term>
/// <term>Caller does not have the appropriate access to complete the operation.</term>
/// </item>
/// <item>
/// <term>STATUS_OBJECT_NAME_NOT_FOUND</term>
/// <term>There is no Trusted Domain object in the target system's LSA Database having the specified name.</term>
/// </item>
/// </list>
/// <para>You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsaopentrusteddomainbyname NTSTATUS
// LsaOpenTrustedDomainByName( LSA_HANDLE PolicyHandle, PLSA_UNICODE_STRING TrustedDomainName, ACCESS_MASK DesiredAccess, PLSA_HANDLE
// TrustedDomainHandle );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "6c55f8b4-d8a2-48e3-8074-b3ca22ce487a")]
public static extern NTStatus LsaOpenTrustedDomainByName(LSA_HANDLE PolicyHandle, [In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringMarshaler))] string TrustedDomainName, ACCESS_MASK DesiredAccess, out SafeLSA_HANDLE TrustedDomainHandle);
/// <summary>The <c>LsaQueryDomainInformationPolicy</c> function retrieves domain information from the Policyobject.</summary>
/// <param name="PolicyHandle">A handle to the Policy object for the system.</param>
/// <param name="InformationClass">
/// <para>
/// POLICY_DOMAIN_INFORMATION_CLASS enumeration that specifies the information to be returned from the Policyobject. The following
/// table shows the possible values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>PolicyDomainEfsInformation</term>
/// <term>The information is for Encrypting File System.</term>
/// </item>
/// <item>
/// <term>PolicyDomainKerberosTicketInformation</term>
/// <term>The information is for a Kerberos ticket.</term>
/// </item>
/// </list>
/// </param>
/// <param name="Buffer">Pointer to a buffer that receives the requested information.</param>
/// <returns>
/// <para>If the function succeeds, the return value is STATUS_SUCCESS.</para>
/// <para>
/// If the function fails, the return value is an NTSTATUS code, which can be the following value or one of the LSA Policy Function
/// Return Values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code/value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_INTERNAL_DB_CORRUPTION</term>
/// <term>The policy database is corrupt. The returned policy information is not valid for the given class.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// The POLICY_VIEW_LOCAL_INFORMATION access type is required to retrieve domain information from the Policyobject. For more
/// information, see Policy Object Access Rights.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsaquerydomaininformationpolicy NTSTATUS
// LsaQueryDomainInformationPolicy( LSA_HANDLE PolicyHandle, POLICY_DOMAIN_INFORMATION_CLASS InformationClass, PVOID *Buffer );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "39a511d7-46fc-4d12-ba43-771f6db2a33b")]
public static extern NTStatus LsaQueryDomainInformationPolicy(LSA_HANDLE PolicyHandle, POLICY_DOMAIN_INFORMATION_CLASS InformationClass, out SafeLsaMemoryHandle Buffer);
/// <summary>
/// The <c>LsaQueryForestTrustInformation</c> function retrieves forest trust information for the specified Local Security Authority
/// TrustedDomain object.
/// </summary>
/// <param name="PolicyHandle">A handle to the Policy object for the system.</param>
/// <param name="TrustedDomainName">
/// Pointer to an LSA_UNICODE_STRING structure that contains the name of the TrustedDomain object for which to retrieve forest trust information.
/// </param>
/// <param name="ForestTrustInfo">
/// Pointer to an LSA_FOREST_TRUST_INFORMATION structure that returns the forest trust information for the TrustedDomain object
/// specified by the TrustedDomainName parameter.
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is STATUS_SUCCESS.</para>
/// <para>
/// If the function fails, the return value is an NTSTATUS code, which can be one of the following values or one of the LSA Policy
/// Function Return Values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code/value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_INVALID_DOMAIN_ROLE</term>
/// <term>The operation is legal only on the primary domain controller.</term>
/// </item>
/// <item>
/// <term>STATUS_INVALID_DOMAIN_STATE</term>
/// <term>The operation is legal only on domain controllers in the root domain.</term>
/// </item>
/// <item>
/// <term>STATUS_NO_SUCH_DOMAIN</term>
/// <term>The specified TrustedDomain object does not exist.</term>
/// </item>
/// <item>
/// <term>STATUS_NOT_FOUND</term>
/// <term>The specified TrustedDomain object does not contain forest trust information.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>Access to this function is protected by a securable object.</remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsaqueryforesttrustinformation NTSTATUS
// LsaQueryForestTrustInformation( LSA_HANDLE PolicyHandle, PLSA_UNICODE_STRING TrustedDomainName, PLSA_FOREST_TRUST_INFORMATION
// *ForestTrustInfo );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "38857f1f-e2c7-4ce5-a928-335bc3bd2176")]
public static extern NTStatus LsaQueryForestTrustInformation(LSA_HANDLE PolicyHandle, [In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringMarshaler))] string TrustedDomainName,
out SafeLsaMemoryHandle ForestTrustInfo);
/// <summary>The <c>LsaQueryInformationPolicy</c> function retrieves information about a Policy object.</summary>
/// <param name="PolicyHandle">
/// A handle to a Policy object. The required access rights for this handle depend on the value of the InformationClass parameter.
/// For more information, see Opening a Policy Object Handle.
/// </param>
/// <param name="InformationClass">
/// <para>
/// Specifies one of the following values from the POLICY_INFORMATION_CLASS enumeration type. The value indicates the type of
/// information to retrieve.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>PolicyAuditEventsInformation</term>
/// <term>
/// Retrieves the system's auditing rules. The handle passed in the PolicyHandle parameter must have the
/// POLICY_VIEW_AUDIT_INFORMATION access right. The Buffer parameter receives a pointer to a POLICY_AUDIT_EVENTS_INFO structure.
/// </term>
/// </item>
/// <item>
/// <term>PolicyPrimaryDomainInformation</term>
/// <term>
/// Retrieves the name and SID of the system's primary domain. The handle passed in the PolicyHandle parameter must have the
/// POLICY_VIEW_LOCAL_INFORMATION access right. The Buffer parameter receives a pointer to a POLICY_PRIMARY_DOMAIN_INFO structure.
/// </term>
/// </item>
/// <item>
/// <term>PolicyAccountDomainInformation</term>
/// <term>
/// Retrieves the name and SID of the system's account domain. The handle passed in the PolicyHandle parameter must have the
/// POLICY_VIEW_LOCAL_INFORMATION access right. The Buffer parameter receives a pointer to a POLICY_ACCOUNT_DOMAIN_INFO structure.
/// </term>
/// </item>
/// <item>
/// <term>PolicyLsaServerRoleInformation</term>
/// <term>
/// Retrieves the role of an LSA server. The handle passed in the PolicyHandle parameter must have the POLICY_VIEW_LOCAL_INFORMATION
/// access right. The Buffer parameter receives a pointer to a POLICY_LSA_SERVER_ROLE_INFO structure.
/// </term>
/// </item>
/// <item>
/// <term>PolicyModificationInformation</term>
/// <term>
/// Retrieves information about the creation time and last modification of the LSA database. The handle passed in the PolicyHandle
/// parameter must have the POLICY_VIEW_LOCAL_INFORMATION access right. The Buffer parameter receives a pointer to a
/// POLICY_MODIFICATION_INFO structure.
/// </term>
/// </item>
/// <item>
/// <term>PolicyDnsDomainInformation</term>
/// <term>
/// Retrieves the Domain Name System (DNS) information about the primary domain associated with the Policy object. The handle passed
/// in the PolicyHandle parameter must have the POLICY_VIEW_LOCAL_INFORMATION access right. The Buffer parameter receives a pointer
/// to a POLICY_DNS_DOMAIN_INFO structure.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="Buffer">
/// <para>
/// Pointer to a variable that receives a pointer to a structure containing the requested information. The type of structure depends
/// on the value of the InformationClass parameter.
/// </para>
/// <para>When you no longer need the information, pass the returned pointer to LsaFreeMemory.</para>
/// </param>
/// <returns>
/// <para>If the <c>LsaQueryInformationPolicy</c> function succeeds, the return value is STATUS_SUCCESS.</para>
/// <para>If the function fails, the return value is an NTSTATUS code. For more information, see LSA Policy Function Return Values.</para>
/// <para>You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code.</para>
/// </returns>
/// <remarks>For an example that demonstrates calling this function see Managing Policy Information.</remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsaqueryinformationpolicy NTSTATUS
// LsaQueryInformationPolicy( LSA_HANDLE PolicyHandle, POLICY_INFORMATION_CLASS InformationClass, PVOID *Buffer );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "2d543500-f639-4ef7-91f4-cdc5060dd567")]
public static extern NTStatus LsaQueryInformationPolicy(LSA_HANDLE PolicyHandle, POLICY_INFORMATION_CLASS InformationClass, out SafeLsaMemoryHandle Buffer);
/// <summary>The <c>LsaQueryInformationPolicy</c> function retrieves information about a Policy object.</summary>
/// <param name="PolicyHandle">
/// A handle to a Policy object. The required access rights for this handle depend on the value of the InformationClass parameter.
/// For more information, see Opening a Policy Object Handle.
2020-03-01 20:59:39 -05:00
/// </param>
/// <returns>
/// The structure containing the requested information.
/// </returns>
/// <remarks>For an example that demonstrates calling this function see Managing Policy Information.</remarks>
[PInvokeData("ntsecapi.h", MSDNShortId = "2d543500-f639-4ef7-91f4-cdc5060dd567")]
public static T LsaQueryInformationPolicy<T>(LSA_HANDLE PolicyHandle) where T : struct
{
if (!CorrespondingTypeAttribute.CanGet<T, POLICY_INFORMATION_CLASS>(out var ic))
throw new ArgumentException($"Type mismatch between {ic} and {typeof(T).Name}.");
LsaQueryInformationPolicy(PolicyHandle, ic, out var mem).ThrowIfFailed();
using (mem)
return mem.DangerousGetHandle().Convert<T>(uint.MaxValue, CharSet.Unicode);
}
/// <summary>
/// <para>The <c>LsaQueryTrustedDomainInfo</c> function retrieves information about a trusted domain.</para>
/// </summary>
/// <param name="PolicyHandle">
/// <para>
/// A handle to the Policy object of a domain controller that has a trust relationship with the domain identified by the
/// TrustedDomainSid parameter. The handle must have the POLICY_VIEW_LOCAL_INFORMATION access right. For more information, see
/// Opening a Policy Object Handle.
/// </para>
/// </param>
/// <param name="TrustedDomainSid">
/// <para>Pointer to the SID of the trusted domain to query.</para>
/// </param>
/// <param name="InformationClass">
/// <para>
/// Specifies one of the following values from the TRUSTED_INFORMATION_CLASS enumeration type. The value indicates the type of
/// information being requested.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>TrustedDomainNameInformation</term>
/// <term>Retrieves the name of the trusted domain. The Buffer parameter receives a pointer to a TRUSTED_DOMAIN_NAME_INFO structure.</term>
/// </item>
/// <item>
/// <term>TrustedPosixOffsetInformation</term>
/// <term>
/// Retrieves the value used to generate Posix user and group identifiers for the trusted domain. The Buffer parameter receives a
/// pointer to a TRUSTED_POSIX_OFFSET_INFO structure.
/// </term>
/// </item>
/// <item>
/// <term>TrustedPasswordInformation</term>
/// <term>
/// Retrieves the password for the trusted domain. The Buffer parameter receives a pointer to a TRUSTED_PASSWORD_INFO structure. The
/// handle passed in the PolicyHandle parameter must have the POLICY_GET_PRIVATE_INFORMATION access right.
/// </term>
/// </item>
/// <item>
/// <term>TrustedDomainInformationEx</term>
/// <term>
/// Retrieves extended information for the trusted domain. The Buffer parameter receives a pointer to a TRUSTED_DOMAIN_INFORMATION_EX structure.
/// </term>
/// </item>
/// <item>
/// <term>TrustedDomainInformationBasic</term>
/// <term>This value is not supported.</term>
/// </item>
/// <item>
/// <term>TrustedDomainFullInformation</term>
/// <term>
/// Retrieves complete information for the trusted domain. This information includes the Posix offset information, authentication
/// information, and the extended information returned for the TrustedDomainInformationEx value. The Buffer parameter receives a
/// pointer to a TRUSTED_DOMAIN_FULL_INFORMATION structure.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="Buffer">
/// <para>
/// A pointer to a buffer that receives a pointer to a structure that contains the requested information. The type of structure
/// depends on the value of the InformationClass parameter.
/// </para>
/// <para>When you have finished using the information, free the returned pointer by passing it to LsaFreeMemory.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the function returns STATUS_SUCCESS.</para>
/// <para>
/// If the function fails, it returns an <c>NTSTATUS</c> value that indicates the error. For more information, see LSA Policy
/// Function Return Values.
/// </para>
/// <para>You can use the LsaNtStatusToWinError function to convert the <c>NTSTATUS</c> value to a Windows error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsaquerytrusteddomaininfo NTSTATUS
// LsaQueryTrustedDomainInfo( LSA_HANDLE PolicyHandle, PSID TrustedDomainSid, TRUSTED_INFORMATION_CLASS InformationClass, PVOID
// *Buffer );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "62925515-a6f3-4b5f-bf97-edb968af19a3")]
public static extern NTStatus LsaQueryTrustedDomainInfo(LSA_HANDLE PolicyHandle, PSID TrustedDomainSid, TRUSTED_INFORMATION_CLASS InformationClass, out SafeLsaMemoryHandle Buffer);
/// <summary>The <c>LsaQueryTrustedDomainInfoByName</c> function returns information about a trusted domain.</summary>
/// <param name="PolicyHandle">
/// A handle to a Policy object. This handle must have the POLICY_VIEW_LOCAL_INFORMATION access right. For more information, see
/// Opening a Policy Object Handle.
/// </param>
/// <param name="TrustedDomainName">
/// String that contains the name of the trusted domain. This can either be the domain name or the flat name.
/// </param>
/// <param name="InformationClass">
/// <para>Specifies the type of information to retrieve. This parameter can be one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>TrustedDomainNameInformation</term>
/// <term>Name of the trusted domain.</term>
/// </item>
/// <item>
/// <term>TrustedPosixInformation</term>
/// <term>Posix offset of the trusted domain.</term>
/// </item>
/// <item>
/// <term>TrustedPasswordInformation</term>
/// <term>Returns the password on the outbound side of the trust.</term>
/// </item>
/// <item>
/// <term>TrustedDomainInformationBasic</term>
/// <term>This value is not supported.</term>
/// </item>
/// <item>
/// <term>TrustedDomainInformationEx</term>
/// <term>Extended trust information, including the basic information and DNS domain name, and attributes about the trust.</term>
/// </item>
/// <item>
/// <term>TrustedDomainFullInformation</term>
/// <term>Full information, including the Posix offset and the authentication information.</term>
/// </item>
/// </list>
/// </param>
/// <param name="Buffer">
/// <para>
/// Receives a pointer to the returned buffer that contains the requested information. The format and content of this buffer depend
/// on the information class. For example, if InformationClass is set to TrustedDomainInformationEx, Buffer receives a pointer to a
/// TRUSTED_DOMAIN_INFORMATION_EX structure. For more information, see TRUSTED_INFORMATION_CLASS.
/// </para>
/// <para>When you have finished using the buffer, free it by calling the LsaFreeMemory function.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the function returns STATUS_SUCCESS.</para>
/// <para>
/// If the function fails, it returns an <c>NTSTATUS</c> value, which can be one of the following values or one of the LSA Policy
/// Function Return Values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_ACCESS_DENIED</term>
/// <term>
/// Caller does not have the appropriate access to complete the operation. For a list of the required access types, see the
/// description of the InformationClass parameter.
/// </term>
/// </item>
/// <item>
/// <term>STATUS_INSUFFICIENT_ RESOURCES</term>
/// <term>Insufficient system resources, such as memory, to complete the call.</term>
/// </item>
/// </list>
/// <para>You can use the LsaNtStatusToWinError function to convert the <c>NTSTATUS</c> value to a Windows error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsaquerytrusteddomaininfobyname NTSTATUS
// LsaQueryTrustedDomainInfoByName( LSA_HANDLE PolicyHandle, PLSA_UNICODE_STRING TrustedDomainName, TRUSTED_INFORMATION_CLASS
// InformationClass, PVOID *Buffer );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "d33d6cee-bd8b-49f4-8e65-07cdc65bec7c")]
public static extern NTStatus LsaQueryTrustedDomainInfoByName(LSA_HANDLE PolicyHandle,
[In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringMarshaler))] string TrustedDomainName,
TRUSTED_INFORMATION_CLASS InformationClass, out SafeLsaMemoryHandle Buffer);
/// <summary>
/// <para>
/// The <c>LsaRemoveAccountRights</c> function removes one or more privileges from an account. You can specify the privileges to be
/// removed, or you can set a flag to remove all privileges. When you remove all privileges, the function deletes the account. If you
/// specify privileges not held by the account, the function ignores them.
/// </para>
/// </summary>
/// <param name="PolicyHandle">
/// <para>
/// A handle to a Policy object. The handle must have the POLICY_LOOKUP_NAMES access right. For more information, see Opening a
/// Policy Object Handle.
/// </para>
/// </param>
/// <param name="AccountSid">
/// <para>Pointer to the security identifier (SID) of the account from which the privileges are removed.</para>
/// </param>
/// <param name="AllRights">
/// <para>
/// If <c>TRUE</c>, the function removes all privileges and deletes the account. In this case, the function ignores the UserRights
/// parameter. If <c>FALSE</c>, the function removes the privileges specified by the UserRights parameter.
/// </para>
/// </param>
/// <param name="UserRights">
/// <para>
/// Pointer to an array of LSA_UNICODE_STRING structures. Each structure contains the name of a privilege to be removed from the
/// account. For a list of privilege names, see Privilege Constants.
/// </para>
/// </param>
/// <param name="CountOfRights">
/// <para>Specifies the number of elements in the UserRights array.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is STATUS_SUCCESS.</para>
/// <para>
/// If the function fails, the return value is an NTSTATUS code, which can be one of the following values or one of the LSA Policy
/// Function Return Values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_NO_SUCH_PRIVILEGE</term>
/// <term>One of the privilege names is not valid.</term>
/// </item>
/// <item>
/// <term>STATUS_INVALID_PARAMETER</term>
/// <term>Indicates the UserRights parameter was NULL and the AllRights parameter was FALSE.</term>
/// </item>
/// </list>
/// <para>You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsaremoveaccountrights NTSTATUS LsaRemoveAccountRights(
// LSA_HANDLE PolicyHandle, PSID AccountSid, BOOLEAN AllRights, PLSA_UNICODE_STRING UserRights, ULONG CountOfRights );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "ad250a01-7a24-4fae-975c-aa3e65731c82")]
// public static extern NTSTATUS LsaRemoveAccountRights(LSA_HANDLE PolicyHandle, PSID AccountSid, [MarshalAs(UnmanagedType.U1)] bool
// AllRights, PLSA_UNICODE_STRING UserRights, uint CountOfRights);
public static extern NTStatus LsaRemoveAccountRights( LSA_HANDLE PolicyHandle, PSID AccountSid, [MarshalAs(UnmanagedType.Bool)] bool AllRights,
[In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringArrayMarshaler))] string[] UserRights, uint CountOfRights);
/// <summary>
/// <para>
/// The <c>LsaRemoveAccountRights</c> function removes one or more privileges from an account. You can specify the privileges to be
/// removed, or you can set a flag to remove all privileges. When you remove all privileges, the function deletes the account. If you
/// specify privileges not held by the account, the function ignores them.
/// </para>
/// </summary>
/// <param name="PolicyHandle">
/// <para>
/// A handle to a Policy object. The handle must have the POLICY_LOOKUP_NAMES access right. For more information, see Opening a
/// Policy Object Handle.
/// </para>
/// </param>
/// <param name="AccountSid">
/// <para>Pointer to the security identifier (SID) of the account from which the privileges are removed.</para>
/// </param>
/// <param name="AllRights">
/// <para>
/// If <c>TRUE</c>, the function removes all privileges and deletes the account. In this case, the function ignores the UserRights
/// parameter. If <c>FALSE</c>, the function removes the privileges specified by the UserRights parameter.
/// </para>
/// </param>
/// <param name="UserRights">
/// <para>
/// Pointer to an array of LSA_UNICODE_STRING structures. Each structure contains the name of a privilege to be removed from the
/// account. For a list of privilege names, see Privilege Constants.
/// </para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is STATUS_SUCCESS.</para>
/// <para>
/// If the function fails, the return value is an NTSTATUS code, which can be one of the following values or one of the LSA Policy
/// Function Return Values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_NO_SUCH_PRIVILEGE</term>
/// <term>One of the privilege names is not valid.</term>
/// </item>
/// <item>
/// <term>STATUS_INVALID_PARAMETER</term>
/// <term>Indicates the UserRights parameter was NULL and the AllRights parameter was FALSE.</term>
/// </item>
/// </list>
/// <para>You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsaremoveaccountrights NTSTATUS LsaRemoveAccountRights(
// LSA_HANDLE PolicyHandle, PSID AccountSid, BOOLEAN AllRights, PLSA_UNICODE_STRING UserRights, ULONG CountOfRights );
[PInvokeData("ntsecapi.h", MSDNShortId = "ad250a01-7a24-4fae-975c-aa3e65731c82")]
// public static extern NTSTATUS LsaRemoveAccountRights(LSA_HANDLE PolicyHandle, PSID AccountSid, [MarshalAs(UnmanagedType.U1)] bool
// AllRights, PLSA_UNICODE_STRING UserRights, uint CountOfRights);
public static NTStatus LsaRemoveAccountRights(LSA_HANDLE PolicyHandle, PSID AccountSid, [MarshalAs(UnmanagedType.Bool)] bool AllRights,
[In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringArrayMarshaler))] params string[] UserRights) =>
LsaRemoveAccountRights(PolicyHandle, AccountSid, AllRights, UserRights, (uint)UserRights?.Length);
/// <summary>Do not use the LSA private data functions. Instead, use the CryptProtectData and CryptUnprotectData functions.</summary>
/// <param name="PolicyHandle">
/// A handle to a Policy object. The handle must have the POLICY_GET_PRIVATE_INFORMATION access right. For more information, see
/// Opening a Policy Object Handle.
/// </param>
/// <param name="KeyName">
/// <para>Pointer to an LSA_UNICODE_STRING structure that contains the name of the key under which the private data is stored.</para>
/// <para>To create a specialized object, add one of the following prefixes to the key name.</para>
/// <list type="table">
/// <listheader>
/// <term>Prefix</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>L$</term>
/// <term>For local objects.</term>
/// </item>
/// <item>
/// <term>G$</term>
/// <term>For global objects.</term>
/// </item>
/// <item>
/// <term>M$</term>
/// <term>For computer objects.</term>
/// </item>
/// </list>
/// <para>
/// If you are not creating one of these specialized types, you do not need to specify a key name prefix. For more information, see
/// Private Data Object.
/// </para>
/// </param>
/// <param name="PrivateData">
/// <para>Pointer to a variable that receives a pointer to an LSA_UNICODE_STRING structure that contains the private data.</para>
/// <para>When you no longer need the information, pass the returned pointer to LsaFreeMemory.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the function returns STATUS_SUCCESS.</para>
/// <para>
/// If the function fails, it returns an <c>NTSTATUS</c> value, which can be the following value or one of the LSA Policy Function
/// Return Values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_OBJECT_NAME_NOT_FOUND</term>
/// <term>No private data is stored under the name specified by the KeyName parameter.</term>
/// </item>
/// </list>
/// <para>You can use the LsaNtStatusToWinError function to convert the <c>NTSTATUS</c> value to a Windows error code.</para>
/// </returns>
/// <remarks>You must run this process "As Administrator" or the call fails with ERROR_ACCESS_DENIED.</remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsaretrieveprivatedata NTSTATUS LsaRetrievePrivateData(
// LSA_HANDLE PolicyHandle, PLSA_UNICODE_STRING KeyName, PLSA_UNICODE_STRING *PrivateData );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "005460db-0919-46eb-b057-37c5b6042243")]
public static extern NTStatus LsaRetrievePrivateData(LSA_HANDLE PolicyHandle, [In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringMarshaler))] string KeyName,
out SafeLsaMemoryHandle PrivateData);
/// <summary>The <c>LsaSetDomainInformationPolicy</c> function sets domain information to the Policyobject.</summary>
/// <param name="PolicyHandle">A handle to the Policy object for the system.</param>
/// <param name="InformationClass">
/// <para>
/// POLICY_DOMAIN_INFORMATION_CLASS enumeration that specifies the information to be set to the Policyobject. The following table
/// shows the possible values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>PolicyDomainEfsInformation</term>
/// <term>The information is for Encrypting File System.</term>
/// </item>
/// <item>
/// <term>PolicyDomainKerberosTicketInformation</term>
/// <term>The information is for a Kerberos ticket.</term>
/// </item>
/// </list>
/// </param>
/// <param name="Buffer">Pointer to a buffer that contains the information to set to the Policyobject.</param>
/// <returns>
/// <para>If the function succeeds, the return value is STATUS_SUCCESS.</para>
/// <para>
/// If the function fails, the return value is an NTSTATUS code, which can be the following value or one of the LSA Policy Function
/// Return Values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code/value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_INTERNAL_DB_CORRUPTION</term>
/// <term>The policy database is corrupt. The returned policy information is not valid for the given class.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// The POLICY_TRUST_ADMIN access type is required to set domain information to the Policyobject. For more information, see Policy
/// Object Access Rights.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsasetdomaininformationpolicy NTSTATUS
// LsaSetDomainInformationPolicy( LSA_HANDLE PolicyHandle, POLICY_DOMAIN_INFORMATION_CLASS InformationClass, PVOID Buffer );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "77af6fdc-a52e-476c-9de2-36ee48133a87")]
public static extern NTStatus LsaSetDomainInformationPolicy(LSA_HANDLE PolicyHandle, POLICY_DOMAIN_INFORMATION_CLASS InformationClass, IntPtr Buffer);
/// <summary>The <c>LsaSetDomainInformationPolicy</c> function sets domain information to the Policyobject.</summary>
/// <typeparam name="T">The type of the structure being passed as <paramref name="value"/>.</typeparam>
/// <param name="PolicyHandle">A handle to the Policy object for the system.</param>
/// <param name="value">The information to set to the Policyobject.</param>
/// <remarks>
/// The POLICY_TRUST_ADMIN access type is required to set domain information to the Policyobject. For more information, see Policy
/// Object Access Rights.
/// </remarks>
[PInvokeData("ntsecapi.h", MSDNShortId = "77af6fdc-a52e-476c-9de2-36ee48133a87")]
public static void LsaSetDomainInformationPolicy<T>(LSA_HANDLE PolicyHandle, in T value) where T : struct
{
if (!CorrespondingTypeAttribute.CanSet<T, POLICY_DOMAIN_INFORMATION_CLASS>(out var ic))
throw new ArgumentException($"Unable to use {typeof(T).Name} with this function.");
using var mem = SafeHGlobalHandle.CreateFromStructure(value);
LsaSetDomainInformationPolicy(PolicyHandle, ic, mem).ThrowIfFailed();
}
/// <summary>
/// <para>
/// The <c>LsaSetForestTrustInformation</c> function sets the forest trust information for a specified Local Security Authority
/// TrustedDomain object.
/// </para>
/// </summary>
/// <param name="PolicyHandle">
/// <para>A handle to the Policy object for the system.</para>
/// </param>
/// <param name="TrustedDomainName">
/// <para>
/// Pointer to an LSA_UNICODE_STRING structure that contains the name of the TrustedDomain object to which to set the forest trust
/// information specified by the ForestTrustInfo parameter.
/// </para>
/// </param>
/// <param name="ForestTrustInfo">
/// <para>
/// Pointer to an LSA_FOREST_TRUST_INFORMATION structure that contains the forest trust information to set to the TrustedDomain
/// object specified by the TrustedDomainName parameter.
/// </para>
/// </param>
/// <param name="CheckOnly">
/// <para>
/// Boolean value that specifies whether changes to the TrustedDomain object are persisted. If this value is <c>TRUE</c>, this
/// function will check for collisions with the specified parameters but will not set the forest trust information specified by the
/// ForestTrustInfo parameter to the <c>TrustedDomain</c> object specified by the TrustedDomainName parameter. If this value is
/// <c>FALSE</c>, the forest trust information will be set to the <c>TrustedDomain</c> object.
/// </para>
/// </param>
/// <param name="CollisionInfo">
/// <para>
/// Pointer to a pointer to an LSA_FOREST_TRUST_COLLISION_INFORMATION structure that returns information about any collisions that occurred.
/// </para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is STATUS_SUCCESS.</para>
/// <para>
/// If the function fails, the return value is an NTSTATUS code, which can be one of the following values or one of the LSA Policy
/// Function Return Values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code/value</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_INVALID_DOMAIN_STATE</term>
/// <term>The operation is legal only on domain controllers in the root domain.</term>
/// </item>
/// <item>
/// <term>STATUS_INVALID_DOMAIN_ROLE</term>
/// <term>The operation is legal only on the primary domain controller.</term>
/// </item>
/// </list>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsasetforesttrustinformation NTSTATUS
// LsaSetForestTrustInformation( LSA_HANDLE PolicyHandle, PLSA_UNICODE_STRING TrustedDomainName, PLSA_FOREST_TRUST_INFORMATION
// ForestTrustInfo, BOOLEAN CheckOnly, PLSA_FOREST_TRUST_COLLISION_INFORMATION *CollisionInfo );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "8b0f90ed-7dd4-4803-97c6-31d191b6d2b3")]
public static extern NTStatus LsaSetForestTrustInformation(LSA_HANDLE PolicyHandle, [In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringMarshaler))] string TrustedDomainName,
in LSA_FOREST_TRUST_INFORMATION ForestTrustInfo, [MarshalAs(UnmanagedType.U1)] bool CheckOnly, out SafeLsaMemoryHandle CollisionInfo);
/// <summary>The <c>LsaSetInformationPolicy</c> function modifies information in a Policy object.</summary>
/// <param name="PolicyHandle">
/// A handle to a Policy object. The required access rights for this handle depend on the value of the InformationClass parameter.
/// For more information, see Opening a Policy Object Handle.
/// </param>
/// <param name="InformationClass">
/// <para>
/// Specifies one of the following values from the POLICY_INFORMATION_CLASS enumeration type. The value indicates the type of
/// information to set.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>PolicyAuditEventsInformation</term>
/// <term>
/// Sets the system's auditing rules. The handle passed in the PolicyHandle parameter must have the POLICY_SET_AUDIT_REQUIREMENTS
/// access right. The Buffer parameter must be a pointer to a POLICY_AUDIT_EVENTS_INFO structure.
/// </term>
/// </item>
/// <item>
/// <term>PolicyPrimaryDomainInformation</term>
/// <term>
/// Sets the name and SID of the system's primary domain. The handle passed in the PolicyHandle parameter must have the
/// POLICY_TRUST_ADMIN access right. The Buffer parameter must be a pointer to a POLICY_PRIMARY_DOMAIN_INFO structure.
/// </term>
/// </item>
/// <item>
/// <term>PolicyAccountDomainInformation</term>
/// <term>
/// Sets the name and SID of the system's account domain. The handle passed in the PolicyHandle parameter must have the
/// POLICY_TRUST_ADMIN access right. The Buffer parameter must be a pointer to a POLICY_ACCOUNT_DOMAIN_INFO structure.
/// </term>
/// </item>
/// <item>
/// <term>PolicyDnsDomainInformation</term>
/// <term>
/// Sets Domain Name System (DNS) information about the primary domain associated with the Policy object. The handle passed in the
/// PolicyHandle parameter must have the POLICY_TRUST_ADMIN access right. The Buffer parameter must be a pointer to a
/// POLICY_DNS_DOMAIN_INFO structure.
/// </term>
/// </item>
/// <item>
/// <term>PolicyLsaServerRoleInformation</term>
/// <term>
/// Sets the role of an LSA server. The handle passed in the PolicyHandle parameter must have the POLICY_SERVER_ADMIN access right.
/// The Buffer parameter must be a pointer to a POLICY_LSA_SERVER_ROLE_INFO structure. Changing a server's role from primary to
/// backup has no effect (although the function returns STATUS_SUCCESS). Changing a server's role from backup to primary requires
/// extensive network operations and may be slow.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="Buffer">
/// Pointer to a structure containing the information to set. The type of structure depends on the value of the InformationClass parameter.
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is STATUS_SUCCESS.</para>
/// <para>If the function fails, the return value is an NTSTATUS code. For more information, see LSA Policy Function Return Values.</para>
/// <para>You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsasetinformationpolicy NTSTATUS
// LsaSetInformationPolicy( LSA_HANDLE PolicyHandle, POLICY_INFORMATION_CLASS InformationClass, PVOID Buffer );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "2aa3b09e-2cd9-4a09-bfd6-b37c97266dcb")]
public static extern NTStatus LsaSetInformationPolicy(LSA_HANDLE PolicyHandle, POLICY_INFORMATION_CLASS InformationClass, IntPtr Buffer);
/// <summary>
/// The <c>LsaSetInformationPolicy</c> function modifies information in a Policy object.
/// </summary>
/// <typeparam name="T">The type of the structure being passed as <paramref name="value"/>.</typeparam>
/// <param name="PolicyHandle">A handle to a Policy object. The required access rights for this handle depend on the value of the InformationClass parameter.
/// For more information, see Opening a Policy Object Handle.</param>
/// <param name="value">A structure containing the information to set.</param>
/// <exception cref="ArgumentException">Unable to use {typeof(T).Name} with this function.</exception>
[PInvokeData("ntsecapi.h", MSDNShortId = "2aa3b09e-2cd9-4a09-bfd6-b37c97266dcb")]
public static void LsaSetInformationPolicy<T>(LSA_HANDLE PolicyHandle, in T value) where T : struct
{
if (!CorrespondingTypeAttribute.CanSet<T, POLICY_INFORMATION_CLASS>(out var ic))
throw new ArgumentException($"Unable to use {typeof(T).Name} with this function.");
using var mem = SafeHGlobalHandle.CreateFromStructure(value);
LsaSetInformationPolicy(PolicyHandle, ic, mem).ThrowIfFailed();
}
/// <summary>Undocumented.</summary>
/// <param name="AccountHandle">The account handle.</param>
/// <param name="SystemAccess">The system access.</param>
/// <returns>
/// If the function succeeds, the return value is STATUS_SUCCESS. If the function fails, the return value is an NTSTATUS code, which
/// can be one of the following values or one of the LSA Policy Function Return Values.
/// </returns>
[PInvokeData("ntlsa.h")]
[DllImport(Lib.AdvApi32, ExactSpelling = true)]
public static extern NTStatus LsaSetSystemAccessAccount(LSA_HANDLE AccountHandle, int SystemAccess);
/// <summary>The <c>LsaSetTrustedDomainInfoByName</c> function sets values for a TrustedDomain object.</summary>
/// <param name="PolicyHandle">
/// A handle to a Policy object. The security descriptor of the trusted domain object determines whether the caller's changes are
/// accepted. For information about policy object handles, see Opening a Policy Object Handle.
/// </param>
/// <param name="TrustedDomainName">
/// Name of the trusted domain to set values for. This can either be the domain name or the flat name.
/// </param>
/// <param name="InformationClass">
/// <para>Specifies the type of information to set. Specify one of the following values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>TrustedPosixInformation</term>
/// <term>Posix offset of the trusted domain.</term>
/// </item>
/// <item>
/// <term>TrustedDomainInformationEx</term>
/// <term>Extended trust information, including the basic information and DNS domain name, and attributes about the trust.</term>
/// </item>
/// <item>
/// <term>TrustedDomainAuthInformation</term>
/// <term>
/// Authentication information for the trust, including authentication information for both the inbound and outbound side of the
/// trust (if it exists).
/// </term>
/// </item>
/// <item>
/// <term>TrustedDomainFullInformation</term>
/// <term>Full information, including the Posix offset and the authentication information.</term>
/// </item>
/// </list>
/// </param>
/// <param name="Buffer">
/// Pointer to a structure that contains the information to set. The type of structure depends on the value of the InformationClass parameter.
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is STATUS_SUCCESS.</para>
/// <para>
/// If the function fails, the return value is an NTSTATUS code. For more information, see the "LSA Policy Function Return Values"
/// section of Security Management Return Values.
/// </para>
/// <para>You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsasettrusteddomaininfobyname NTSTATUS
// LsaSetTrustedDomainInfoByName( LSA_HANDLE PolicyHandle, PLSA_UNICODE_STRING TrustedDomainName, TRUSTED_INFORMATION_CLASS
// InformationClass, PVOID Buffer );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "263e1025-1010-463d-8bc7-cdf916ce9872")]
public static extern NTStatus LsaSetTrustedDomainInfoByName(LSA_HANDLE PolicyHandle, [In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringMarshaler))] string TrustedDomainName,
TRUSTED_INFORMATION_CLASS InformationClass, IntPtr Buffer);
/// <summary>
/// <para>The <c>LsaSetTrustedDomainInformation</c> function modifies a Policy object's information about a trusted domain.</para>
/// </summary>
/// <param name="PolicyHandle">
/// <para>
/// A handle to the Policy object of a domain controller. The required user rights for this handle depend on the value of the
/// InformationClass parameter. For more information, see Opening a Policy Object Handle.
/// </para>
/// </param>
/// <param name="TrustedDomainSid">
/// <para>
/// Pointer to the SID of the trusted domain whose information is modified. If the InformationClass parameter is set to
/// TrustedDomainNameInformation, this parameter must point to the SID of the domain to add to the list of trusted domains.
/// </para>
/// </param>
/// <param name="InformationClass">
/// <para>
/// Specifies one of the following values from the TRUSTED_INFORMATION_CLASS enumeration type. The value indicates the type of
/// information being set.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>TrustedDomainNameInformation</term>
/// <term>
/// If the specified domain is not in the list of trusted domains, the LsaSetTrustedDomainInformation function adds it. The
/// TrustedDomainSid parameter must be the SID of the domain to add. The Buffer parameter must be a pointer to a
/// TRUSTED_DOMAIN_NAME_INFO structure containing the name of the domain to add. If the specified domain is already in the list of
/// trusted domains, the function fails.
/// </term>
/// </item>
/// <item>
/// <term>TrustedPosixOffsetInformation</term>
/// <term>
/// Sets the value used to generate Posix user and group identifiers. The Buffer parameter must be a pointer to a
/// TRUSTED_POSIX_OFFSET_INFO structure.
/// </term>
/// </item>
/// <item>
/// <term>TrustedPasswordInformation</term>
/// <term>
/// Sets the password for the trusted domain. The Buffer parameter must be a pointer to a TRUSTED_PASSWORD_INFO structure containing
/// the old and new passwords for the specified domain. The handle passed in the PolicyHandle parameter must have the
/// POLICY_CREATE_SECRET access right. The old password string can be NULL.
/// </term>
/// </item>
/// </list>
/// </param>
/// <param name="Buffer">
/// <para>
/// Pointer to a structure containing the information to set. The type of structure depends on the value of the InformationClass parameter.
/// </para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is STATUS_SUCCESS.</para>
/// <para>If the function fails, the return value is an NTSTATUS code. For more information, see LSA Policy Function Return Values.</para>
/// <para>You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsasettrusteddomaininformation NTSTATUS
// LsaSetTrustedDomainInformation( LSA_HANDLE PolicyHandle, PSID TrustedDomainSid, TRUSTED_INFORMATION_CLASS InformationClass, PVOID
// Buffer );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "a7b89ea7-af92-46ba-ac73-2fba1cc27680")]
public static extern NTStatus LsaSetTrustedDomainInformation(LSA_HANDLE PolicyHandle, PSID TrustedDomainSid, TRUSTED_INFORMATION_CLASS InformationClass, IntPtr Buffer);
/// <summary>Do not use the LSA private data functions. Instead, use the CryptProtectData and CryptUnprotectData functions.</summary>
/// <param name="PolicyHandle">
/// A handle to a Policy object. The handle must have the POLICY_CREATE_SECRET access right if this is the first time data is being
/// stored under the key specified by the KeyName parameter. For more information, see Opening a Policy Object Handle.
/// </param>
/// <param name="KeyName">
/// Pointer to an LSA_UNICODE_STRING structure containing the name of the key under which the private data is stored.
/// </param>
/// <param name="PrivateData">
/// <para>
/// Pointer to an LSA_UNICODE_STRING structure containing the private data to store. The function encrypts this data before storing it.
/// </para>
/// <para>
/// If this parameter is <c>NULL</c>, the function deletes any private data stored under the key and deletes the key. Subsequent
/// attempts to retrieve data from the key will return the STATUS_OBJECT_NAME_NOT_FOUND error code.
/// </para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is STATUS_SUCCESS.</para>
/// <para>If the function fails, the return value is an NTSTATUS code. For more information, see LSA Policy Function Return Values.</para>
/// <para>You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code.</para>
/// </returns>
/// <remarks>
/// <para>The <c>LsaStorePrivateData</c> function can be used by server applications to store client and machine passwords.</para>
/// <para>
/// As described in Private Data Object, private data objects include three specialized types: local, global, and machine.
/// Specialized objects are identified by a prefix in the key name: "L$" for local objects, "G$" for global objects, and "M$" for
/// machine objects. Local objects cannot be accessed remotely. Machine objects can be accessed only by the operating system.
/// </para>
/// <para>
/// In addition to these prefixes, the following values also indicate local or machine objects. These values are supported for
/// backward compatibility and should not be used when you create new local or machine objects. The key name of local private data
/// objects may also be "$machine.acc", "SAC", "SAI", "SANSC", or start with "RasDialParms" or "RasCredentials". The key name for
/// machine objects may also start with, "NL$" or "sc".
/// </para>
/// <para>
/// Private data objects which do not use any of the preceding key name conventions can be accessed remotely and are not replicated
/// to other domains.
/// </para>
/// <para>
/// The data stored by the <c>LsaStorePrivateData</c> function is not absolutely protected. However, the data is encrypted before
/// being stored, and the key has a DACL that allows only the creator and administrators to read the data.
/// </para>
/// <para>Use the LsaRetrievePrivateData function to retrieve the value stored by <c>LsaStorePrivateData</c>.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsastoreprivatedata NTSTATUS LsaStorePrivateData(
// LSA_HANDLE PolicyHandle, PLSA_UNICODE_STRING KeyName, PLSA_UNICODE_STRING PrivateData );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "95d6cf30-fd08-473e-b0b3-3f7ca5e85357")]
public static extern NTStatus LsaStorePrivateData(LSA_HANDLE PolicyHandle, [In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringMarshaler))] string KeyName,
[In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringMarshaler))] string PrivateData);
/// <summary>
/// <para>The <c>LsaClose</c> function closes a handle to a Policy or TrustedDomain object.</para>
/// </summary>
/// <param name="ObjectHandle">
/// <para>
/// A handle to a Policy object returned by the LsaOpenPolicy function or to a TrustedDomain object returned by the
/// LsaOpenTrustedDomainByName function. Following the completion of this call, the handle is no longer valid.
/// </para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is STATUS_SUCCESS.</para>
/// <para>If the function fails, the return value is an NTSTATUS code. For more information, see LSA Policy Function Return Values.</para>
/// <para>You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsaclose NTSTATUS LsaClose( LSA_HANDLE ObjectHandle );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "6283b1da-4ec3-48e1-91f6-321c6390befe")]
// public static extern NTSTATUS LsaClose(LSA_HANDLE ObjectHandle);
private static extern NTStatus LsaClose(LSA_HANDLE ObjectHandle);
/// <summary>
/// <para>
/// The <c>LsaFreeMemory</c> function frees memory allocated for an output buffer by an LSA function call. LSA functions that return
/// variable-length output buffers always allocate the buffer on behalf of the caller. The caller must free this memory by passing
/// the returned buffer pointer to <c>LsaFreeMemory</c> when the memory is no longer required.
/// </para>
/// </summary>
/// <param name="Buffer">
/// <para>
/// Pointer to memory buffer that was allocated by an LSA function call. If <c>LsaFreeMemory</c> is successful, this buffer is freed.
/// </para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is STATUS_SUCCESS.</para>
/// <para>
/// If the function fails, the return value is an NTSTATUS code, which can be the following value or one of the LSA Policy Function
/// Return Values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_UNSUCCESSFUL</term>
/// <term>Memory could not be freed because it was not allocated by an LSA function call.</term>
/// </item>
/// </list>
/// <para>You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code.</para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsafreememory NTSTATUS LsaFreeMemory( PVOID Buffer );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "6eb3d18f-c54c-4e51-8a4b-b7a3f930cfa9")]
// public static extern NTSTATUS LsaFreeMemory(IntPtr Buffer);
private static extern NTStatus LsaFreeMemory(IntPtr Buffer);
/// <summary>Provides a handle to an LSA enumeration.</summary>
[StructLayout(LayoutKind.Sequential)]
public struct LSA_ENUMERATION_HANDLE : IHandle
{
private readonly IntPtr handle;
/// <summary>Initializes a new instance of the <see cref="LSA_ENUMERATION_HANDLE"/> struct.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
public LSA_ENUMERATION_HANDLE(IntPtr preexistingHandle) => handle = preexistingHandle;
/// <summary>Returns an invalid handle by instantiating a <see cref="LSA_ENUMERATION_HANDLE"/> object with <see cref="IntPtr.Zero"/>.</summary>
public static LSA_ENUMERATION_HANDLE NULL => new LSA_ENUMERATION_HANDLE(IntPtr.Zero);
/// <summary>Gets a value indicating whether this instance is a null handle.</summary>
public bool IsNull => handle == IntPtr.Zero;
/// <summary>Performs an explicit conversion from <see cref="LSA_ENUMERATION_HANDLE"/> to <see cref="IntPtr"/>.</summary>
/// <param name="h">The handle.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator IntPtr(LSA_ENUMERATION_HANDLE h) => h.handle;
/// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="LSA_ENUMERATION_HANDLE"/>.</summary>
/// <param name="h">The pointer to a handle.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator LSA_ENUMERATION_HANDLE(IntPtr h) => new LSA_ENUMERATION_HANDLE(h);
/// <summary>Implements the operator !=.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !=(LSA_ENUMERATION_HANDLE h1, LSA_ENUMERATION_HANDLE h2) => !(h1 == h2);
/// <summary>Implements the operator ==.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator ==(LSA_ENUMERATION_HANDLE h1, LSA_ENUMERATION_HANDLE h2) => h1.Equals(h2);
/// <inheritdoc/>
public override bool Equals(object obj) => obj is LSA_ENUMERATION_HANDLE h ? handle == h.handle : false;
/// <inheritdoc/>
public override int GetHashCode() => handle.GetHashCode();
/// <inheritdoc/>
public IntPtr DangerousGetHandle() => handle;
}
/// <summary>Used with the LsaEnumerateAccountsWithUserRight function to return a pointer to a SID.</summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/ns-ntsecapi-_lsa_enumeration_information typedef struct
// _LSA_ENUMERATION_INFORMATION { PSID Sid; } LSA_ENUMERATION_INFORMATION, *PLSA_ENUMERATION_INFORMATION;
[PInvokeData("ntsecapi.h", MSDNShortId = "7577548f-3ceb-43a5-b447-6f66a09963fe")]
[StructLayout(LayoutKind.Sequential)]
public struct LSA_ENUMERATION_INFORMATION
{
/// <summary>Pointer to a SID.</summary>
public PSID Sid;
}
/// <summary>
/// The <c>LSA_FOREST_TRUST_BINARY_DATA</c> structure contains binary data used in Local Security Authority forest trust operations.
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/ns-ntsecapi-_lsa_forest_trust_binary_data typedef struct
// _LSA_FOREST_TRUST_BINARY_DATA { #if ... ULONG Length; #if ... PUCHAR Buffer; #else ULONG Length; #endif #else PUCHAR Buffer;
// #endif } LSA_FOREST_TRUST_BINARY_DATA, *PLSA_FOREST_TRUST_BINARY_DATA;
[PInvokeData("ntsecapi.h", MSDNShortId = "2ddcf54e-c30f-4146-8cb6-71fcdd42ae68")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct LSA_FOREST_TRUST_BINARY_DATA
{
/// <summary>The count of bytes in Buffer.</summary>
public uint Length;
/// <summary>The trust record. If the Length field has a value other than 0, this field MUST NOT be NULL.</summary>
public IntPtr Buffer;
}
/// <summary>
/// The <c>LSA_FOREST_TRUST_COLLISION_INFORMATION</c> structure contains information about Local Security Authority forest trust collisions.
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/ns-ntsecapi-lsa_forest_trust_collision_information typedef struct
// _LSA_FOREST_TRUST_COLLISION_INFORMATION { ULONG RecordCount; PLSA_FOREST_TRUST_COLLISION_RECORD *Entries; }
// LSA_FOREST_TRUST_COLLISION_INFORMATION, *PLSA_FOREST_TRUST_COLLISION_INFORMATION;
[PInvokeData("ntsecapi.h", MSDNShortId = "a4a3b040-c074-4756-a30f-408d8bca87ba")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct LSA_FOREST_TRUST_COLLISION_INFORMATION
{
/// <summary>Number of LSA_FOREST_TRUST_COLLISION_RECORD structures in the array pointed to by the <c>Entries</c> member.</summary>
public uint RecordCount;
/// <summary>
/// Pointer to a pointer to an array of LSA_FOREST_TRUST_COLLISION_RECORD structures, each of which contains information about a
/// single collision.
/// </summary>
public IntPtr Entries;
}
/// <summary>
/// The <c>LSA_FOREST_TRUST_COLLISION_RECORD</c> structure contains information about a Local Security Authority forest trust collision.
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/ns-ntsecapi-lsa_forest_trust_collision_record typedef struct
// _LSA_FOREST_TRUST_COLLISION_RECORD { ULONG Index; LSA_FOREST_TRUST_COLLISION_RECORD_TYPE Type; ULONG Flags; LSA_UNICODE_STRING
// Name; } LSA_FOREST_TRUST_COLLISION_RECORD, *PLSA_FOREST_TRUST_COLLISION_RECORD;
[PInvokeData("ntsecapi.h", MSDNShortId = "9f9d2f57-0e7f-4222-be35-e3f026b60e93")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct LSA_FOREST_TRUST_COLLISION_RECORD
{
/// <summary>
/// Index of this collision record in the array of <c>LSA_FOREST_TRUST_COLLISION_RECORD</c> structures pointed to by the
/// <c>Entries</c> member of the LSA_FOREST_TRUST_COLLISION_INFORMATION structure.
/// </summary>
public uint Index;
/// <summary>
/// <para>Type of the collision. The following table shows the possible values.</para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>CollisionTdo</term>
/// <term>Collision between TrustedDomain objects.</term>
/// </item>
/// <item>
/// <term>CollisionXref</term>
/// <term>Collision between cross-references.</term>
/// </item>
/// <item>
/// <term>CollisionOther</term>
/// <term>Collision that is not a collision between TrustedDomain objects or cross-references.</term>
/// </item>
/// </list>
/// </summary>
public LSA_FOREST_TRUST_COLLISION_RECORD_TYPE Type;
/// <summary>
/// <para>
/// Flags that provide more information about the collision. The following table lists the possible values for this member when
/// the <c>Type</c> member is CollisionTdo.
/// </para>
/// <para>LSA_TLN_DISABLED_NEW (0x00000001)</para>
/// <para>LSA_TLN_DISABLED_ADMIN (0x00000002)</para>
/// <para>LSA_TLN_DISABLED_CONFLICT (0x00000004)</para>
/// <para>The following table lists the possible values for this member when the <c>Type</c> member is CollisionXref.</para>
/// <para>LSA_SID_DISABLED_ADMIN (0x00000001)</para>
/// <para>LSA_SID_DISABLED_CONFLICT (0x00000002)</para>
/// <para>LSA_NB_DISABLED_ADMIN (0x00000004)</para>
/// <para>LSA_NB_DISABLED_CONFLICT (0x00000008)</para>
/// </summary>
public CollisionFlags Flags;
/// <summary>LSA_UNICODE_STRING structure that contains the name of the collision record.</summary>
public LSA_UNICODE_STRING Name;
}
/// <summary>The <c>LSA_FOREST_TRUST_DOMAIN_INFO</c> structure contains identifying information for a domain.</summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/ns-ntsecapi-_lsa_forest_trust_domain_info typedef struct
// _LSA_FOREST_TRUST_DOMAIN_INFO { #if ... PISID Sid; #else PSID Sid; #endif LSA_UNICODE_STRING DnsName; LSA_UNICODE_STRING
// NetbiosName; } LSA_FOREST_TRUST_DOMAIN_INFO, *PLSA_FOREST_TRUST_DOMAIN_INFO;
[PInvokeData("ntsecapi.h", MSDNShortId = "c0e06735-ca10-4bee-a45b-6db5b6666e31")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct LSA_FOREST_TRUST_DOMAIN_INFO
{
/// <summary>Domain SID for the trusted domain.</summary>
public PSID Sid;
/// <summary>LSA_UNICODE_STRING structure that contains the DNS name of the domain.</summary>
public LSA_UNICODE_STRING DnsName;
/// <summary>LSA_UNICODE_STRING structure that contains the NetBIOS name of the domain.</summary>
public LSA_UNICODE_STRING NetbiosName;
}
/// <summary>The <c>LSA_FOREST_TRUST_INFORMATION</c> structure contains Local Security Authority forest trust information.</summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/ns-ntsecapi-_lsa_forest_trust_information typedef struct
// _LSA_FOREST_TRUST_INFORMATION { #if ... ULONG RecordCount; #if ... PLSA_FOREST_TRUST_RECORD *Entries; #else ULONG RecordCount;
// #endif #else PLSA_FOREST_TRUST_RECORD *Entries; #endif } LSA_FOREST_TRUST_INFORMATION, *PLSA_FOREST_TRUST_INFORMATION;
[PInvokeData("ntsecapi.h", MSDNShortId = "9e456462-59a9-4f18-ba47-92fc2350889b")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct LSA_FOREST_TRUST_INFORMATION
{
/// <summary>A count of elements in the Entries array.</summary>
public uint RecordCount;
/// <summary>
/// An array of LSA_FOREST_TRUST_RECORD structures. If the RecordCount field has a value other than 0, this field MUST NOT be NULL.
/// </summary>
public IntPtr Entries;
}
/// <summary>
/// <para>The <c>LSA_FOREST_TRUST_RECORD</c> structure represents a Local Security Authority forest trust record.</para>
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/ns-ntsecapi-_lsa_forest_trust_record typedef struct
// _LSA_FOREST_TRUST_RECORD { ULONG Flags; LSA_FOREST_TRUST_RECORD_TYPE ForestTrustType; LARGE_INTEGER Time; #if ... union {
// LSA_UNICODE_STRING TopLevelName; LSA_FOREST_TRUST_DOMAIN_INFO DomainInfo; LSA_FOREST_TRUST_BINARY_DATA Data; } ForestTrustData;
// #else union { LSA_UNICODE_STRING TopLevelName; LSA_FOREST_TRUST_DOMAIN_INFO DomainInfo; LSA_FOREST_TRUST_BINARY_DATA Data; }
// ForestTrustData; #endif } LSA_FOREST_TRUST_RECORD, *PLSA_FOREST_TRUST_RECORD;
[PInvokeData("ntsecapi.h", MSDNShortId = "19b4ee56-664f-4f37-bfc9-129032ebeb22")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct LSA_FOREST_TRUST_RECORD
{
/// <summary>Flags that control the behavior of the operation.</summary>
public LSA_TLN Flags;
/// <summary>
/// <para>
/// LSA_FOREST_TRUST_RECORD_TYPE enumeration that indicates the type of the record. The following table shows the possible values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>ForestTrustTopLevelName</term>
/// <term>Record contains an included top-level name.</term>
/// </item>
/// <item>
/// <term>ForestTrustTopLevelNameEx</term>
/// <term>Record contains an excluded top-level name.</term>
/// </item>
/// <item>
/// <term>ForestTrustDomainInfo</term>
/// <term>Record contains an LSA_FOREST_TRUST_DOMAIN_INFO structure.</term>
/// </item>
/// <item>
/// <term>ForestTrustRecordTypeLast</term>
/// <term>Marks the end of an enumeration.</term>
/// </item>
/// </list>
/// </summary>
public LSA_FOREST_TRUST_RECORD_TYPE ForestTrustType;
/// <summary>Time stamp of the record.</summary>
public FILETIME Time;
/// <summary>
/// An LSA_UNICODE_STRING or LSA_FOREST_TRUST_DOMAIN_INFO structure, depending on the value ForestTrustType as specified in the
/// structure definition for LSA_FOREST_TRUST_RECORD.
/// </summary>
public ForestTrustDataUnion ForestTrustData;
/// <summary>
/// An LSA_UNICODE_STRING or LSA_FOREST_TRUST_DOMAIN_INFO structure, depending on the value ForestTrustType as specified in the
/// structure definition for LSA_FOREST_TRUST_RECORD.
/// </summary>
[StructLayout(LayoutKind.Explicit)]
public struct ForestTrustDataUnion
{
/// <summary>Top-level name. This member is used only if the ForestTrustType member is ForestTrustTopLevelName or ForestTrustTopLevelNameEx.</summary>
[FieldOffset(0)]
public LSA_UNICODE_STRING TopLevelName;
/// <summary>Domain information. This member is used only if the ForestTrustType member is ForestTrustDomainInfo.</summary>
[FieldOffset(0)]
public LSA_FOREST_TRUST_DOMAIN_INFO DomainInfo;
/// <summary>Binary data. This member is used for unrecognized entries after ForestTrustRecordTypeLast.</summary>
[FieldOffset(0)]
public LSA_FOREST_TRUST_BINARY_DATA Data;
}
}
/// <summary>Provides a handle to a LSA handle.</summary>
[StructLayout(LayoutKind.Sequential)]
public struct LSA_HANDLE : IHandle
{
private readonly IntPtr handle;
/// <summary>Initializes a new instance of the <see cref="LSA_HANDLE"/> struct.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
public LSA_HANDLE(IntPtr preexistingHandle) => handle = preexistingHandle;
/// <summary>Returns an invalid handle by instantiating a <see cref="LSA_HANDLE"/> object with <see cref="IntPtr.Zero"/>.</summary>
public static LSA_HANDLE NULL => new LSA_HANDLE(IntPtr.Zero);
/// <summary>Gets a value indicating whether this instance is a null handle.</summary>
public bool IsNull => handle == IntPtr.Zero;
/// <summary>Performs an explicit conversion from <see cref="LSA_HANDLE"/> to <see cref="IntPtr"/>.</summary>
/// <param name="h">The handle.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator IntPtr(LSA_HANDLE h) => h.handle;
/// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="LSA_HANDLE"/>.</summary>
/// <param name="h">The pointer to a handle.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator LSA_HANDLE(IntPtr h) => new LSA_HANDLE(h);
/// <summary>Implements the operator !=.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !=(LSA_HANDLE h1, LSA_HANDLE h2) => !(h1 == h2);
/// <summary>Implements the operator ==.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator ==(LSA_HANDLE h1, LSA_HANDLE h2) => h1.Equals(h2);
/// <inheritdoc/>
public override bool Equals(object obj) => obj is LSA_HANDLE h ? handle == h.handle : false;
/// <inheritdoc/>
public override int GetHashCode() => handle.GetHashCode();
/// <inheritdoc/>
public IntPtr DangerousGetHandle() => handle;
}
/// <summary>The <c>LSA_REFERENCED_DOMAIN_LIST</c> structure contains information about the domains referenced in a lookup operation.</summary>
// typedef struct _LSA_REFERENCED_DOMAIN_LIST { ULONG Entries; PLSA_TRUST_INFORMATION Domains;} LSA_REFERENCED_DOMAIN_LIST,
// *PLSA_REFERENCED_DOMAIN_LIST; https://msdn.microsoft.com/en-us/library/windows/desktop/ms721834(v=vs.85).aspx
[PInvokeData("Ntsecapi.h", MSDNShortId = "ms721834")]
[StructLayout(LayoutKind.Sequential)]
public struct LSA_REFERENCED_DOMAIN_LIST
{
/// <summary>Specifies the number of entries in the Domains array.</summary>
public uint Entries;
/// <summary>Pointer to an array of LSA_TRUST_INFORMATION structures that identify the referenced domains.</summary>
public IntPtr Domains;
/// <summary>Gets the list of <see cref="LSA_TRUST_INFORMATION"/> structures from the <see cref="Domains"/> field.</summary>
public IEnumerable<LSA_TRUST_INFORMATION> DomainList => Domains.ToIEnum<LSA_TRUST_INFORMATION>((int)Entries);
}
/// <summary>
/// The <c>LSA_TRANSLATED_SID</c> structure is used with the LsaLookupNames function to return information about the SID that
/// identifies an account.
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/ns-ntsecapi-_lsa_translated_sid typedef struct _LSA_TRANSLATED_SID {
// SID_NAME_USE Use; ULONG RelativeId; LONG DomainIndex; } LSA_TRANSLATED_SID, *PLSA_TRANSLATED_SID;
[PInvokeData("ntsecapi.h", MSDNShortId = "1fa8fb74-3e61-4982-aa6b-a0ffe979abd4")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct LSA_TRANSLATED_SID
{
/// <summary>
/// <para>A value from the SID_NAME_USE enumeration type that identifies the type of SID.</para>
/// <para>
/// If <c>Use</c> has one of the following values, one or both of the <c>RelativeId</c> or <c>DomainIndex</c> members of
/// <c>LSA_TRANSLATED_SID</c> is not valid. These members are valid if <c>Use</c> has any other value.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>SidTypeDomain</term>
/// <term>The DomainIndex member is valid, but the RelativeId member is not valid and must be ignored.</term>
/// </item>
/// <item>
/// <term>SidTypeInvalid</term>
/// <term>Both DomainIndex and RelativeId are not valid and must be ignored.</term>
/// </item>
/// <item>
/// <term>SidTypeUnknown</term>
/// <term>Both DomainIndex and RelativeId members are not valid and must be ignored.</term>
/// </item>
/// </list>
/// </summary>
public SID_NAME_USE Use;
/// <summary>
/// Specifies the relative identifier (RID) of the account's SID. The RID identifies the account relative to the domain
/// referenced by the <c>DomainIndex</c> member. The account's complete SID consists of the domain SID followed by the RID.
/// </summary>
public uint RelativeId;
/// <summary>
/// <para>
/// Specifies the zero-based index of an entry in the LSA_REFERENCED_DOMAIN_LIST structure returned by the LsaLookupNames
/// function. This entry contains the name and SID of the domain in which the account was found.
/// </para>
/// <para>If there is no corresponding domain for an account, this member contains a negative value.</para>
/// </summary>
public int DomainIndex;
}
/// <summary>
/// <para>The <c>LSA_TRUST_INFORMATION</c> structure identifies a domain.</para>
/// </summary>
/// <remarks>
/// <para>TRUSTED_DOMAIN_INFORMATION_BASIC is an alias for this structure.</para>
/// <para>
/// The TRUSTED_DOMAIN_INFORMATION_BASIC structure identifies a domain. This structure is used by the LsaQueryTrustedDomainInfo
/// function when its InformationClass parameter is set to <c>TrustedDomainInformationBasic</c>.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/lsalookup/ns-lsalookup-_lsa_trust_information typedef struct
// _LSA_TRUST_INFORMATION { LSA_UNICODE_STRING Name; PSID Sid; } LSA_TRUST_INFORMATION, *PLSA_TRUST_INFORMATION;
[PInvokeData("lsalookup.h", MSDNShortId = "2b5e6f79-b97a-4018-a45a-37c300c3dc0d")]
[StructLayout(LayoutKind.Sequential)]
public struct LSA_TRUST_INFORMATION
{
/// <summary>An LSA_UNICODE_STRING structure that contains the name of the domain.</summary>
public LSA_UNICODE_STRING Name;
/// <summary>Pointer to the SID of the domain.</summary>
public PSID Sid;
}
/// <summary>
/// The LSA_UNICODE_STRING structure is used by various Local Security Authority (LSA) functions to specify a Unicode string. Also an
/// example of unnecessary over-engineering and re-engineering.
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 8)]
[PInvokeData("Ntsecapi.h", MSDNShortId = "ms721841")]
public struct LSA_UNICODE_STRING
{
/// <summary>
/// Specifies the length, in bytes, of the string pointed to by the Buffer member, not including the terminating null character,
/// if any.
/// </summary>
public ushort length;
/// <summary>
/// Specifies the total size, in bytes, of the memory allocated for Buffer. Up to MaximumLength bytes can be written into the
/// buffer without trampling memory.
/// </summary>
public ushort MaximumLength;
/// <summary>
/// Pointer to a wide character string. Note that the strings returned by the various LSA functions might not be null-terminated.
/// </summary>
public StrPtrUni Buffer;
/* REMOVED TO AVOID MEMORY LEAK
*
/// <summary>Initializes a new instance of the <see cref="LSA_UNICODE_STRING"/> struct from a string.</summary>
/// <param name="s">The string value.</param>
/// <exception cref="System.ArgumentException">String exceeds 32Kb of data.</exception>
public LSA_UNICODE_STRING(string s)
{
if (s == null)
{
length = MaximumLength = 0;
Buffer = IntPtr.Zero;
}
else
{
var l = s.Length * UnicodeEncoding.CharSize;
// Unicode strings max. 32KB
if (l >= ushort.MaxValue)
throw new ArgumentException("String too long");
Buffer = s;
length = (ushort)l;
MaximumLength = (ushort)(l + UnicodeEncoding.CharSize);
}
}
*/
/// <summary>Gets the number of characters in the string.</summary>
public int Length => length / UnicodeEncoding.CharSize;
/// <summary>Returns a <see cref="string"/> that represents this instance.</summary>
/// <returns>A <see cref="string"/> that represents this instance.</returns>
public override string ToString() => StringHelper.GetString((IntPtr)Buffer, CharSet.Unicode, length) ?? string.Empty;
/// <summary>Performs an implicit conversion from <see cref="LSA_UNICODE_STRING"/> to <see cref="string"/>.</summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator string(LSA_UNICODE_STRING value) => value.ToString();
}
/// <summary>Smart wrapper for LSA_FOREST_TRUST_INFORMATION.</summary>
public class LsaForestTrustInformation : IDisposable
{
private SafeAllocatedMemoryHandle allocatedMemory;
/// <summary>A list of LsaForestTrustRecord entries that wrap LSA_FOREST_TRUST_RECORD.</summary>
/// <value>Returns a <see cref="List{LsaForestTrustRecord}"/> value.</value>
public List<LsaForestTrustRecord> Entries { get; } = new List<LsaForestTrustRecord>();
/// <summary>Creates a new instance from a memory pointer. This can fail if the memory is not allocated properly.</summary>
/// <param name="ptr">The memory pointer.</param>
/// <returns>A new instance of <see cref="LsaForestTrustInformation"/>.</returns>
public static LsaForestTrustInformation FromBuffer(IntPtr ptr)
{
var ret = new LsaForestTrustInformation();
var info = ptr.ToStructure<LSA_FOREST_TRUST_INFORMATION>();
foreach (var e in info.Entries.ToIEnum<LSA_FOREST_TRUST_RECORD>((int)info.RecordCount))
{
if (e.ForestTrustType == LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustRecordTypeLast) break;
LsaForestTrustRecord rec = null;
switch (e.ForestTrustType)
{
case LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustTopLevelName:
rec = new LsaForestTrustTopLevelName(e.ForestTrustData.TopLevelName, false);
break;
case LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustTopLevelNameEx:
rec = new LsaForestTrustTopLevelName(e.ForestTrustData.TopLevelName, true);
break;
case LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustDomainInfo:
rec = new LsaForestTrustDomainInfo { DnsName = e.ForestTrustData.DomainInfo.DnsName, NetbiosName = e.ForestTrustData.DomainInfo.NetbiosName, Sid = e.ForestTrustData.DomainInfo.Sid };
break;
default:
throw new ArgumentException("Unrecognized record type.", nameof(ptr));
}
rec.Flags = e.Flags;
rec.Time = e.Time.ToDateTime();
ret.Entries.Add(rec);
}
return ret;
}
/// <summary>
/// Returns an instance of <see cref="LSA_FOREST_TRUST_INFORMATION"/>. Warning! The memory allocated for the entries is tied to
/// this instance and will be disposed with it. Thus, if the returned structure is copied, the pointers within it may become
/// invalid if its scope outlives this instance's scope. Subsequent calls to this method will also invalidate the pointers within
/// any previous structures. In other words, just use this method to extract the structure for one time use and ensure this
/// instance does not go out of scope while the structure's being used.
/// </summary>
/// <returns>A <see cref="LSA_FOREST_TRUST_INFORMATION"/> instance matching the values of this instance.</returns>
public LSA_FOREST_TRUST_INFORMATION DangerousGetLSA_FOREST_TRUST_INFORMATION()
{
((IDisposable)this).Dispose();
allocatedMemory = SafeHGlobalHandle.CreateFromList(Entries.Select(e => e.Convert())); //.Concat(new[] { new LSA_FOREST_TRUST_RECORD { ForestTrustType = LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustRecordTypeLast } }));
return new LSA_FOREST_TRUST_INFORMATION { RecordCount = (uint)Entries.Count, Entries = allocatedMemory.DangerousGetHandle() };
}
/// <summary>Releases the unmanaged resources used by this object, and optionally releases the managed resources.</summary>
void IDisposable.Dispose() => allocatedMemory?.Dispose();
/// <summary>Represents a LSA_FOREST_TRUST_RECORD with the ForestTrustType value set to ForestTrustDomainInfo.</summary>
[DebuggerDisplay("DnsName:{DnsName}, NB:{NetbiosName}, Time:{Time:u}, Flg:{Flags}")]
public class LsaForestTrustDomainInfo : LsaForestTrustRecord
{
private SafeLSA_UNICODE_STRING dnsName = new SafeLSA_UNICODE_STRING(null);
private SafeLSA_UNICODE_STRING netbiosName = new SafeLSA_UNICODE_STRING(null);
/// <summary>The DNS name of the domain.</summary>
public string DnsName { get => dnsName; set => dnsName = value; }
/// <summary>The NetBIOS name of the domain.</summary>
public string NetbiosName { get => netbiosName; set => netbiosName = value; }
/// <summary>Domain SID for the trusted domain.</summary>
public SafePSID Sid { get; set; }
/// <summary>Converts this instance.</summary>
/// <returns>A <c>LSA_FOREST_TRUST_RECORD</c> instance.</returns>
protected internal override LSA_FOREST_TRUST_RECORD Convert()
{
var ret = base.Convert();
ret.ForestTrustType = LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustDomainInfo;
ret.ForestTrustData.DomainInfo.DnsName = dnsName;
ret.ForestTrustData.DomainInfo.NetbiosName = netbiosName;
ret.ForestTrustData.DomainInfo.Sid = Sid;
return ret;
}
}
/// <summary>Represents a LSA_FOREST_TRUST_RECORD.</summary>
public abstract class LsaForestTrustRecord
{
/// <summary>Flags that control the behavior of the operation.</summary>
public LSA_TLN Flags { get; set; }
/// <summary>Time stamp of the record.</summary>
public DateTime Time { get; set; }
/// <summary>Converts this instance.</summary>
/// <returns>A <c>LSA_FOREST_TRUST_RECORD</c> instance.</returns>
protected internal virtual LSA_FOREST_TRUST_RECORD Convert() =>
new LSA_FOREST_TRUST_RECORD { Flags = Flags, Time = Time.ToFileTimeStruct() };
}
/// <summary>
/// Represents a LSA_FOREST_TRUST_RECORD with the ForestTrustType value set to ForestTrustTopLevelNameEx if the
/// <see cref="Excluded"/> property is <see langword="true"/> and ForestTrustTopLevelName if the <see cref="Excluded"/> property
/// is <see langword="true"/>.
/// </summary>
[DebuggerDisplay("TopName:{TopLevelName}, Excl:{Excluded}, Time:{Time:u}, Flg:{Flags}")]
public class LsaForestTrustTopLevelName : LsaForestTrustRecord
{
private SafeLSA_UNICODE_STRING topLevelName = new SafeLSA_UNICODE_STRING(null);
/// <summary>Initializes a new instance of the <see cref="LsaForestTrustTopLevelName"/> class.</summary>
/// <param name="name">The name.</param>
/// <param name="exclude">if set to <c>true</c> [exclude].</param>
public LsaForestTrustTopLevelName(string name = null, bool exclude = false)
{
TopLevelName = name;
Excluded = exclude;
}
/// <summary>
/// Gets or sets a value indicating whether this <see cref="LsaForestTrustTopLevelName"/> contains an excluded top-level name..
/// </summary>
/// <value><c>true</c> if excluded; otherwise, <c>false</c> to include.</value>
public bool Excluded { get; set; }
/// <summary>Top-level name. This member is used only if the ForestTrustType member is ForestTrustTopLevelName or ForestTrustTopLevelNameEx.</summary>
public string TopLevelName { get => topLevelName; set => topLevelName = value; }
/// <summary>Converts this instance.</summary>
/// <returns>A <c>LSA_FOREST_TRUST_RECORD</c> instance.</returns>
protected internal override LSA_FOREST_TRUST_RECORD Convert()
{
var ret = base.Convert();
ret.ForestTrustType = Excluded ? LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustTopLevelNameEx : LSA_FOREST_TRUST_RECORD_TYPE.ForestTrustTopLevelName;
ret.ForestTrustData.TopLevelName = topLevelName;
return ret;
}
}
}
/// <summary>
/// Provides a <see cref="SafeHandle"/> to a LSA handle that releases a created LSA_HANDLE instance at disposal using LsaClose.
/// </summary>
public class SafeLSA_HANDLE : SafeHANDLE
{
/// <summary>Initializes a new instance of the <see cref="LSA_HANDLE"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeLSA_HANDLE(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="LSA_HANDLE"/> class.</summary>
private SafeLSA_HANDLE() : base() { }
/// <summary>Performs an implicit conversion from <see cref="SafeLSA_HANDLE"/> to <see cref="LSA_HANDLE"/>.</summary>
/// <param name="h">The safe handle instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator LSA_HANDLE(SafeLSA_HANDLE h) => h.handle;
/// <inheritdoc/>
protected override bool InternalReleaseHandle() => LsaClose(this).Succeeded;
}
/// <summary>Provides a <see cref="SafeHandle"/> for <see cref="LSA_UNICODE_STRING"/> that manages its own memory allocations.</summary>
public class SafeLSA_UNICODE_STRING : SafeHANDLE
{
/// <summary>Initializes a new instance of the <see cref="SafeLSA_UNICODE_STRING"/> class.</summary>
/// <param name="value">The value of the string to assign.</param>
public SafeLSA_UNICODE_STRING(string value) : base(IntPtr.Zero, true) => Buffer = value;
/// <summary>Initializes a new instance of the <see cref="SafeLSA_UNICODE_STRING"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeLSA_UNICODE_STRING(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeLSA_UNICODE_STRING"/> class.</summary>
private SafeLSA_UNICODE_STRING() : base() { }
/// <summary>The string value.</summary>
public string Buffer
{
get => LsaUnicodeStringMarshaler.MarshalPtr(handle);
set
{
Close();
SetHandle(LsaUnicodeStringMarshaler.MarshalValue(value));
}
}
/// <summary>
/// Specifies the length, in bytes, of the string pointed to by the Buffer member, not including the terminating null character,
/// if any.
/// </summary>
public short length => IsInvalid ? (short)0 : Marshal.ReadInt16(handle);
/// <summary>
/// Specifies the total size, in bytes, of the memory allocated for Buffer. Up to MaximumLength bytes can be written into the
/// buffer without trampling memory.
/// </summary>
public short MaximumLength => IsInvalid ? (short)0 : Marshal.ReadInt16(handle, 2);
/// <summary>Performs an implicit conversion from <see cref="SafeLSA_UNICODE_STRING"/> to <see cref="LSA_UNICODE_STRING"/>.</summary>
/// <param name="h">The safe handle instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator LSA_UNICODE_STRING(SafeLSA_UNICODE_STRING h) => h.handle.ToStructure<LSA_UNICODE_STRING>();
/// <summary>Performs an implicit conversion from <see cref="System.String"/> to <see cref="SafeLSA_UNICODE_STRING"/>.</summary>
/// <param name="val">The string value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator SafeLSA_UNICODE_STRING(string val) => new SafeLSA_UNICODE_STRING(val);
/// <summary>Performs an implicit conversion from <see cref="SafeLSA_UNICODE_STRING"/> to <see cref="System.String"/>.</summary>
/// <param name="h">The <see cref="SafeLSA_UNICODE_STRING"/> instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator string(SafeLSA_UNICODE_STRING h) => h.Buffer;
/// <inheritdoc/>
protected override bool InternalReleaseHandle()
{
if (handle != IntPtr.Zero)
Marshal.FreeCoTaskMem(handle);
return true;
}
}
/// <summary>
/// Provides a <see cref="SafeHandle"/> to a LSA memory handle that releases a created LsaMemoryHandle instance at disposal using <see cref="LsaFreeMemory"/>.
/// </summary>
public class SafeLsaMemoryHandle : SafeLsaMemoryHandleBase
{
/// <summary>Initializes a new instance of the <see cref="SafeLsaMemoryHandle"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeLsaMemoryHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeLsaMemoryHandle"/> class.</summary>
private SafeLsaMemoryHandle() : base() { }
/// <inheritdoc/>
protected override bool InternalReleaseHandle() => LsaFreeMemory(handle).Succeeded;
}
/// <summary>Base class for other LSA memory handles.</summary>
public abstract class SafeLsaMemoryHandleBase : SafeHANDLE
{
/// <summary>Initializes a new instance of the <see cref="SafeLsaMemoryHandleBase"/> class.</summary>
protected SafeLsaMemoryHandleBase() : base()
{
}
/// <summary>Initializes a new instance of the <see cref="SafeHANDLE"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
protected SafeLsaMemoryHandleBase(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) => SetHandle(preexistingHandle);
/// <summary>Gets or sets the size that will be passed to limit buffer overruns.</summary>
/// <value>The size.</value>
public SizeT Size { get; set; } = 0;
/// <summary>
/// Extracts an array of structures of <typeparamref name="T"/> containing <paramref name="count"/> items. <note type="note">This
/// call can cause memory exceptions if the pointer does not have sufficient allocated memory to retrieve all the structures.</note>
/// </summary>
/// <typeparam name="T">The type of the structures to retrieve.</typeparam>
/// <param name="count">The number of structures to retrieve.</param>
/// <param name="prefixBytes">The number of bytes to skip before reading the structures.</param>
/// <returns>An array of structures of <typeparamref name="T"/>.</returns>
public T[] ToArray<T>(int count, int prefixBytes = 0)
{
if (IsInvalid) return null;
return handle.ToArray<T>(count, prefixBytes, Size == 0 ? (SizeT)int.MaxValue : Size);
}
/// <summary>
/// Marshals data from this block of memory to a newly allocated managed object of the type specified by a generic type parameter.
/// </summary>
/// <typeparam name="T">The type of the object to which the data is to be copied. This must be a structure.</typeparam>
/// <returns>A managed object that contains the data that this <see cref="SafeMemoryHandleExt{T}"/> holds.</returns>
public T ToStructure<T>()
{
if (IsInvalid) return default;
return handle.ToStructure<T>(Size == 0 ? (SizeT)int.MaxValue : Size);
}
}
/// <summary>
/// A <see cref="SafeHandle"/> for values that must be freed using the <see cref="Secur32.LsaFreeReturnBuffer(IntPtr)"/> function.
/// </summary>
public sealed class SafeLsaReturnBufferHandle : SafeLsaMemoryHandleBase
{
/// <summary>Initializes a new instance of the <see cref="SafeLsaReturnBufferHandle"/> class.</summary>
/// <param name="preexistingHandle">The pointer to the memory allocated by an Lsa function.</param>
/// <param name="ownsHandle">if set to <c>true</c> release the memory when out of scope.</param>
public SafeLsaReturnBufferHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeLsaReturnBufferHandle"/> class.</summary>
private SafeLsaReturnBufferHandle() : base() { }
/// <inheritdoc/>
protected override bool InternalReleaseHandle() => Secur32.LsaFreeReturnBuffer(handle) == 0;
}
/// <summary>A custom marshaler for functions using LSA_UNICODE_STRING arrays so that managed string arrays can be used.</summary>
/// <seealso cref="ICustomMarshaler"/>
internal class LsaUnicodeStringArrayMarshaler : ICustomMarshaler
{
public static ICustomMarshaler GetInstance(string _) => new LsaUnicodeStringArrayMarshaler();
public void CleanUpManagedData(object ManagedObj)
{
}
public void CleanUpNativeData(IntPtr pNativeData)
{
if (pNativeData == IntPtr.Zero) return;
Marshal.FreeCoTaskMem(pNativeData);
}
public int GetNativeDataSize() => -1;
public IntPtr MarshalManagedToNative(object ManagedObj)
{
if (ManagedObj is string[] a)
{
var uma = Array.ConvertAll(a, p => new LSA_UNICODE_STRING { length = (ushort)StringHelper.GetByteCount(p, false, CharSet.Unicode) });
var strSz = uma.Sum(s => s.length + UnicodeEncoding.CharSize);
var result = Marshal.AllocCoTaskMem(LsaUnicodeStringMarshaler.ssz * a.Length + strSz);
var strPtr = result.Offset(LsaUnicodeStringMarshaler.ssz * a.Length);
for (var i = 0; i < uma.Length; i++)
{
uma[i].Buffer = strPtr;
StringHelper.Write(a[i], (IntPtr)uma[i].Buffer, out var byteCnt, true, CharSet.Unicode);
uma[i].MaximumLength = (ushort)byteCnt;
strPtr = strPtr.Offset(byteCnt);
Marshal.StructureToPtr(uma[i], result.Offset(i * LsaUnicodeStringMarshaler.ssz), false);
}
return result;
}
return IntPtr.Zero;
}
public object MarshalNativeToManaged(IntPtr pNativeData)
{
if (pNativeData == IntPtr.Zero) return null;
throw new InvalidOperationException(@"Unable to marshal LSA_UNICODE_STRING arrays from unmanaged to managed code.");
}
}
/// <summary>A custom marshaler for functions using LSA_UNICODE_STRING so that managed strings can be used.</summary>
/// <seealso cref="ICustomMarshaler"/>
internal class LsaUnicodeStringMarshaler : ICustomMarshaler
{
internal static readonly int ssz = Marshal.SizeOf(typeof(LSA_UNICODE_STRING));
public static ICustomMarshaler GetInstance(string _) => new LsaUnicodeStringMarshaler();
public void CleanUpManagedData(object ManagedObj)
{
}
public void CleanUpNativeData(IntPtr pNativeData)
{
if (pNativeData == IntPtr.Zero) return;
Marshal.FreeCoTaskMem(pNativeData);
}
public int GetNativeDataSize() => Marshal.SizeOf(typeof(LSA_UNICODE_STRING));
public IntPtr MarshalManagedToNative(object ManagedObj) => ManagedObj is string s ? MarshalValue(s) : IntPtr.Zero;
public object MarshalNativeToManaged(IntPtr pNativeData)
{
var s = MarshalPtr(pNativeData);
LsaFreeMemory(pNativeData);
return s;
}
internal static string MarshalPtr(IntPtr ptr) => ptr == IntPtr.Zero ? null : StringHelper.GetString(ptr.Offset(4), CharSet.Unicode, Marshal.ReadInt16(ptr));
internal static IntPtr MarshalValue(string value)
{
if (value is null) return IntPtr.Zero;
var lus = new LSA_UNICODE_STRING { length = (ushort)StringHelper.GetByteCount(value, false, CharSet.Unicode) };
lus.MaximumLength = (ushort)(lus.length + UnicodeEncoding.CharSize);
var mem = Marshal.AllocCoTaskMem(ssz + lus.MaximumLength);
lus.Buffer = mem.Offset(ssz);
mem.Write(lus);
StringHelper.Write(value, mem.Offset(ssz), out _, true, CharSet.Unicode, lus.MaximumLength);
return mem;
}
}
}
}