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

3402 lines
172 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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
{
/// <summary>The top-level name trust record is disabled during initial creation.</summary>
LSA_TLN_DISABLED_NEW = 0x00000001,
/// <summary>The top-level name trust record is disabled by the domain administrator.</summary>
LSA_TLN_DISABLED_ADMIN = 0x00000002,
/// <summary>The top-level name trust record is disabled due to a conflict.</summary>
LSA_TLN_DISABLED_CONFLICT = 0x00000004,
/// <summary>The domain information trust record is disabled by the domain administrator.</summary>
LSA_SID_DISABLED_ADMIN = 0x00000001,
/// <summary>The domain information trust record is disabled due to a conflict.</summary>
LSA_SID_DISABLED_CONFLICT = 0x00000002,
/// <summary>The domain information trust record is disabled by the domain administrator.</summary>
LSA_NB_DISABLED_ADMIN = 0x00000004,
/// <summary>The domain information trust record is disabled due to a conflict.</summary>
LSA_NB_DISABLED_CONFLICT = 0x00000008,
/// <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.
/// </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;
}
}
}
}