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 { /// Flags that provide more information about the collision. [PInvokeData("ntsecapi.h", MSDNShortId = "9f9d2f57-0e7f-4222-be35-e3f026b60e93")] [Flags] public enum CollisionFlags { /// The top-level name trust record is disabled during initial creation. LSA_TLN_DISABLED_NEW = 0x00000001, /// The top-level name trust record is disabled by the domain administrator. LSA_TLN_DISABLED_ADMIN = 0x00000002, /// The top-level name trust record is disabled due to a conflict. LSA_TLN_DISABLED_CONFLICT = 0x00000004, /// The domain information trust record is disabled by the domain administrator. LSA_SID_DISABLED_ADMIN = 0x00000001, /// The domain information trust record is disabled due to a conflict. LSA_SID_DISABLED_CONFLICT = 0x00000002, /// The domain information trust record is disabled by the domain administrator. LSA_NB_DISABLED_ADMIN = 0x00000004, /// The domain information trust record is disabled due to a conflict. LSA_NB_DISABLED_CONFLICT = 0x00000008, /// The domain information trust record is disabled. LSA_FTRECORD_DISABLED_REASONS = 0x0000FFFF, } /// /// /// The LSA_FOREST_TRUST_COLLISION_RECORD_TYPE enumeration defines the types of collision that can occur between Local /// Security Authority forest trust records. /// /// /// /// This enumeration is used by the LSA_FOREST_TRUST_COLLISION_RECORD structure. /// // 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 { /// Collision between TrustedDomain objects. This indicates a collision with a namespace element of another forest. CollisionTdo, /// Collision between cross-references. This indicates a collision with a domain in the same forest. CollisionXref, /// Collision that is not a collision between TrustedDomain objects or cross-references. CollisionOther, } /// /// The LSA_FOREST_TRUST_RECORD_TYPE enumeration defines the type of a Local Security Authority forest trust record. /// /// /// This enumeration is used by the LSA_FOREST_TRUST_RECORD structure. /// // 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 { /// Record contains an included top-level name. ForestTrustTopLevelName, /// Record contains an excluded top-level name. ForestTrustTopLevelNameEx, /// Record contains an LSA_FOREST_TRUST_DOMAIN_INFO structure. ForestTrustDomainInfo, /// Marks the end of an enumeration. ForestTrustRecordTypeLast, } /// Flags used by LSA_FOREST_TRUST_RECORD. [PInvokeData("ntsecapi.h", MSDNShortId = "19b4ee56-664f-4f37-bfc9-129032ebeb22")] [Flags] public enum LSA_TLN { /// /// The top-level name trust record is disabled during initial creation. This flag MUST be used only with /// forest trust record types of ForestTrustTopLevelName and ForestTrustTopLevelNameEx. /// LSA_TLN_DISABLED_NEW = 0x00000001, /// /// The top-level name trust record is disabled by the domain administrator. This flag MUST be used only with /// forest trust record types of ForestTrustTopLevelName and ForestTrustTopLevelNameEx. /// LSA_TLN_DISABLED_ADMIN = 0x00000002, /// /// The top-level name trust record is disabled due to a conflict. This flag MUST be used only with forest /// trust record types of ForestTrustTopLevelName and ForestTrustTopLevelNameEx. /// LSA_TLN_DISABLED_CONFLICT = 0x00000004, /// /// The domain information trust record is disabled by the domain administrator. This flag MUST be used only /// with a forest trust record type of ForestTrustDomainInfo. /// LSA_SID_DISABLED_ADMIN = 0x00000001, /// /// The domain information trust record is disabled due to a conflict. This flag MUST be used only with a /// forest trust record type of ForestTrustDomainInfo. /// LSA_SID_DISABLED_CONFLICT = 0x00000002, /// /// The domain information trust record is disabled by the domain administrator. This flag MUST be used only /// with a forest trust record type of ForestTrustDomainInfo. /// LSA_NB_DISABLED_ADMIN = 0x00000004, /// /// The domain information trust record is disabled due to a conflict. This flag MUST be used only with a /// forest trust record type of ForestTrustDomainInfo. /// LSA_NB_DISABLED_CONFLICT = 0x00000008, /// /// The domain information trust record is disabled. This set of flags is reserved; for current and future /// reasons, the trust is disabled. /// LSA_FTRECORD_DISABLED_REASONS = 0x0000FFFF, } /// The Policy object has the following object-specific access types: [Flags] [PInvokeData("ntsecapi.h")] public enum LsaPolicyRights : uint { /// /// 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. /// POLICY_VIEW_LOCAL_INFORMATION = 1, /// This access type is needed to view audit trail or audit requirements information. POLICY_VIEW_AUDIT_INFORMATION = 2, /// /// This access type is needed to view sensitive information, such as the names of accounts established for trusted domain relationships. /// POLICY_GET_PRIVATE_INFORMATION = 4, /// This access type is needed to change the account domain or primary domain information. POLICY_TRUST_ADMIN = 8, /// This access type is needed to create a new Account object. POLICY_CREATE_ACCOUNT = 0x10, /// This access type is needed to create a new Private Data object. POLICY_CREATE_SECRET = 0x20, /// Not yet supported. POLICY_CREATE_PRIVILEGE = 0x40, /// Set the default system quotas that are applied to user accounts. POLICY_SET_DEFAULT_QUOTA_LIMITS = 0x80, /// This access type is needed to update the auditing requirements of the system. POLICY_SET_AUDIT_REQUIREMENTS = 0x100, /// /// 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. /// POLICY_AUDIT_LOG_ADMIN = 0x200, /// /// 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. /// POLICY_SERVER_ADMIN = 0x400, /// This access type is needed to translate between names and SIDs. POLICY_LOOKUP_NAMES = 0x800, /// The policy notification POLICY_NOTIFICATION = 0x1000, /// All access 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, /// Read access POLICY_READ = ACCESS_MASK.STANDARD_RIGHTS_READ | POLICY_VIEW_AUDIT_INFORMATION | POLICY_GET_PRIVATE_INFORMATION, /// Write access 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, /// Execute access POLICY_EXECUTE = ACCESS_MASK.STANDARD_RIGHTS_EXECUTE | POLICY_VIEW_LOCAL_INFORMATION | POLICY_LOOKUP_NAMES, } /// /// The LsaAddAccountRights function assigns one or more privileges to an account. If the account does not exist, /// LsaAddAccountRights creates it. /// /// /// 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. /// /// Pointer to the SID of the account to which the function assigns privileges. /// /// 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. /// /// Specifies the number of elements in the UserRights array. /// /// If the function succeeds, the return value is STATUS_SUCCESS. /// /// 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. /// /// /// /// Return code /// Description /// /// /// STATUS_NO_SUCH_PRIVILEGE /// One of the privilege names is not valid. /// /// /// You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code. /// /// /// If you specify privileges already granted to the account, they are ignored. /// For an example that demonstrates calling this function, see Managing Account Permissions. /// // 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); /// /// The LsaAddAccountRights function assigns one or more privileges to an account. If the account does not exist, /// LsaAddAccountRights creates it. /// /// /// 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. /// /// Pointer to the SID of the account to which the function assigns privileges. /// /// 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. /// /// /// If the function succeeds, the return value is STATUS_SUCCESS. /// /// 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. /// /// /// /// Return code /// Description /// /// /// STATUS_NO_SUCH_PRIVILEGE /// One of the privilege names is not valid. /// /// /// You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code. /// /// /// If you specify privileges already granted to the account, they are ignored. /// For an example that demonstrates calling this function, see Managing Account Permissions. /// // 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); /// Undocumented function for creating an account. /// A handle to a Policy object. For more information, see Opening a Policy Object Handle. /// Pointer to the SID of the account for which to enumerate privileges. /// The desired access. /// The account handle. /// /// 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. /// [PInvokeData("ntlsa.h")] [DllImport(Lib.AdvApi32, ExactSpelling = true)] public static extern NTStatus LsaCreateAccount(LSA_HANDLE PolicyHandle, PSID AccountSid, LsaAccountAccessMask DesiredAccess, out SafeLSA_HANDLE AccountHandle); /// The LsaCreateTrustedDomainEx function establishes a new trusted domain by creating a new TrustedDomain object. /// /// A handle to a Policy object. For the object to be created, the caller must have permission to create children on the /// System container. For information about policy object handles, see Opening a Policy Object Handle. /// /// /// Pointer to a TRUSTED_DOMAIN_INFORMATION_EX structure that contains the name and SID of the new trusted domain. /// /// /// Pointer to a TRUSTED_DOMAIN_AUTH_INFORMATION structure that contains authentication information for the new trusted domain. /// /// An ACCESS_MASK structure that specifies the accesses to be granted for the new trusted domain. /// /// /// 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. /// /// When your application no longer needs this handle, it should call LsaClose to delete the handle. /// /// /// If the function succeeds, the function returns STATUS_SUCCESS. /// /// If the function fails, it returns an NTSTATUS code, which can be one of the following values or one of the LSA Policy /// Function Return Values. /// /// /// /// Return code /// Description /// /// /// STATUS_DIRECTORY_SERVICE_REQUIRED /// The target system (specified in the TrustedDomainInformation parameter) for the TrustedDomain object is not a domain controller. /// /// /// STATUS_INVALID_SID /// The specified SID is not valid. /// /// /// STATUS_UNSUCCESSFUL /// Unable to determine whether the target system is a domain controller. /// /// /// You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code. /// /// /// LsaCreateTrustedDomainEx does not check whether the specified domain name matches the specified SID or whether the SID and /// name represent an actual domain. /// // 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); /// /// The LsaDeleteTrustedDomain function removes a trusted domain from the list of trusted domains for a system and deletes the /// associated TrustedDomain object. /// /// A handle to a Policy object. For more information, see Opening a Policy Object Handle. /// Pointer to the SID of the trusted domain to be removed. /// /// 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. /// // 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); /// /// The LsaEnumerateAccountRights function enumerates the privileges assigned to an account. /// /// /// /// 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. /// /// /// /// Pointer to the SID of the account for which to enumerate privileges. /// /// /// /// 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 /// /// When you no longer need the information, pass the returned pointer to LsaFreeMemory. /// /// /// Pointer to a variable that receives the number of privileges in the UserRights array. /// /// /// If at least one account right is found, the function succeeds and returns STATUS_SUCCESS. /// /// 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. /// /// // 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); /// The LsaEnumerateAccountRights function enumerates the privileges assigned to an account. /// /// 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. /// /// Pointer to the SID of the account for which to enumerate privileges. /// /// An enumeration of strings containing the names of privileges held by the account. For a list of privilege names, see Privilege Constants. /// public static IEnumerable 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((int)cnt).Select(u => (string)u.ToString().Clone()).ToArray(); } /// /// /// 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. /// /// /// /// /// 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. /// /// /// /// /// 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. /// /// /// If this parameter is NULL, the function enumerates all accounts in the LSA database of the system associated with the /// Policy object. /// /// /// /// /// Pointer to a variable that receives a pointer to an array of LSA_ENUMERATION_INFORMATION structures. The Sid member of /// each structure is a pointer to the security identifier (SID) of an account that holds the specified privilege. /// /// When you no longer need the information, free the memory by passing the returned pointer to the LsaFreeMemory function. /// /// /// Pointer to a variable that receives the number of entries returned in the EnumerationBuffer parameter. /// /// /// If the function succeeds, the function returns STATUS_SUCCESS. /// /// If the function fails, it returns an NTSTATUS code, which can be one of the following values or one of the LSA Policy /// Function Return Values. /// /// /// /// Value /// Description /// /// /// STATUS_NO_SUCH_PRIVILEGE /// The privilege string specified was not a valid privilege. /// /// /// STATUS_NO_MORE_ENTRIES /// There were no accounts with the specified privilege. /// /// /// You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code. /// // 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); /// /// 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. /// /// /// 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. /// /// /// A string that specifies the name of a privilege. For a list of privileges, see Privilege Constants and Account Rights Constants. /// /// If this parameter is NULL, the function enumerates all accounts in the LSA database of the system associated with the Policy object. /// /// /// An enumeration of security identifiers (SID) of accounts that holds the specified privilege. public static IEnumerable 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(cnt).Select(u => u.Sid).ToArray(); } /// /// /// The LsaEnumerateTrustedDomains function retrieves the names and SIDs of domains trusted to authenticate logon credentials. /// LsaEnumerateTrustedDomains 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, LsaEnumerateTrustedDomains can only be used /// if one or more of the following is true: /// /// /// /// The calling system is running Windows NT 4.0 or an earlier version of Windows NT. /// /// /// /// The target system (specified using the PolicyHandle parameter), is a domain controller running Windows NT 4.0 or an earlier version. /// /// /// /// /// 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. /// /// /// /// /// /// 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. /// /// /// Pointer to an enumeration handle that enables you to make multiple calls to enumerate all the trusted domains. On the first call /// to LsaEnumerateTrustedDomains, EnumerationContext must point to a variable that has been initialized to zero. On /// subsequent calls to LsaEnumerateTrustedDomains, EnumerationContext must point to the enumeration handle returned by the /// previous call. /// /// /// /// Receives a pointer to an array of LSA_TRUST_INFORMATION structures that contain the names and SIDs of one or more trusted domains. /// /// When you no longer need the information, pass the returned pointer to LsaFreeMemory. /// /// /// 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. /// /// Pointer to a variable that receives the number of elements returned in the Buffer parameter. /// /// If the function is successful, the return value is one of the following NTSTATUS values. /// /// /// Value /// Description /// /// /// STATUS_SUCCESS /// The enumeration has been successfully completed. /// /// /// STATUS_MORE_ENTRIES /// /// The call was successful, but there are more trusted domains to be enumerated. Call LsaEnumerateTrustedDomains again, passing the /// value returned in the EnumerationContext parameter. /// /// /// /// STATUS_NO_MORE_ENTRIES /// There are no more trusted domains to enumerate. /// /// /// 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. /// /// /// /// For domains with domain controllers running only Windows NT 4.0 or earlier versions of Windows NT, /// LsaEnumerateTrustedDomains 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. /// /// /// 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, LsaEnumerateTrustedDomains returns only directly trusted domains. /// /// /// 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, LsaEnumerateTrustedDomains returns both directly trusted and indirectly /// trusted domains. /// /// /// Retrieving all trust information may require more than a single LsaEnumerateTrustedDomains 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 LsaEnumerateTrustedDomains 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. /// /// // 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); /// /// /// The LsaEnumerateTrustedDomains function retrieves the names and SIDs of domains trusted to authenticate logon credentials. /// LsaEnumerateTrustedDomains 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, LsaEnumerateTrustedDomains can only be used /// if one or more of the following is true: /// /// /// /// The calling system is running Windows NT 4.0 or an earlier version of Windows NT. /// /// /// /// The target system (specified using the PolicyHandle parameter), is a domain controller running Windows NT 4.0 or an earlier version. /// /// /// /// /// 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. /// /// /// /// /// /// 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. /// /// An enumeration of LSA_TRUST_INFORMATION structures that contain the names and SIDs of one or more trusted domains. [PInvokeData("ntsecapi.h", MSDNShortId = "5c371d5a-26cf-4a99-a8e1-006b6b3cc91f")] public static IEnumerable 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((int)count)) yield return i; } ret.ThrowIfFailed(); } /// /// The LsaEnumerateTrustedDomainsEx function returns information about the domains trusted by the local system. /// LsaEnumerateTrustedDomainsEx returns information only on direct trusts. DsEnumerateDomainTrusts is recommended for more /// complete trust enumeration purposes. /// /// /// A handle to a Policy object. This call requires POLICY_VIEW_LOCAL_INFORMATION access to the Policy object. For more /// information, see Opening a Policy Object Handle. /// /// /// A pointer to an LSA_ENUMERATION_HANDLE that you can use to make multiple calls to LsaEnumerateTrustedDomainsEx to retrieve /// all of the trusted domain information. For more information, see Remarks. /// /// /// /// Pointer to a buffer that receives a list of TRUSTED_DOMAIN_INFORMATION_EX structures that contain information about the /// enumerated trusted domains. /// /// Your application should free this buffer when it is no longer needed by calling LsaFreeMemory. /// /// /// 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. /// /// Pointer to a LONG that receives the number of trusted domain objects returned. /// /// If the function succeeds, the function returns STATUS_SUCCESS. /// /// If the function fails, it returns an NTSTATUS code, which can be one of the following values or one of the LSA Policy /// Function Return Values. /// /// /// /// Value /// Description /// /// /// STATUS_ACCESS_DENIED /// Caller does not have the appropriate access to complete the operation. /// /// /// STATUS_NO_MORE_ENTRIES /// /// There are no more entries. This warning is returned if no objects have been enumerated because the EnumerationContext value is /// too high. /// /// /// /// You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code. /// /// /// Retrieving all trust information may require more than a single LsaEnumerateTrustedDomainsEx call. /// To use the EnumerationContext parameter to make multiple calls /// /// /// Set the variable pointed to by EnumerationContext to zero. /// /// /// /// If LsaEnumerateTrustedDomainsEx 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. /// /// /// // 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); /// [Undocumented] Gets system access for an account. /// The account handle. /// The system access. /// If the function succeeds, the function returns one of the following NTSTATUS values. [PInvokeData("ntlsa.h")] [DllImport(Lib.AdvApi32, ExactSpelling = true)] public static extern NTStatus LsaGetSystemAccessAccount(LSA_HANDLE AccountHandle, out int SystemAccess); /// /// /// The LsaLookupNames function retrieves the security identifiers (SIDs) that correspond to an array of user, group, or local /// group names. /// /// /// The LsaLookupNames function is superseded by the LsaLookupNames2 function. Applications should use the /// LsaLookupNames2 function to ensure future compatibility. /// /// The LsaLookupNames function can also retrieve computer accounts. /// /// /// 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. /// /// /// Specifies the number of names in the Names array. This is also the number of entries returned in the Sids array. /// /// /// /// 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. /// /// For more information about the format of the name strings, see Remarks. /// /// /// /// Receives a pointer to an LSA_REFERENCED_DOMAIN_LIST structure. The Domains member of this structure is an array that /// contains an entry for each domain in which a name was found. The DomainIndex member of each entry in the Sids array is the /// index of the Domains array entry for the domain in which the name was found. /// /// /// 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 STATUS_NONE_MAPPED or STATUS_SOME_NOT_MAPPED /// /// /// /// /// 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. /// /// /// 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 STATUS_NONE_MAPPED or STATUS_SOME_NOT_MAPPED /// /// /// /// If the function succeeds, the function returns one of the following NTSTATUS values. /// /// /// Value /// Description /// /// /// STATUS_SOME_NOT_MAPPED /// Some of the names could not be translated. This is an informational-level return value. /// /// /// STATUS_SUCCESS /// All of the names were found and successfully translated. /// /// /// /// If the function fails, the return value is the following NTSTATUS value or one of the LSA Policy Function Return Values. /// /// /// /// Value /// Description /// /// /// STATUS_NONE_MAPPED /// None of the names were translated. /// /// /// Use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code. /// /// /// /// 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). /// /// /// Translation of isolated names introduces the possibility of name collisions because the same name may be used in multiple /// domains. The LsaLookupNames function uses the following algorithm to translate isolated names /// /// To translate isolated names /// /// /// /// If the name is a well-known name, such as Local or Interactive, the function returns the corresponding well-known security /// identifier (SID). /// /// /// /// If the name is the name of the built-in domain, the function returns the SID of that domain. /// /// /// If the name is the name of the account domain, the function returns the SID of that domain. /// /// /// If the name is the name of the primary domain, the function returns the SID of that domain. /// /// /// If the name is one of the names of the trusted domain, the function returns the SID of that domain. /// /// /// If the name is a user, group, or local group account in the built-in domain, the function returns the SID of that account. /// /// /// /// 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. /// /// /// /// If the name is a user, group, or a local group in the primary domain, the function returns the SID of that account. /// /// /// After looking in the primary domain, the primary domain looks in each of its trusted domains. /// /// /// Otherwise, the name is not translated. /// /// /// /// In addition to looking up local accounts, local domain accounts, and explicitly trusted domain accounts, LsaLookupNames /// can look up the name of any account in any domain in the Windows forest. /// /// Examples /// For an example that calls this function, see Translating Between Names and SIDs. /// // 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); /// /// /// The LsaLookupNames2 function retrieves the security identifiers (SIDs) for specified account names. LsaLookupNames2 /// can look up the SID for any account in any domain in a Windows forest. /// /// /// The LsaLookupNames function is superseded by the LsaLookupNames2 function. Applications should use the /// LsaLookupNames2 function to ensure future compatibility. /// /// /// This function differs from the LsaLookupNames function in that LsaLookupNames2 returns each SID as a single element, while /// LsaLookupNames divides each SID into an RID/domain pair. /// /// /// /// /// 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. /// /// /// /// Values that control the behavior of this function. The following value is currently defined. /// /// /// Value /// Meaning /// /// /// LSA_LOOKUP_ISOLATED_AS_LOCAL 0x80000000 /// /// 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. /// /// /// /// /// /// Specifies the number of names in the Names array. This is also the number of entries returned in the Sids array. /// /// /// /// 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. /// /// For more information about the format of the name strings, see Remarks. /// /// /// /// Receives a pointer to an LSA_REFERENCED_DOMAIN_LIST structure. The Domains member of this structure is an array that /// contains an entry for each domain in which a name was found. The DomainIndex member of each entry in the Sids array is the /// index of the Domains array entry for the domain in which the name was found. /// /// /// 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 STATUS_NONE_MAPPED or STATUS_SOME_NOT_MAPPED /// /// /// /// /// 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. /// /// /// 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 STATUS_NONE_MAPPED or STATUS_SOME_NOT_MAPPED /// /// /// /// If the function succeeds, the function returns one of the following NTSTATUS values. /// /// /// Value /// Description /// /// /// STATUS_SOME_NOT_MAPPED /// Some of the names could not be translated. This is an informational-level return value. /// /// /// STATUS_SUCCESS /// All of the names were found and successfully translated. /// /// /// /// If the function fails, the return value is the following NTSTATUS value or one of the LSA Policy Function Return Values. /// /// /// /// Value /// Description /// /// /// STATUS_NONE_MAPPED /// None of the names were translated. /// /// /// Use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code. /// /// /// /// Use fully qualified account names (for example, DomainName<i>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<i>UserName) and user principal names (UPN) (for example, Someone@Example.com). /// /// /// Translation of isolated names introduces the possibility of name collisions because the same name may be used in multiple /// domains. The LsaLookupNames2 function uses the following algorithm to translate isolated names. /// /// To translate isolated names /// /// /// /// If the name is a well-known name, such as Local or Interactive, the function returns the corresponding well-known security /// identifier (SID). /// /// /// /// If the name is the name of the built-in domain, the function returns the SID of that domain. /// /// /// If the name is the name of the account domain, the function returns the SID of that domain. /// /// /// If the name is the name of the primary domain, the function returns the SID of that domain. /// /// /// If the name is one of the names of the trusted domain, the function returns the SID of that domain. /// /// /// If the name is a user, group, or local group account in the built-in domain, the function returns the SID of that account. /// /// /// /// 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. /// /// /// /// If the name is a user, group, or a local group in the primary domain, the function returns the SID of that account. /// /// /// After looking in the primary domain, the function looks in each of the primary domain's trusted domains. /// /// /// Otherwise, the name is not translated. /// /// /// // 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); /// /// /// [ LsaLookupSids 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.] /// /// /// The LsaLookupSids function looks up the names that correspond to an array of security identifiers (SIDs). If /// LsaLookupSids cannot find a name that corresponds to a SID, the function returns the SID in character form. /// /// /// /// 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. /// /// /// Specifies the number of SIDs in the Sids array. This is also the number of entries returned in the Names array. /// /// /// 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. /// /// /// /// Receives a pointer to a pointer to a LSA_REFERENCED_DOMAIN_LIST structure. The Domains 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 non–Windows domains, the flat name is the /// identifying name of that domain, or it is NULL. /// /// /// 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 STATUS_NONE_MAPPED or STATUS_SOME_NOT_MAPPED /// /// /// /// /// 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 Name member of each structure contains the isolated name /// of the account. For domain SIDs, the Name member is not valid. /// /// /// The DomainIndex member of each entry in the Names array is the index of an entry in the Domains array returned in /// the ReferencedDomains parameter. The index identifies the Domains array for the domain in which the SID was found. /// /// /// 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 STATUS_NONE_MAPPED or STATUS_SOME_NOT_MAPPED /// /// /// /// If the function succeeds, the return value is one of the following NTSTATUS values. /// /// /// Return code /// Description /// /// /// STATUS_SOME_NOT_MAPPED /// Some of the SIDs could not be translated. This is an informational-level return value. /// /// /// STATUS_SUCCESS /// All of the SIDs were found and successfully translated. /// /// /// /// 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. /// /// /// /// Return code /// Description /// /// /// STATUS_NONE_MAPPED /// None of the SIDs were translated. This is an error-level return value. /// /// /// You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code. /// /// /// /// For account SIDs, the string returned in the Name 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. /// /// If the LsaLookupSids function cannot translate a SID, the function uses the following algorithm: /// /// /// /// 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. /// /// /// /// /// 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. /// /// /// /// /// In addition to looking up SIDs for local accounts, local domain accounts, and explicitly trusted domain accounts, /// LsaLookupSids can look up SIDs for any account in any domain in the Windows forest, including SIDs that appear only in the /// SIDhistory field of an account in the forest. The SIDhistory 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. /// /// // 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); /// /// /// The LsaLookupSids2 function looks up the names that correspond to an array of security identifiers (SIDs) and supports /// Internet provider identities. If LsaLookupSids2 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. /// /// /// /// /// 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. /// /// /// /// Flags that modify the lookup behavior. /// /// /// Value /// Meaning /// /// /// LSA_LOOKUP_DISALLOW_CONNECTED_ACCOUNT_INTERNET_SID /// /// 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. /// /// /// /// LSA_LOOKUP_PREFER_INTERNET_NAMES /// /// 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. /// /// /// /// LSA_LOOKUP_RETURN_LOCAL_NAMES /// Always returns local SAM account names even for Internet provider identities. /// /// /// /// /// Specifies the number of SIDs in the Sids array. This is also the number of entries returned in the Names array. /// /// /// /// 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. /// /// /// /// /// Receives a pointer to a pointer to a LSA_REFERENCED_DOMAIN_LIST structure. The Domains 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 non–Windows domains, the flat name is the /// identifying name of that domain, or it is NULL. /// /// /// 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 STATUS_NONE_MAPPED or STATUS_SOME_NOT_MAPPED /// /// /// /// /// 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 Name member of each structure contains the isolated name /// of the account. For domain SIDs, the Name member is not valid. /// /// /// The DomainIndex member of each entry in the Names array is the index of an entry in the Domains array returned in /// the ReferencedDomains parameter. The index identifies the Domains array for the domain in which the SID was found. /// /// /// 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 STATUS_NONE_MAPPED or STATUS_SOME_NOT_MAPPED /// /// /// /// If the function succeeds, the return value is one of the following NTSTATUS values. /// /// /// Return code /// Description /// /// /// STATUS_SOME_NOT_MAPPED /// Some of the SIDs could not be translated. This is an informational-level return value. /// /// /// STATUS_SUCCESS /// All of the SIDs were found and successfully translated. /// /// /// /// 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. /// /// /// /// Return code /// Description /// /// /// STATUS_NONE_MAPPED /// None of the SIDs were translated. This is an error-level return value. /// /// /// You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code. /// /// /// /// 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. /// /// /// For account SIDs, the string returned in the Name 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. /// /// If the LsaLookupSids2 function cannot translate a SID, the function uses the following algorithm: /// /// /// /// 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. /// /// /// /// /// 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. /// /// /// /// /// In addition to looking up SIDs for local accounts, local domain accounts, and explicitly trusted domain accounts, /// LsaLookupSids2 can look up SIDs for any account in any domain in the Windows forest, including SIDs that appear only in /// the SIDhistory field of an account in the forest. The SIDhistory 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. /// /// // 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); /// /// The LsaNtStatusToWinError function converts an NTSTATUS code returned by an LSA function to a Windows error code. /// /// An NTSTATUS code returned by an LSA function call. This value will be converted to a System error code. /// /// 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. /// // 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); /// [Undocumented] Opens an account. /// The policy handle. /// The account sid. /// The desired access. /// The account handle. /// NTSTATUS [PInvokeData("ntlsa.h")] [DllImport(Lib.AdvApi32, ExactSpelling = true)] public static extern NTStatus LsaOpenAccount(LSA_HANDLE PolicyHandle, PSID AccountSid, LsaAccountAccessMask DesiredAccess, out SafeLSA_HANDLE AccountHandle); /// /// 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. /// /// /// /// 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 NULL, the function opens the Policy object on the local system. /// /// /// /// /// A pointer to an LSA_OBJECT_ATTRIBUTES structure that specifies the connection attributes. The structure members are not used; /// initialize them to NULL or zero. /// /// /// /// /// 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. /// /// /// /// A pointer to an LSA_HANDLE variable that receives a handle to the Policy object. /// When you no longer need this handle, pass it to the LsaClose function to close it. /// /// /// If the function succeeds, the function returns STATUS_SUCCESS. /// If the function fails, it returns 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. /// /// /// /// To administer the local security policy of a local or remote system, you must call the LsaOpenPolicy function to establish /// a session with that system's LSA subsystem. LsaOpenPolicy 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. /// /// For an example that demonstrates calling this function see Opening a Policy Object Handle. /// // 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); /// /// 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. /// /// /// 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. /// /// /// 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. /// /// A pointer to an LSA_HANDLE variable that receives a handle to the Policy object. [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; } /// /// The LsaOpenTrustedDomainByName 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. /// /// /// A handle to a Policy object. This is the policy handle of the local machine. For more information, see Opening a Policy Object Handle. /// /// /// Name of the trusted domain. This name can be either the flat name, or the Domain Name System (DNS) domain name. /// /// /// An ACCESS_MASK structure that specifies the access permissions requested on the remote trusted domain object. /// /// /// /// 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. /// /// When your application no longer needs this handle, it should call LsaClose to delete the handle. /// /// /// 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. /// /// /// /// Value /// Description /// /// /// STATUS_ACCESS_DENIED /// Caller does not have the appropriate access to complete the operation. /// /// /// STATUS_OBJECT_NAME_NOT_FOUND /// There is no Trusted Domain object in the target system's LSA Database having the specified name. /// /// /// You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code. /// // 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); /// The LsaQueryDomainInformationPolicy function retrieves domain information from the Policyobject. /// A handle to the Policy object for the system. /// /// /// POLICY_DOMAIN_INFORMATION_CLASS enumeration that specifies the information to be returned from the Policyobject. The following /// table shows the possible values. /// /// /// /// Value /// Meaning /// /// /// PolicyDomainEfsInformation /// The information is for Encrypting File System. /// /// /// PolicyDomainKerberosTicketInformation /// The information is for a Kerberos ticket. /// /// /// /// Pointer to a buffer that receives the requested information. /// /// If the function succeeds, the return value is STATUS_SUCCESS. /// /// 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. /// /// /// /// Return code/value /// Description /// /// /// STATUS_INTERNAL_DB_CORRUPTION /// The policy database is corrupt. The returned policy information is not valid for the given class. /// /// /// /// /// The POLICY_VIEW_LOCAL_INFORMATION access type is required to retrieve domain information from the Policyobject. For more /// information, see Policy Object Access Rights. /// // 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); /// /// The LsaQueryForestTrustInformation function retrieves forest trust information for the specified Local Security Authority /// TrustedDomain object. /// /// A handle to the Policy object for the system. /// /// Pointer to an LSA_UNICODE_STRING structure that contains the name of the TrustedDomain object for which to retrieve forest trust information. /// /// /// Pointer to an LSA_FOREST_TRUST_INFORMATION structure that returns the forest trust information for the TrustedDomain object /// specified by the TrustedDomainName parameter. /// /// /// 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. /// /// /// /// Return code/value /// Description /// /// /// STATUS_INVALID_DOMAIN_ROLE /// The operation is legal only on the primary domain controller. /// /// /// STATUS_INVALID_DOMAIN_STATE /// The operation is legal only on domain controllers in the root domain. /// /// /// STATUS_NO_SUCH_DOMAIN /// The specified TrustedDomain object does not exist. /// /// /// STATUS_NOT_FOUND /// The specified TrustedDomain object does not contain forest trust information. /// /// /// /// Access to this function is protected by a securable object. // 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); /// The LsaQueryInformationPolicy function retrieves information about a Policy object. /// /// 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. /// /// /// /// Specifies one of the following values from the POLICY_INFORMATION_CLASS enumeration type. The value indicates the type of /// information to retrieve. /// /// /// /// Value /// Meaning /// /// /// PolicyAuditEventsInformation /// /// 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. /// /// /// /// PolicyPrimaryDomainInformation /// /// 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. /// /// /// /// PolicyAccountDomainInformation /// /// 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. /// /// /// /// PolicyLsaServerRoleInformation /// /// 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. /// /// /// /// PolicyModificationInformation /// /// 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. /// /// /// /// PolicyDnsDomainInformation /// /// 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. /// /// /// /// /// /// /// 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. /// /// When you no longer need the information, pass the returned pointer to LsaFreeMemory. /// /// /// If the LsaQueryInformationPolicy 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. /// /// For an example that demonstrates calling this function see Managing Policy Information. // 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); /// The LsaQueryInformationPolicy function retrieves information about a Policy object. /// /// 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. /// /// /// The structure containing the requested information. /// /// For an example that demonstrates calling this function see Managing Policy Information. [PInvokeData("ntsecapi.h", MSDNShortId = "2d543500-f639-4ef7-91f4-cdc5060dd567")] public static T LsaQueryInformationPolicy(LSA_HANDLE PolicyHandle) where T : struct { if (!CorrespondingTypeAttribute.CanGet(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(uint.MaxValue, CharSet.Unicode); } /// /// The LsaQueryTrustedDomainInfo function retrieves information about a trusted domain. /// /// /// /// 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. /// /// /// /// Pointer to the SID of the trusted domain to query. /// /// /// /// Specifies one of the following values from the TRUSTED_INFORMATION_CLASS enumeration type. The value indicates the type of /// information being requested. /// /// /// /// Value /// Meaning /// /// /// TrustedDomainNameInformation /// Retrieves the name of the trusted domain. The Buffer parameter receives a pointer to a TRUSTED_DOMAIN_NAME_INFO structure. /// /// /// TrustedPosixOffsetInformation /// /// 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. /// /// /// /// TrustedPasswordInformation /// /// 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. /// /// /// /// TrustedDomainInformationEx /// /// Retrieves extended information for the trusted domain. The Buffer parameter receives a pointer to a TRUSTED_DOMAIN_INFORMATION_EX structure. /// /// /// /// TrustedDomainInformationBasic /// This value is not supported. /// /// /// TrustedDomainFullInformation /// /// 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. /// /// /// /// /// /// /// 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. /// /// When you have finished using the information, free the returned pointer by passing it to LsaFreeMemory. /// /// /// If the function succeeds, the function returns STATUS_SUCCESS. /// /// If the function fails, it returns an NTSTATUS value that indicates the error. For more information, see LSA Policy /// Function Return Values. /// /// You can use the LsaNtStatusToWinError function to convert the NTSTATUS value to a Windows error code. /// // 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); /// The LsaQueryTrustedDomainInfoByName function returns information about a trusted domain. /// /// 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. /// /// /// String that contains the name of the trusted domain. This can either be the domain name or the flat name. /// /// /// Specifies the type of information to retrieve. This parameter can be one of the following values. /// /// /// Value /// Meaning /// /// /// TrustedDomainNameInformation /// Name of the trusted domain. /// /// /// TrustedPosixInformation /// Posix offset of the trusted domain. /// /// /// TrustedPasswordInformation /// Returns the password on the outbound side of the trust. /// /// /// TrustedDomainInformationBasic /// This value is not supported. /// /// /// TrustedDomainInformationEx /// Extended trust information, including the basic information and DNS domain name, and attributes about the trust. /// /// /// TrustedDomainFullInformation /// Full information, including the Posix offset and the authentication information. /// /// /// /// /// /// 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. /// /// When you have finished using the buffer, free it by calling the LsaFreeMemory function. /// /// /// If the function succeeds, the function returns STATUS_SUCCESS. /// /// If the function fails, it returns an NTSTATUS value, which can be one of the following values or one of the LSA Policy /// Function Return Values. /// /// /// /// Value /// Description /// /// /// STATUS_ACCESS_DENIED /// /// 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. /// /// /// /// STATUS_INSUFFICIENT_ RESOURCES /// Insufficient system resources, such as memory, to complete the call. /// /// /// You can use the LsaNtStatusToWinError function to convert the NTSTATUS value to a Windows error code. /// // 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); /// /// /// The LsaRemoveAccountRights 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. /// /// /// /// /// 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. /// /// /// /// Pointer to the security identifier (SID) of the account from which the privileges are removed. /// /// /// /// If TRUE, the function removes all privileges and deletes the account. In this case, the function ignores the UserRights /// parameter. If FALSE, the function removes the privileges specified by the UserRights parameter. /// /// /// /// /// 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. /// /// /// /// Specifies the number of elements in the UserRights array. /// /// /// 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. /// /// /// /// Value /// Description /// /// /// STATUS_NO_SUCH_PRIVILEGE /// One of the privilege names is not valid. /// /// /// STATUS_INVALID_PARAMETER /// Indicates the UserRights parameter was NULL and the AllRights parameter was FALSE. /// /// /// You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code. /// // 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); /// /// /// The LsaRemoveAccountRights 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. /// /// /// /// /// 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. /// /// /// /// Pointer to the security identifier (SID) of the account from which the privileges are removed. /// /// /// /// If TRUE, the function removes all privileges and deletes the account. In this case, the function ignores the UserRights /// parameter. If FALSE, the function removes the privileges specified by the UserRights parameter. /// /// /// /// /// 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. /// /// /// /// 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. /// /// /// /// Value /// Description /// /// /// STATUS_NO_SUCH_PRIVILEGE /// One of the privilege names is not valid. /// /// /// STATUS_INVALID_PARAMETER /// Indicates the UserRights parameter was NULL and the AllRights parameter was FALSE. /// /// /// You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code. /// // 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); /// Do not use the LSA private data functions. Instead, use the CryptProtectData and CryptUnprotectData functions. /// /// 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. /// /// /// Pointer to an LSA_UNICODE_STRING structure that contains the name of the key under which the private data is stored. /// To create a specialized object, add one of the following prefixes to the key name. /// /// /// Prefix /// Meaning /// /// /// L$ /// For local objects. /// /// /// G$ /// For global objects. /// /// /// M$ /// For computer objects. /// /// /// /// 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. /// /// /// /// Pointer to a variable that receives a pointer to an LSA_UNICODE_STRING structure that contains the private data. /// When you no longer need the information, pass the returned pointer to LsaFreeMemory. /// /// /// If the function succeeds, the function returns STATUS_SUCCESS. /// /// If the function fails, it returns an NTSTATUS value, which can be the following value or one of the LSA Policy Function /// Return Values. /// /// /// /// Return code /// Description /// /// /// STATUS_OBJECT_NAME_NOT_FOUND /// No private data is stored under the name specified by the KeyName parameter. /// /// /// You can use the LsaNtStatusToWinError function to convert the NTSTATUS value to a Windows error code. /// /// You must run this process "As Administrator" or the call fails with ERROR_ACCESS_DENIED. // 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); /// The LsaSetDomainInformationPolicy function sets domain information to the Policyobject. /// A handle to the Policy object for the system. /// /// /// POLICY_DOMAIN_INFORMATION_CLASS enumeration that specifies the information to be set to the Policyobject. The following table /// shows the possible values. /// /// /// /// Value /// Meaning /// /// /// PolicyDomainEfsInformation /// The information is for Encrypting File System. /// /// /// PolicyDomainKerberosTicketInformation /// The information is for a Kerberos ticket. /// /// /// /// Pointer to a buffer that contains the information to set to the Policyobject. /// /// If the function succeeds, the return value is STATUS_SUCCESS. /// /// 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. /// /// /// /// Return code/value /// Description /// /// /// STATUS_INTERNAL_DB_CORRUPTION /// The policy database is corrupt. The returned policy information is not valid for the given class. /// /// /// /// /// The POLICY_TRUST_ADMIN access type is required to set domain information to the Policyobject. For more information, see Policy /// Object Access Rights. /// // 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); /// The LsaSetDomainInformationPolicy function sets domain information to the Policyobject. /// The type of the structure being passed as . /// A handle to the Policy object for the system. /// The information to set to the Policyobject. /// /// The POLICY_TRUST_ADMIN access type is required to set domain information to the Policyobject. For more information, see Policy /// Object Access Rights. /// [PInvokeData("ntsecapi.h", MSDNShortId = "77af6fdc-a52e-476c-9de2-36ee48133a87")] public static void LsaSetDomainInformationPolicy(LSA_HANDLE PolicyHandle, in T value) where T : struct { if (!CorrespondingTypeAttribute.CanSet(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(); } /// /// /// The LsaSetForestTrustInformation function sets the forest trust information for a specified Local Security Authority /// TrustedDomain object. /// /// /// /// A handle to the Policy object for the system. /// /// /// /// 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. /// /// /// /// /// 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. /// /// /// /// /// Boolean value that specifies whether changes to the TrustedDomain object are persisted. If this value is TRUE, 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 TrustedDomain object specified by the TrustedDomainName parameter. If this value is /// FALSE, the forest trust information will be set to the TrustedDomain object. /// /// /// /// /// Pointer to a pointer to an LSA_FOREST_TRUST_COLLISION_INFORMATION structure that returns information about any collisions that occurred. /// /// /// /// 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. /// /// /// /// Return code/value /// Description /// /// /// STATUS_INVALID_DOMAIN_STATE /// The operation is legal only on domain controllers in the root domain. /// /// /// STATUS_INVALID_DOMAIN_ROLE /// The operation is legal only on the primary domain controller. /// /// /// // 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); /// The LsaSetInformationPolicy function modifies information in a Policy object. /// /// 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. /// /// /// /// Specifies one of the following values from the POLICY_INFORMATION_CLASS enumeration type. The value indicates the type of /// information to set. /// /// /// /// Value /// Meaning /// /// /// PolicyAuditEventsInformation /// /// 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. /// /// /// /// PolicyPrimaryDomainInformation /// /// 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. /// /// /// /// PolicyAccountDomainInformation /// /// 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. /// /// /// /// PolicyDnsDomainInformation /// /// 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. /// /// /// /// PolicyLsaServerRoleInformation /// /// 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. /// /// /// /// /// /// Pointer to a structure containing the information to set. The type of structure depends on the value of the InformationClass parameter. /// /// /// 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. /// // 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); /// /// The LsaSetInformationPolicy function modifies information in a Policy object. /// /// The type of the structure being passed as . /// 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. /// A structure containing the information to set. /// Unable to use {typeof(T).Name} with this function. [PInvokeData("ntsecapi.h", MSDNShortId = "2aa3b09e-2cd9-4a09-bfd6-b37c97266dcb")] public static void LsaSetInformationPolicy(LSA_HANDLE PolicyHandle, in T value) where T : struct { if (!CorrespondingTypeAttribute.CanSet(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(); } /// Undocumented. /// The account handle. /// The system access. /// /// 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. /// [PInvokeData("ntlsa.h")] [DllImport(Lib.AdvApi32, ExactSpelling = true)] public static extern NTStatus LsaSetSystemAccessAccount(LSA_HANDLE AccountHandle, int SystemAccess); /// The LsaSetTrustedDomainInfoByName function sets values for a TrustedDomain object. /// /// 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. /// /// /// Name of the trusted domain to set values for. This can either be the domain name or the flat name. /// /// /// Specifies the type of information to set. Specify one of the following values. /// /// /// Value /// Meaning /// /// /// TrustedPosixInformation /// Posix offset of the trusted domain. /// /// /// TrustedDomainInformationEx /// Extended trust information, including the basic information and DNS domain name, and attributes about the trust. /// /// /// TrustedDomainAuthInformation /// /// Authentication information for the trust, including authentication information for both the inbound and outbound side of the /// trust (if it exists). /// /// /// /// TrustedDomainFullInformation /// Full information, including the Posix offset and the authentication information. /// /// /// /// /// Pointer to a structure that contains the information to set. The type of structure depends on the value of the InformationClass parameter. /// /// /// 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 the "LSA Policy Function Return Values" /// section of Security Management Return Values. /// /// You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code. /// // 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); /// /// The LsaSetTrustedDomainInformation function modifies a Policy object's information about a trusted domain. /// /// /// /// 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. /// /// /// /// /// 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. /// /// /// /// /// Specifies one of the following values from the TRUSTED_INFORMATION_CLASS enumeration type. The value indicates the type of /// information being set. /// /// /// /// Value /// Meaning /// /// /// TrustedDomainNameInformation /// /// 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. /// /// /// /// TrustedPosixOffsetInformation /// /// 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. /// /// /// /// TrustedPasswordInformation /// /// 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. /// /// /// /// /// /// /// Pointer to a structure containing the information to set. The type of structure depends on the value of the InformationClass parameter. /// /// /// /// 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. /// // 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); /// Do not use the LSA private data functions. Instead, use the CryptProtectData and CryptUnprotectData functions. /// /// 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. /// /// /// Pointer to an LSA_UNICODE_STRING structure containing the name of the key under which the private data is stored. /// /// /// /// Pointer to an LSA_UNICODE_STRING structure containing the private data to store. The function encrypts this data before storing it. /// /// /// If this parameter is NULL, 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. /// /// /// /// 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. /// /// /// The LsaStorePrivateData function can be used by server applications to store client and machine passwords. /// /// 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. /// /// /// 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". /// /// /// 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. /// /// /// The data stored by the LsaStorePrivateData 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. /// /// Use the LsaRetrievePrivateData function to retrieve the value stored by LsaStorePrivateData. /// // 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); /// /// The LsaClose function closes a handle to a Policy or TrustedDomain object. /// /// /// /// 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. /// /// /// /// 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. /// // 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); /// /// /// The LsaFreeMemory 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 LsaFreeMemory when the memory is no longer required. /// /// /// /// /// Pointer to memory buffer that was allocated by an LSA function call. If LsaFreeMemory is successful, this buffer is freed. /// /// /// /// If the function succeeds, the return value is STATUS_SUCCESS. /// /// 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. /// /// /// /// Return code /// Description /// /// /// STATUS_UNSUCCESSFUL /// Memory could not be freed because it was not allocated by an LSA function call. /// /// /// You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code. /// // 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); /// Provides a handle to an LSA enumeration. [StructLayout(LayoutKind.Sequential)] public struct LSA_ENUMERATION_HANDLE : IHandle { private readonly IntPtr handle; /// Initializes a new instance of the struct. /// An object that represents the pre-existing handle to use. public LSA_ENUMERATION_HANDLE(IntPtr preexistingHandle) => handle = preexistingHandle; /// Returns an invalid handle by instantiating a object with . public static LSA_ENUMERATION_HANDLE NULL => new LSA_ENUMERATION_HANDLE(IntPtr.Zero); /// Gets a value indicating whether this instance is a null handle. public bool IsNull => handle == IntPtr.Zero; /// Performs an explicit conversion from to . /// The handle. /// The result of the conversion. public static explicit operator IntPtr(LSA_ENUMERATION_HANDLE h) => h.handle; /// Performs an implicit conversion from to . /// The pointer to a handle. /// The result of the conversion. public static implicit operator LSA_ENUMERATION_HANDLE(IntPtr h) => new LSA_ENUMERATION_HANDLE(h); /// Implements the operator !=. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator !=(LSA_ENUMERATION_HANDLE h1, LSA_ENUMERATION_HANDLE h2) => !(h1 == h2); /// Implements the operator ==. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator ==(LSA_ENUMERATION_HANDLE h1, LSA_ENUMERATION_HANDLE h2) => h1.Equals(h2); /// public override bool Equals(object obj) => obj is LSA_ENUMERATION_HANDLE h ? handle == h.handle : false; /// public override int GetHashCode() => handle.GetHashCode(); /// public IntPtr DangerousGetHandle() => handle; } /// Used with the LsaEnumerateAccountsWithUserRight function to return a pointer to a SID. // 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 { /// Pointer to a SID. public PSID Sid; } /// /// The LSA_FOREST_TRUST_BINARY_DATA structure contains binary data used in Local Security Authority forest trust operations. /// // 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 { /// The count of bytes in Buffer. public uint Length; /// The trust record. If the Length field has a value other than 0, this field MUST NOT be NULL. public IntPtr Buffer; } /// /// The LSA_FOREST_TRUST_COLLISION_INFORMATION structure contains information about Local Security Authority forest trust collisions. /// // 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 { /// Number of LSA_FOREST_TRUST_COLLISION_RECORD structures in the array pointed to by the Entries member. public uint RecordCount; /// /// Pointer to a pointer to an array of LSA_FOREST_TRUST_COLLISION_RECORD structures, each of which contains information about a /// single collision. /// public IntPtr Entries; } /// /// The LSA_FOREST_TRUST_COLLISION_RECORD structure contains information about a Local Security Authority forest trust collision. /// // 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 { /// /// Index of this collision record in the array of LSA_FOREST_TRUST_COLLISION_RECORD structures pointed to by the /// Entries member of the LSA_FOREST_TRUST_COLLISION_INFORMATION structure. /// public uint Index; /// /// Type of the collision. The following table shows the possible values. /// /// /// Value /// Meaning /// /// /// CollisionTdo /// Collision between TrustedDomain objects. /// /// /// CollisionXref /// Collision between cross-references. /// /// /// CollisionOther /// Collision that is not a collision between TrustedDomain objects or cross-references. /// /// /// public LSA_FOREST_TRUST_COLLISION_RECORD_TYPE Type; /// /// /// Flags that provide more information about the collision. The following table lists the possible values for this member when /// the Type member is CollisionTdo. /// /// LSA_TLN_DISABLED_NEW (0x00000001) /// LSA_TLN_DISABLED_ADMIN (0x00000002) /// LSA_TLN_DISABLED_CONFLICT (0x00000004) /// The following table lists the possible values for this member when the Type member is CollisionXref. /// LSA_SID_DISABLED_ADMIN (0x00000001) /// LSA_SID_DISABLED_CONFLICT (0x00000002) /// LSA_NB_DISABLED_ADMIN (0x00000004) /// LSA_NB_DISABLED_CONFLICT (0x00000008) /// public CollisionFlags Flags; /// LSA_UNICODE_STRING structure that contains the name of the collision record. public LSA_UNICODE_STRING Name; } /// The LSA_FOREST_TRUST_DOMAIN_INFO structure contains identifying information for a domain. // 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 { /// Domain SID for the trusted domain. public PSID Sid; /// LSA_UNICODE_STRING structure that contains the DNS name of the domain. public LSA_UNICODE_STRING DnsName; /// LSA_UNICODE_STRING structure that contains the NetBIOS name of the domain. public LSA_UNICODE_STRING NetbiosName; } /// The LSA_FOREST_TRUST_INFORMATION structure contains Local Security Authority forest trust information. // 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 { /// A count of elements in the Entries array. public uint RecordCount; /// /// An array of LSA_FOREST_TRUST_RECORD structures. If the RecordCount field has a value other than 0, this field MUST NOT be NULL. /// public IntPtr Entries; } /// /// The LSA_FOREST_TRUST_RECORD structure represents a Local Security Authority forest trust record. /// // 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 { /// Flags that control the behavior of the operation. public LSA_TLN Flags; /// /// /// LSA_FOREST_TRUST_RECORD_TYPE enumeration that indicates the type of the record. The following table shows the possible values. /// /// /// /// Value /// Meaning /// /// /// ForestTrustTopLevelName /// Record contains an included top-level name. /// /// /// ForestTrustTopLevelNameEx /// Record contains an excluded top-level name. /// /// /// ForestTrustDomainInfo /// Record contains an LSA_FOREST_TRUST_DOMAIN_INFO structure. /// /// /// ForestTrustRecordTypeLast /// Marks the end of an enumeration. /// /// /// public LSA_FOREST_TRUST_RECORD_TYPE ForestTrustType; /// Time stamp of the record. public FILETIME Time; /// /// 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. /// public ForestTrustDataUnion ForestTrustData; /// /// 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. /// [StructLayout(LayoutKind.Explicit)] public struct ForestTrustDataUnion { /// Top-level name. This member is used only if the ForestTrustType member is ForestTrustTopLevelName or ForestTrustTopLevelNameEx. [FieldOffset(0)] public LSA_UNICODE_STRING TopLevelName; /// Domain information. This member is used only if the ForestTrustType member is ForestTrustDomainInfo. [FieldOffset(0)] public LSA_FOREST_TRUST_DOMAIN_INFO DomainInfo; /// Binary data. This member is used for unrecognized entries after ForestTrustRecordTypeLast. [FieldOffset(0)] public LSA_FOREST_TRUST_BINARY_DATA Data; } } /// Provides a handle to a LSA handle. [StructLayout(LayoutKind.Sequential)] public struct LSA_HANDLE : IHandle { private readonly IntPtr handle; /// Initializes a new instance of the struct. /// An object that represents the pre-existing handle to use. public LSA_HANDLE(IntPtr preexistingHandle) => handle = preexistingHandle; /// Returns an invalid handle by instantiating a object with . public static LSA_HANDLE NULL => new LSA_HANDLE(IntPtr.Zero); /// Gets a value indicating whether this instance is a null handle. public bool IsNull => handle == IntPtr.Zero; /// Performs an explicit conversion from to . /// The handle. /// The result of the conversion. public static explicit operator IntPtr(LSA_HANDLE h) => h.handle; /// Performs an implicit conversion from to . /// The pointer to a handle. /// The result of the conversion. public static implicit operator LSA_HANDLE(IntPtr h) => new LSA_HANDLE(h); /// Implements the operator !=. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator !=(LSA_HANDLE h1, LSA_HANDLE h2) => !(h1 == h2); /// Implements the operator ==. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator ==(LSA_HANDLE h1, LSA_HANDLE h2) => h1.Equals(h2); /// public override bool Equals(object obj) => obj is LSA_HANDLE h ? handle == h.handle : false; /// public override int GetHashCode() => handle.GetHashCode(); /// public IntPtr DangerousGetHandle() => handle; } /// The LSA_REFERENCED_DOMAIN_LIST structure contains information about the domains referenced in a lookup operation. // 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 { /// Specifies the number of entries in the Domains array. public uint Entries; /// Pointer to an array of LSA_TRUST_INFORMATION structures that identify the referenced domains. public IntPtr Domains; /// Gets the list of structures from the field. public IEnumerable DomainList => Domains.ToIEnum((int)Entries); } /// /// The LSA_TRANSLATED_SID structure is used with the LsaLookupNames function to return information about the SID that /// identifies an account. /// // 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 { /// /// A value from the SID_NAME_USE enumeration type that identifies the type of SID. /// /// If Use has one of the following values, one or both of the RelativeId or DomainIndex members of /// LSA_TRANSLATED_SID is not valid. These members are valid if Use has any other value. /// /// /// /// Value /// Meaning /// /// /// SidTypeDomain /// The DomainIndex member is valid, but the RelativeId member is not valid and must be ignored. /// /// /// SidTypeInvalid /// Both DomainIndex and RelativeId are not valid and must be ignored. /// /// /// SidTypeUnknown /// Both DomainIndex and RelativeId members are not valid and must be ignored. /// /// /// public SID_NAME_USE Use; /// /// Specifies the relative identifier (RID) of the account's SID. The RID identifies the account relative to the domain /// referenced by the DomainIndex member. The account's complete SID consists of the domain SID followed by the RID. /// public uint RelativeId; /// /// /// 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. /// /// If there is no corresponding domain for an account, this member contains a negative value. /// public int DomainIndex; } /// /// The LSA_TRUST_INFORMATION structure identifies a domain. /// /// /// TRUSTED_DOMAIN_INFORMATION_BASIC is an alias for this structure. /// /// The TRUSTED_DOMAIN_INFORMATION_BASIC structure identifies a domain. This structure is used by the LsaQueryTrustedDomainInfo /// function when its InformationClass parameter is set to TrustedDomainInformationBasic. /// /// // 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 { /// An LSA_UNICODE_STRING structure that contains the name of the domain. public LSA_UNICODE_STRING Name; /// Pointer to the SID of the domain. public PSID Sid; } /// /// 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. /// [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 8)] [PInvokeData("Ntsecapi.h", MSDNShortId = "ms721841")] public struct LSA_UNICODE_STRING { /// /// Specifies the length, in bytes, of the string pointed to by the Buffer member, not including the terminating null character, /// if any. /// public ushort length; /// /// 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. /// public ushort MaximumLength; /// /// Pointer to a wide character string. Note that the strings returned by the various LSA functions might not be null-terminated. /// public StrPtrUni Buffer; /* REMOVED TO AVOID MEMORY LEAK * /// Initializes a new instance of the struct from a string. /// The string value. /// String exceeds 32Kb of data. 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); } } */ /// Gets the number of characters in the string. public int Length => length / UnicodeEncoding.CharSize; /// Returns a that represents this instance. /// A that represents this instance. public override string ToString() => StringHelper.GetString((IntPtr)Buffer, CharSet.Unicode, length) ?? string.Empty; /// Performs an implicit conversion from to . /// The value. /// The result of the conversion. public static implicit operator string(LSA_UNICODE_STRING value) => value.ToString(); } /// Smart wrapper for LSA_FOREST_TRUST_INFORMATION. public class LsaForestTrustInformation : IDisposable { private SafeAllocatedMemoryHandle allocatedMemory; /// A list of LsaForestTrustRecord entries that wrap LSA_FOREST_TRUST_RECORD. /// Returns a value. public List Entries { get; } = new List(); /// Creates a new instance from a memory pointer. This can fail if the memory is not allocated properly. /// The memory pointer. /// A new instance of . public static LsaForestTrustInformation FromBuffer(IntPtr ptr) { var ret = new LsaForestTrustInformation(); var info = ptr.ToStructure(); foreach (var e in info.Entries.ToIEnum((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; } /// /// Returns an instance of . 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. /// /// A instance matching the values of this instance. 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() }; } /// Releases the unmanaged resources used by this object, and optionally releases the managed resources. void IDisposable.Dispose() => allocatedMemory?.Dispose(); /// Represents a LSA_FOREST_TRUST_RECORD with the ForestTrustType value set to ForestTrustDomainInfo. [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); /// The DNS name of the domain. public string DnsName { get => dnsName; set => dnsName = value; } /// The NetBIOS name of the domain. public string NetbiosName { get => netbiosName; set => netbiosName = value; } /// Domain SID for the trusted domain. public SafePSID Sid { get; set; } /// Converts this instance. /// A LSA_FOREST_TRUST_RECORD instance. 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; } } /// Represents a LSA_FOREST_TRUST_RECORD. public abstract class LsaForestTrustRecord { /// Flags that control the behavior of the operation. public LSA_TLN Flags { get; set; } /// Time stamp of the record. public DateTime Time { get; set; } /// Converts this instance. /// A LSA_FOREST_TRUST_RECORD instance. protected internal virtual LSA_FOREST_TRUST_RECORD Convert() => new LSA_FOREST_TRUST_RECORD { Flags = Flags, Time = Time.ToFileTimeStruct() }; } /// /// Represents a LSA_FOREST_TRUST_RECORD with the ForestTrustType value set to ForestTrustTopLevelNameEx if the /// property is and ForestTrustTopLevelName if the property /// is . /// [DebuggerDisplay("TopName:{TopLevelName}, Excl:{Excluded}, Time:{Time:u}, Flg:{Flags}")] public class LsaForestTrustTopLevelName : LsaForestTrustRecord { private SafeLSA_UNICODE_STRING topLevelName = new SafeLSA_UNICODE_STRING(null); /// Initializes a new instance of the class. /// The name. /// if set to true [exclude]. public LsaForestTrustTopLevelName(string name = null, bool exclude = false) { TopLevelName = name; Excluded = exclude; } /// /// Gets or sets a value indicating whether this contains an excluded top-level name.. /// /// true if excluded; otherwise, false to include. public bool Excluded { get; set; } /// Top-level name. This member is used only if the ForestTrustType member is ForestTrustTopLevelName or ForestTrustTopLevelNameEx. public string TopLevelName { get => topLevelName; set => topLevelName = value; } /// Converts this instance. /// A LSA_FOREST_TRUST_RECORD instance. 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; } } } /// /// Provides a to a LSA handle that releases a created LSA_HANDLE instance at disposal using LsaClose. /// public class SafeLSA_HANDLE : SafeHANDLE { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeLSA_HANDLE(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Initializes a new instance of the class. private SafeLSA_HANDLE() : base() { } /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator LSA_HANDLE(SafeLSA_HANDLE h) => h.handle; /// protected override bool InternalReleaseHandle() => LsaClose(this).Succeeded; } /// Provides a for that manages its own memory allocations. public class SafeLSA_UNICODE_STRING : SafeHANDLE { /// Initializes a new instance of the class. /// The value of the string to assign. public SafeLSA_UNICODE_STRING(string value) : base(IntPtr.Zero, true) => Buffer = value; /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeLSA_UNICODE_STRING(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Initializes a new instance of the class. private SafeLSA_UNICODE_STRING() : base() { } /// The string value. public string Buffer { get => LsaUnicodeStringMarshaler.MarshalPtr(handle); set { Close(); SetHandle(LsaUnicodeStringMarshaler.MarshalValue(value)); } } /// /// Specifies the length, in bytes, of the string pointed to by the Buffer member, not including the terminating null character, /// if any. /// public short length => IsInvalid ? (short)0 : Marshal.ReadInt16(handle); /// /// 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. /// public short MaximumLength => IsInvalid ? (short)0 : Marshal.ReadInt16(handle, 2); /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator LSA_UNICODE_STRING(SafeLSA_UNICODE_STRING h) => h.handle.ToStructure(); /// Performs an implicit conversion from to . /// The string value. /// The result of the conversion. public static implicit operator SafeLSA_UNICODE_STRING(string val) => new SafeLSA_UNICODE_STRING(val); /// Performs an implicit conversion from to . /// The instance. /// The result of the conversion. public static implicit operator string(SafeLSA_UNICODE_STRING h) => h.Buffer; /// protected override bool InternalReleaseHandle() { if (handle != IntPtr.Zero) Marshal.FreeCoTaskMem(handle); return true; } } /// /// Provides a to a LSA memory handle that releases a created LsaMemoryHandle instance at disposal using . /// public class SafeLsaMemoryHandle : SafeLsaMemoryHandleBase { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeLsaMemoryHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Initializes a new instance of the class. private SafeLsaMemoryHandle() : base() { } /// protected override bool InternalReleaseHandle() => LsaFreeMemory(handle).Succeeded; } /// Base class for other LSA memory handles. public abstract class SafeLsaMemoryHandleBase : SafeHANDLE { /// Initializes a new instance of the class. protected SafeLsaMemoryHandleBase() : base() { } /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// protected SafeLsaMemoryHandleBase(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) => SetHandle(preexistingHandle); /// Gets or sets the size that will be passed to limit buffer overruns. /// The size. public SizeT Size { get; set; } = 0; /// /// Extracts an array of structures of containing items. This /// call can cause memory exceptions if the pointer does not have sufficient allocated memory to retrieve all the structures. /// /// The type of the structures to retrieve. /// The number of structures to retrieve. /// The number of bytes to skip before reading the structures. /// An array of structures of . public T[] ToArray(int count, int prefixBytes = 0) { if (IsInvalid) return null; return handle.ToArray(count, prefixBytes, Size == 0 ? (SizeT)int.MaxValue : Size); } /// /// Marshals data from this block of memory to a newly allocated managed object of the type specified by a generic type parameter. /// /// The type of the object to which the data is to be copied. This must be a structure. /// A managed object that contains the data that this holds. public T ToStructure() { if (IsInvalid) return default; return handle.ToStructure(Size == 0 ? (SizeT)int.MaxValue : Size); } } /// /// A for values that must be freed using the function. /// public sealed class SafeLsaReturnBufferHandle : SafeLsaMemoryHandleBase { /// Initializes a new instance of the class. /// The pointer to the memory allocated by an Lsa function. /// if set to true release the memory when out of scope. public SafeLsaReturnBufferHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Initializes a new instance of the class. private SafeLsaReturnBufferHandle() : base() { } /// protected override bool InternalReleaseHandle() => Secur32.LsaFreeReturnBuffer(handle) == 0; } /// A custom marshaler for functions using LSA_UNICODE_STRING arrays so that managed string arrays can be used. /// 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."); } } /// A custom marshaler for functions using LSA_UNICODE_STRING so that managed strings can be used. /// 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; } } } }