Collapsed SafeLocalPSID into SafePSID. Enhanced SafePSIDArray.

Finished unit testing and changes for Lsa** functions.
pull/83/head
David Hall 2019-08-09 14:18:18 -06:00
parent 198a3fafd5
commit 0c73576e40
10 changed files with 804 additions and 252 deletions

View File

@ -48,10 +48,7 @@ namespace Vanara.PInvoke
/// <summary>Should be <c>NULL</c>.</summary>
public IntPtr SecurityQualityOfService;
/// <summary>
/// Returns a completely empty reference. This value should be used when calling <see cref="LsaOpenPolicy(string, ref
/// LSA_OBJECT_ATTRIBUTES, LsaPolicyRights, out SafeLSA_HANDLE)"/>.
/// </summary>
/// <summary>Returns a completely empty reference. This value should be used when calling <see cref="LsaOpenPolicy(string, ref LSA_OBJECT_ATTRIBUTES, LsaPolicyRights, out SafeLSA_HANDLE)"/>.</summary>
/// <value>An <see cref="LSA_OBJECT_ATTRIBUTES"/> instance with all members set to <c>NULL</c> or zero.</value>
public static LSA_OBJECT_ATTRIBUTES Empty { get; } = new LSA_OBJECT_ATTRIBUTES();
}
@ -160,7 +157,7 @@ namespace Vanara.PInvoke
public SID_NAME_USE Use;
/// <summary>The complete SID of the account.</summary>
public IntPtr Sid;
public PSID Sid;
/// <summary>
/// The index of an entry in a related LSA_REFERENCED_DOMAIN_LIST data structure which describes the domain that owns the
@ -196,7 +193,7 @@ namespace Vanara.PInvoke
var s = ManagedObj as string;
if (s == null) return IntPtr.Zero;
var str = new LSA_STRING(s);
return str.StructureToPtr(Marshal.AllocCoTaskMem, out int _);
return str.StructureToPtr(Marshal.AllocCoTaskMem, out var _);
}
public object MarshalNativeToManaged(IntPtr pNativeData)

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace Vanara.PInvoke
@ -82,12 +83,12 @@ namespace Vanara.PInvoke
}
/// <summary>
/// The LsaGetAppliedCAPIDs function returns an array of central access policies (CAPs) identifiers (CAPIDs) of all the CAPs applied
/// on a specific computer.
/// The <c>LsaGetAppliedCAPIDs</c> function returns an array of central access policies (CAPs) identifiers (CAPIDs) of all the CAPs
/// applied on a specific computer.
/// </summary>
/// <param name="systemName">
/// The name of the specific computer. The name can have the form of "ComputerName" or "\\ComputerName". If this parameter is NULL,
/// then the function returns the CAPIDs of the local computer.
/// <param name="SystemName">
/// A pointer to an LSA_UNICODE_STRING structure that contains the name of the specific computer. The name can have the form of
/// "ComputerName" or "\ComputerName". If this parameter is <c>NULL</c>, then the function returns the CAPIDs of the local computer.
/// </param>
/// <param name="CAPIDs">
/// A pointer to a variable that receives an array of pointers to CAPIDs that identify the CAPs available on the specified computer.
@ -98,18 +99,46 @@ namespace Vanara.PInvoke
/// CAPIDs parameter contains the same number of elements as the CAPIDCount parameter.
/// </param>
/// <returns>
/// If the function succeeds, the return value is STATUS_SUCCESS.
/// <para>If the function succeeds, the return value is STATUS_SUCCESS.</para>
/// <para>
/// If the function fails, the return value is one of the LSA Policy Function Return Values. You can use the LsaNtStatusToWinError
/// function to convert the NTSTATUS code to a Windows error code.
/// function to convert the <c>NTSTATUS</c> code to a Windows error code.
/// </para>
/// </returns>
[DllImport(Lib.AdvApi32, ExactSpelling = true, SetLastError = true, CharSet = CharSet.Unicode)]
[PInvokeData("ntlsa.h", MSDNShortId = "hh846251")]
/// <remarks>
/// For specific details about the central access policies, you can query the attributes of the central access policy object in the
/// Active Directory on the specified computer's domain controller. Look for the object whose <c>msAuthz-CentralAccessPolicyID</c>
/// attribute matches one of the returned CAPIDs.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/ntlsa/nf-ntlsa-lsagetappliedcapids
// NTSTATUS LsaGetAppliedCAPIDs( PLSA_UNICODE_STRING SystemName, PSID **CAPIDs, PULONG CAPIDCount );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntlsa.h", MSDNShortId = "DF10F5CE-BBF5-4CA8-919B-F59B7775C983")]
public static extern NTStatus LsaGetAppliedCAPIDs(
[In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringMarshaler))] string systemName,
[In, Optional, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringMarshaler))] string systemName,
out SafeLsaMemoryHandle CAPIDs, out uint CAPIDCount);
/// <summary>
/// The <c>LsaGetAppliedCAPIDs</c> function returns an array of central access policies (CAPs) identifiers (CAPIDs) of all the CAPs
/// applied on a specific computer.
/// </summary>
/// <param name="SystemName">
/// A pointer to an LSA_UNICODE_STRING structure that contains the name of the specific computer. The name can have the form of
/// "ComputerName" or "\ComputerName". If this parameter is <c>NULL</c>, then the function returns the CAPIDs of the local computer.
/// </param>
/// <returns>An array of pointers to CAPIDs that identify the CAPs available on the specified computer.</returns>
/// <remarks>
/// For specific details about the central access policies, you can query the attributes of the central access policy object in the
/// Active Directory on the specified computer's domain controller. Look for the object whose <c>msAuthz-CentralAccessPolicyID</c>
/// attribute matches one of the returned CAPIDs.
/// </remarks>
[PInvokeData("ntlsa.h", MSDNShortId = "DF10F5CE-BBF5-4CA8-919B-F59B7775C983")]
public static IEnumerable<PSID> LsaGetAppliedCAPIDs([Optional] string systemName)
{
LsaGetAppliedCAPIDs(systemName, out var pCapIds, out var idCnt).ThrowIfFailed();
return pCapIds.ToArray<PSID>((int)idCnt);
}
/// <summary>
/// <para>
/// Retrieves the locally unique identifier (LUID) used by the Local Security Authority (LSA) to represent the specified privilege name.
@ -159,7 +188,7 @@ namespace Vanara.PInvoke
// CAPIDCount, PCENTRAL_ACCESS_POLICY *CAPs, PULONG CAPCount );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntlsa.h", MSDNShortId = "55D6FD6F-0FD5-41F6-967B-F5600E19C3EF")]
public static extern NTStatus LsaQueryCAPs([In] IntPtr[] CAPIDs, uint CAPIDCount, SafeLsaMemoryHandle CAPs, out uint CAPCount);
public static extern NTStatus LsaQueryCAPs([In] PSID[] CAPIDs, uint CAPIDCount, out SafeLsaMemoryHandle CAPs, out uint CAPCount);
/// <summary>
/// <para>Represents a central access policy that contains a set of central access policy entries.</para>
@ -174,7 +203,7 @@ namespace Vanara.PInvoke
/// <summary>
/// <para>The identifier of the central access policy.</para>
/// </summary>
public IntPtr CAPID;
public PSID CAPID;
/// <summary>
/// <para>The name of the central access policy.</para>
@ -251,7 +280,7 @@ namespace Vanara.PInvoke
/// <summary>
/// <para>A buffer of security descriptors associated with the entry.</para>
/// </summary>
public IntPtr SD;
public PSECURITY_DESCRIPTOR SD;
/// <summary>
/// <para>The length of the buffer pointed to by the StagedSD field.</para>
@ -261,7 +290,7 @@ namespace Vanara.PInvoke
/// <summary>
/// <para>A buffer of staged security descriptors associated with the entry.</para>
/// </summary>
public IntPtr StagedSD;
public PSECURITY_DESCRIPTOR StagedSD;
/// <summary>
/// <para>This field is reserved.</para>

View File

@ -81,36 +81,52 @@ namespace Vanara.PInvoke
[Flags]
public enum LSA_TLN
{
/// <summary>The top-level name trust record is disabled during initial creation.<note type="note">This flag MUST be used only
/// with forest trust record types of ForestTrustTopLevelName and ForestTrustTopLevelNameEx.</note></summary>
/// <summary>
/// The top-level name trust record is disabled during initial creation. <note type="note">This flag MUST be used only with
/// forest trust record types of ForestTrustTopLevelName and ForestTrustTopLevelNameEx.</note>
/// </summary>
LSA_TLN_DISABLED_NEW = 0x00000001,
/// <summary>The top-level name trust record is disabled by the domain administrator.<note type="note">This flag MUST be used only
/// with forest trust record types of ForestTrustTopLevelName and ForestTrustTopLevelNameEx.</note></summary>
/// <summary>
/// The top-level name trust record is disabled by the domain administrator. <note type="note">This flag MUST be used only with
/// forest trust record types of ForestTrustTopLevelName and ForestTrustTopLevelNameEx.</note>
/// </summary>
LSA_TLN_DISABLED_ADMIN = 0x00000002,
/// <summary>The top-level name trust record is disabled due to a conflict.<note type="note">This flag MUST be used only with
/// forest trust record types of ForestTrustTopLevelName and ForestTrustTopLevelNameEx.</note></summary>
/// <summary>
/// The top-level name trust record is disabled due to a conflict. <note type="note">This flag MUST be used only with forest
/// trust record types of ForestTrustTopLevelName and ForestTrustTopLevelNameEx.</note>
/// </summary>
LSA_TLN_DISABLED_CONFLICT = 0x00000004,
/// <summary>The domain information trust record is disabled by the domain administrator.<note type="note">This flag MUST be used
/// only with a forest trust record type of ForestTrustDomainInfo.</note></summary>
/// <summary>
/// The domain information trust record is disabled by the domain administrator. <note type="note">This flag MUST be used only
/// with a forest trust record type of ForestTrustDomainInfo.</note>
/// </summary>
LSA_SID_DISABLED_ADMIN = 0x00000001,
/// <summary>The domain information trust record is disabled due to a conflict.<note type="note">This flag MUST be used only with
/// a forest trust record type of ForestTrustDomainInfo.</note></summary>
/// <summary>
/// The domain information trust record is disabled due to a conflict. <note type="note">This flag MUST be used only with a
/// forest trust record type of ForestTrustDomainInfo.</note>
/// </summary>
LSA_SID_DISABLED_CONFLICT = 0x00000002,
/// <summary>The domain information trust record is disabled by the domain administrator.<note type="note">This flag MUST be used
/// only with a forest trust record type of ForestTrustDomainInfo.</note></summary>
/// <summary>
/// The domain information trust record is disabled by the domain administrator. <note type="note">This flag MUST be used only
/// with a forest trust record type of ForestTrustDomainInfo.</note>
/// </summary>
LSA_NB_DISABLED_ADMIN = 0x00000004,
/// <summary>The domain information trust record is disabled due to a conflict.<note type="note">This flag MUST be used only with
/// a forest trust record type of ForestTrustDomainInfo.</note></summary>
/// <summary>
/// The domain information trust record is disabled due to a conflict. <note type="note">This flag MUST be used only with a
/// forest trust record type of ForestTrustDomainInfo.</note>
/// </summary>
LSA_NB_DISABLED_CONFLICT = 0x00000008,
/// <summary>The domain information trust record is disabled.<note type="note">This set of flags is reserved; for current and
/// future reasons, the trust is disabled.</note></summary>
/// <summary>
/// The domain information trust record is disabled. <note type="note">This set of flags is reserved; for current and future
/// reasons, the trust is disabled.</note>
/// </summary>
LSA_FTRECORD_DISABLED_REASONS = 0x0000FFFF,
}
@ -208,32 +224,48 @@ namespace Vanara.PInvoke
}
/// <summary>
/// The LsaAddAccountRights function assigns one or more privileges to an account. If the account does not exist, LsaAddAccountRights
/// creates it.
/// The <c>LsaAddAccountRights</c> function assigns one or more privileges to an account. If the account does not exist,
/// <c>LsaAddAccountRights</c> creates it.
/// </summary>
/// <param name="PolicyHandle">
/// A handle to a Policy object. The handle must have the POLICY_LOOKUP_NAMES access right. If the account identified by the
/// AccountSid parameter does not exist, the handle must have the POLICY_CREATE_ACCOUNT access right. For more information, see
/// Opening a Policy Object Handle.
/// </param>
/// <param name="pSID">Pointer to the SID of the account to which the function assigns privileges.</param>
/// <param name="AccountSid">Pointer to the SID of the account to which the function assigns privileges.</param>
/// <param name="UserRights">
/// Pointer to an array of strings. Each string contains the name of a privilege to add to the account. For a list of privilege
/// names, see Privilege Constants.
/// Pointer to an array of LSA_UNICODE_STRING structures. Each structure contains the name of a privilege to add to the account. For
/// a list of privilege names, see Privilege Constants.
/// </param>
/// <param name="CountOfRights">Specifies the number of elements in the UserRights array.</param>
/// <returns>
/// 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.
/// <para>If the function succeeds, the return value is STATUS_SUCCESS.</para>
/// <para>
/// If the function fails, the return value is an NTSTATUS code, which can be the following value or one of the LSA Policy Function
/// Return Values.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>STATUS_NO_SUCH_PRIVILEGE</term>
/// <term>One of the privilege names is not valid.</term>
/// </item>
/// </list>
/// <para>You can use the LsaNtStatusToWinError function to convert the NTSTATUS code to a Windows error code.</para>
/// </returns>
[DllImport(Lib.AdvApi32, ExactSpelling = true), SuppressUnmanagedCodeSecurity]
[PInvokeData("ntsecapi.h", MSDNShortId = "ms721786")]
public static extern uint LsaAddAccountRights(
LSA_HANDLE PolicyHandle,
PSID pSID,
[In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringArrayMarshaler))]
string[] UserRights,
int CountOfRights);
/// <remarks>
/// <para>If you specify privileges already granted to the account, they are ignored.</para>
/// <para>For an example that demonstrates calling this function, see Managing Account Permissions.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-lsaaddaccountrights NTSTATUS LsaAddAccountRights(
// LSA_HANDLE PolicyHandle, PSID AccountSid, PLSA_UNICODE_STRING UserRights, ULONG CountOfRights );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("ntsecapi.h", MSDNShortId = "66b78404-02c2-48e9-92c3-d27b68f77c23")]
public static extern NTStatus LsaAddAccountRights(LSA_HANDLE PolicyHandle, PSID AccountSid,
[In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringArrayMarshaler))] string[] UserRights, uint CountOfRights);
/// <summary>Undocumented function for creating an account.</summary>
/// <param name="PolicyHandle">A handle to a Policy object. For more information, see Opening a Policy Object Handle.</param>
@ -247,7 +279,7 @@ namespace Vanara.PInvoke
/// </returns>
[PInvokeData("ntlsa.h")]
[DllImport(Lib.AdvApi32, ExactSpelling = true)]
public static extern uint LsaCreateAccount(LSA_HANDLE PolicyHandle, PSID AccountSid, LsaAccountAccessMask DesiredAccess, out SafeLSA_HANDLE AccountHandle);
public static extern NTStatus LsaCreateAccount(LSA_HANDLE PolicyHandle, PSID AccountSid, LsaAccountAccessMask DesiredAccess, out SafeLSA_HANDLE AccountHandle);
/// <summary>The <c>LsaCreateTrustedDomainEx</c> function establishes a new trusted domain by creating a new TrustedDomain object.</summary>
/// <param name="PolicyHandle">
@ -356,7 +388,7 @@ namespace Vanara.PInvoke
// 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 uint LsaEnumerateAccountRights(
public static extern NTStatus LsaEnumerateAccountRights(
LSA_HANDLE PolicyHandle,
PSID AccountSid,
out SafeLsaMemoryHandle UserRights,
@ -377,7 +409,7 @@ namespace Vanara.PInvoke
var winErr = LsaNtStatusToWinError(ret);
if (winErr == Win32Error.ERROR_FILE_NOT_FOUND) return new string[0];
winErr.ThrowIfFailed();
return mem.DangerousGetHandle().ToIEnum<LSA_UNICODE_STRING>((int)cnt).Select(u => (string)u.ToString().Clone());
return mem.DangerousGetHandle().ToIEnum<LSA_UNICODE_STRING>((int)cnt).Select(u => (string)u.ToString().Clone()).ToArray();
}
/// <summary>
@ -441,9 +473,9 @@ namespace Vanara.PInvoke
[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 uint LsaEnumerateAccountsWithUserRight(
public static extern NTStatus LsaEnumerateAccountsWithUserRight(
LSA_HANDLE PolicyHandle,
[In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringMarshaler))] string UserRight,
[In, Optional, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringMarshaler))] string UserRight,
out SafeLsaMemoryHandle Buffer,
out int CountReturned);
@ -463,13 +495,12 @@ namespace Vanara.PInvoke
/// </para>
/// </param>
/// <returns>An enumeration of security identifiers (SID) of accounts that holds the specified privilege.</returns>
public static IEnumerable<PSID> LsaEnumerateAccountsWithUserRight(LSA_HANDLE PolicyHandle, string UserRights)
public static IEnumerable<PSID> LsaEnumerateAccountsWithUserRight(LSA_HANDLE PolicyHandle, [Optional] string UserRights)
{
var ret = LsaEnumerateAccountsWithUserRight(PolicyHandle, UserRights, out var mem, out var cnt);
if (ret == NTStatus.STATUS_NO_MORE_ENTRIES) return new PSID[0];
var wret = LsaNtStatusToWinError(ret);
wret.ThrowIfFailed();
return mem.DangerousGetHandle().ToIEnum<LSA_ENUMERATION_INFORMATION>(cnt).Select(u => u.Sid);
LsaNtStatusToWinError(ret).ThrowIfFailed();
return mem.DangerousGetHandle().ToIEnum<LSA_ENUMERATION_INFORMATION>(cnt).Select(u => u.Sid).ToArray();
}
/// <summary>
@ -695,15 +726,13 @@ namespace Vanara.PInvoke
[PInvokeData("ntsecapi.h", MSDNShortId = "4a203bff-c3e1-4d95-b556-617dc8c2e8c2")]
public static extern NTStatus LsaEnumerateTrustedDomainsEx(LSA_HANDLE PolicyHandle, ref LSA_ENUMERATION_HANDLE EnumerationContext, out SafeLsaMemoryHandle Buffer, uint PreferedMaximumLength, out uint CountReturned);
/// <summary>Gets system access for an account.</summary>
/// <summary>[Undocumented] Gets system access for an account.</summary>
/// <param name="AccountHandle">The account handle.</param>
/// <param name="SystemAccess">The system access.</param>
/// <returns>
/// <para>If the function succeeds, the function returns one of the following <c>NTSTATUS</c> values.</para>
/// </returns>
/// <returns>If the function succeeds, the function returns one of the following <c>NTSTATUS</c> values.</returns>
[PInvokeData("ntlsa.h")]
[DllImport(Lib.AdvApi32, ExactSpelling = true)]
public static extern uint LsaGetSystemAccessAccount(LSA_HANDLE AccountHandle, out int SystemAccess);
public static extern NTStatus LsaGetSystemAccessAccount(LSA_HANDLE AccountHandle, out int SystemAccess);
/// <summary>
/// <para>
@ -1276,34 +1305,29 @@ namespace Vanara.PInvoke
// 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 uint LsaLookupSids2(
public static extern NTStatus LsaLookupSids2(
LSA_HANDLE PolicyHandle,
LsaLookupSidsFlags LookupOptions,
uint Count,
[In, MarshalAs(UnmanagedType.LPArray)] IntPtr[] Sids,
[In, MarshalAs(UnmanagedType.LPArray)] PSID[] Sids,
out SafeLsaMemoryHandle ReferencedDomains,
out SafeLsaMemoryHandle Names);
/// <summary>
/// <para>The <c>LsaNtStatusToWinError</c> function converts an NTSTATUS code returned by an LSA function to a Windows error code.</para>
/// The <c>LsaNtStatusToWinError</c> function converts an NTSTATUS code returned by an LSA function to a Windows error code.
/// </summary>
/// <param name="Status">
/// <para>An NTSTATUS code returned by an LSA function call. This value will be converted to a System error code.</para>
/// </param>
/// <param name="Status">An NTSTATUS code returned by an LSA function call. This value will be converted to a System error code.</param>
/// <returns>
/// <para>
/// 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.
/// </para>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/ntsecapi/nf-ntsecapi-lsantstatustowinerror ULONG LsaNtStatusToWinError(
// 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 uint LsaNtStatusToWinError(NTSTATUS Status);
public static extern Win32Error LsaNtStatusToWinError(uint Status);
public static extern Win32Error LsaNtStatusToWinError(NTStatus Status);
/// <summary>Undocumented. Opens an account.</summary>
/// <summary>[Undocumented] Opens an account.</summary>
/// <param name="PolicyHandle">The policy handle.</param>
/// <param name="AccountSid">The account sid.</param>
/// <param name="DesiredAccess">The desired access.</param>
@ -1311,7 +1335,7 @@ namespace Vanara.PInvoke
/// <returns>NTSTATUS</returns>
[PInvokeData("ntlsa.h")]
[DllImport(Lib.AdvApi32, ExactSpelling = true)]
public static extern uint LsaOpenAccount(LSA_HANDLE PolicyHandle, PSID AccountSid, LsaAccountAccessMask DesiredAccess, out SafeLSA_HANDLE AccountHandle);
public static extern NTStatus LsaOpenAccount(LSA_HANDLE PolicyHandle, PSID AccountSid, LsaAccountAccessMask DesiredAccess, out SafeLSA_HANDLE AccountHandle);
/// <summary>
/// <para>The <c>LsaOpenPolicy</c> function opens a handle to the Policy object on a local or remote system.</para>
@ -1360,9 +1384,9 @@ namespace Vanara.PInvoke
[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 uint LsaOpenPolicy(
public static extern NTStatus LsaOpenPolicy(
[In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringMarshaler))] string SystemName,
ref LSA_OBJECT_ATTRIBUTES ObjectAttributes,
in LSA_OBJECT_ATTRIBUTES ObjectAttributes,
LsaPolicyRights DesiredAccess,
out SafeLSA_HANDLE PolicyHandle);
@ -1380,10 +1404,10 @@ namespace Vanara.PInvoke
/// opens the Policy object on the local system.
/// </param>
/// <returns>A pointer to an LSA_HANDLE variable that receives a handle to the Policy object.</returns>
[PInvokeData("ntsecapi.h", MSDNShortId = "361bc962-1e97-4606-a835-cbce37692c55")]
public static SafeLSA_HANDLE LsaOpenPolicy(LsaPolicyRights DesiredAccess, string SystemName = null)
{
var oa = LSA_OBJECT_ATTRIBUTES.Empty;
LsaNtStatusToWinError(LsaOpenPolicy(SystemName, ref oa, DesiredAccess, out var handle)).ThrowIfFailed();
LsaNtStatusToWinError(LsaOpenPolicy(SystemName, LSA_OBJECT_ATTRIBUTES.Empty, DesiredAccess, out var handle)).ThrowIfFailed();
return handle;
}
@ -1484,7 +1508,7 @@ namespace Vanara.PInvoke
// 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 IntPtr Buffer);
public static extern NTStatus LsaQueryDomainInformationPolicy(LSA_HANDLE PolicyHandle, POLICY_DOMAIN_INFORMATION_CLASS InformationClass, out SafeLsaMemoryHandle Buffer);
/// <summary>
/// The <c>LsaQueryForestTrustInformation</c> function retrieves forest trust information for the specified Local Security Authority
@ -1839,13 +1863,13 @@ namespace Vanara.PInvoke
[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 uint LsaRemoveAccountRights(
public static extern NTStatus LsaRemoveAccountRights(
LSA_HANDLE PolicyHandle,
PSID AccountSid,
[MarshalAs(UnmanagedType.Bool)] bool AllRights,
[In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringArrayMarshaler))]
string[] UserRights,
int CountOfRights);
uint CountOfRights);
/// <summary>Do not use the LSA private data functions. Instead, use the CryptProtectData and CryptUnprotectData functions.</summary>
/// <param name="PolicyHandle">
@ -1905,7 +1929,10 @@ namespace Vanara.PInvoke
// 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, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringMarshaler))] out string PrivateData);
public static extern NTStatus LsaRetrievePrivateData(LSA_HANDLE PolicyHandle, [In, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringMarshaler))] string KeyName,
out SafeLsaMemoryHandle PrivateData);
//[Out, MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(LsaUnicodeStringMarshaler))] out string PrivateData);
/// <summary>The <c>LsaSetDomainInformationPolicy</c> function sets domain information to the Policyobject.</summary>
/// <param name="PolicyHandle">A handle to the Policy object for the system.</param>
@ -2098,7 +2125,7 @@ namespace Vanara.PInvoke
/// </returns>
[PInvokeData("ntlsa.h")]
[DllImport(Lib.AdvApi32, ExactSpelling = true)]
public static extern uint LsaSetSystemAccessAccount(LSA_HANDLE AccountHandle, int SystemAccess);
public static extern NTStatus LsaSetSystemAccessAccount(LSA_HANDLE AccountHandle, int SystemAccess);
/// <summary>The <c>LsaSetTrustedDomainInfoByName</c> function sets values for a TrustedDomain object.</summary>
/// <param name="PolicyHandle">
@ -2293,7 +2320,7 @@ namespace Vanara.PInvoke
[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 uint LsaClose(LSA_HANDLE ObjectHandle);
private static extern NTStatus LsaClose(LSA_HANDLE ObjectHandle);
/// <summary>
/// <para>
@ -2329,13 +2356,13 @@ namespace Vanara.PInvoke
[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 uint LsaFreeMemory(IntPtr Buffer);
private static extern NTStatus LsaFreeMemory(IntPtr Buffer);
/// <summary>Provides a handle to an LSA enumeration.</summary>
[StructLayout(LayoutKind.Sequential)]
public struct LSA_ENUMERATION_HANDLE : IHandle
{
private IntPtr handle;
private readonly IntPtr handle;
/// <summary>Initializes a new instance of the <see cref="LSA_ENUMERATION_HANDLE"/> struct.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
@ -2599,7 +2626,7 @@ namespace Vanara.PInvoke
[StructLayout(LayoutKind.Sequential)]
public struct LSA_HANDLE : IHandle
{
private IntPtr handle;
private readonly IntPtr handle;
/// <summary>Initializes a new instance of the <see cref="LSA_HANDLE"/> struct.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
@ -2733,7 +2760,7 @@ namespace Vanara.PInvoke
public LSA_UNICODE_STRING Name;
/// <summary>Pointer to the SID of the domain.</summary>
public IntPtr Sid;
public PSID Sid;
}
/// <summary>
@ -2762,7 +2789,7 @@ namespace Vanara.PInvoke
public StrPtrUni Buffer;
/* REMOVED TO AVOID MEMORY LEAK
*
*
/// <summary>Initializes a new instance of the <see cref="LSA_UNICODE_STRING"/> struct from a string.</summary>
/// <param name="s">The string value.</param>
/// <exception cref="System.ArgumentException">String exceeds 32Kb of data.</exception>
@ -2796,7 +2823,7 @@ namespace Vanara.PInvoke
/// <summary>Performs an implicit conversion from <see cref="LSA_UNICODE_STRING"/> to <see cref="string"/>.</summary>
/// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator string(LSA_UNICODE_STRING value) => (string)value.Buffer;
public static implicit operator string(LSA_UNICODE_STRING value) => value.Buffer;
}
/// <summary>Smart wrapper for LSA_FOREST_TRUST_INFORMATION.</summary>
@ -2925,7 +2952,9 @@ namespace Vanara.PInvoke
Excluded = exclude;
}
/// <summary>Gets or sets a value indicating whether this <see cref="LsaForestTrustTopLevelName"/> contains an excluded top-level name..</summary>
/// <summary>
/// Gets or sets a value indicating whether this <see cref="LsaForestTrustTopLevelName"/> contains an excluded top-level name..
/// </summary>
/// <value><c>true</c> if excluded; otherwise, <c>false</c> to include.</value>
public bool Excluded { get; set; }
@ -2965,29 +2994,37 @@ namespace Vanara.PInvoke
public static implicit operator LSA_HANDLE(SafeLSA_HANDLE h) => h.handle;
/// <inheritdoc/>
protected override bool InternalReleaseHandle() => LsaClose(this) == 0;
protected override bool InternalReleaseHandle() => LsaClose(this).Succeeded;
}
/// <summary>Provides a <see cref="SafeHandle"/> for <see cref="LSA_UNICODE_STRING"/> that manages its own memory allocations.</summary>
public class SafeLSA_UNICODE_STRING : SafeHANDLE
{
/// <summary>
/// Initializes a new instance of the <see cref="SafeLSA_UNICODE_STRING"/> class.
/// </summary>
/// <summary>Initializes a new instance of the <see cref="SafeLSA_UNICODE_STRING"/> class.</summary>
/// <param name="value">The value of the string to assign.</param>
public SafeLSA_UNICODE_STRING(string value) : base(IntPtr.Zero, true)
{
Buffer = value;
}
public SafeLSA_UNICODE_STRING(string value) : base(IntPtr.Zero, true) => Buffer = value;
/// <summary>Initializes a new instance of the <see cref="SafeLSA_UNICODE_STRING"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle"><see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeLSA_UNICODE_STRING(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeLSA_UNICODE_STRING"/> class.</summary>
private SafeLSA_UNICODE_STRING() : base() { }
/// <summary>The string value.</summary>
public string Buffer
{
get => LsaUnicodeStringMarshaler.MarshalPtr(handle);
set
{
Close();
SetHandle(LsaUnicodeStringMarshaler.MarshalValue(value));
}
}
/// <summary>
/// Specifies the length, in bytes, of the string pointed to by the Buffer member, not including the terminating null character,
/// if any.
@ -3000,32 +3037,21 @@ namespace Vanara.PInvoke
/// </summary>
public short MaximumLength => IsInvalid ? (short)0 : Marshal.ReadInt16(handle, 2);
/// <summary>The string value.</summary>
public string Buffer
{
get => LsaUnicodeStringMarshaler.MarshalPtr(handle);
set
{
Close();
SetHandle(LsaUnicodeStringMarshaler.MarshalValue(value));
}
}
/// <summary>Performs an implicit conversion from <see cref="SafeLSA_UNICODE_STRING"/> to <see cref="LSA_UNICODE_STRING"/>.</summary>
/// <param name="h">The safe handle instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator LSA_UNICODE_STRING(SafeLSA_UNICODE_STRING h) => h.handle.ToStructure<LSA_UNICODE_STRING>();
/// <summary>Performs an implicit conversion from <see cref="SafeLSA_UNICODE_STRING"/> to <see cref="System.String"/>.</summary>
/// <param name="h">The <see cref="SafeLSA_UNICODE_STRING"/> instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator string(SafeLSA_UNICODE_STRING h) => h.Buffer;
/// <summary>Performs an implicit conversion from <see cref="System.String"/> to <see cref="SafeLSA_UNICODE_STRING"/>.</summary>
/// <param name="val">The string value.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator SafeLSA_UNICODE_STRING(string val) => new SafeLSA_UNICODE_STRING(val);
/// <summary>Performs an implicit conversion from <see cref="SafeLSA_UNICODE_STRING"/> to <see cref="System.String"/>.</summary>
/// <param name="h">The <see cref="SafeLSA_UNICODE_STRING"/> instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator string(SafeLSA_UNICODE_STRING h) => h.Buffer;
/// <inheritdoc/>
protected override bool InternalReleaseHandle()
{
@ -3051,7 +3077,7 @@ namespace Vanara.PInvoke
private SafeLsaMemoryHandle() : base() { }
/// <inheritdoc/>
protected override bool InternalReleaseHandle() => LsaFreeMemory(handle) == 0;
protected override bool InternalReleaseHandle() => LsaFreeMemory(handle).Succeeded;
}
/// <summary>Base class for other LSA memory handles.</summary>
@ -3098,7 +3124,9 @@ namespace Vanara.PInvoke
}
}
/// <summary>A <see cref="SafeHandle"/> for values that must be freed using the <see cref="Secur32.LsaFreeReturnBuffer(IntPtr)"/> function.</summary>
/// <summary>
/// A <see cref="SafeHandle"/> for values that must be freed using the <see cref="Secur32.LsaFreeReturnBuffer(IntPtr)"/> function.
/// </summary>
public sealed class SafeLsaReturnBufferHandle : SafeLsaMemoryHandleBase
{
/// <summary>Initializes a new instance of the <see cref="SafeLsaReturnBufferHandle"/> class.</summary>
@ -3140,7 +3168,7 @@ namespace Vanara.PInvoke
var strSz = uma.Sum(s => s.length + 2);
var result = Marshal.AllocCoTaskMem(sz * a.Length + strSz);
var strPtr = result.Offset(sz * a.Length);
for (int i = 0; i < uma.Length; i++)
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);
@ -3187,6 +3215,8 @@ namespace Vanara.PInvoke
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;
@ -3204,8 +3234,6 @@ namespace Vanara.PInvoke
}
return mem;
}
internal static string MarshalPtr(IntPtr ptr) => ptr == IntPtr.Zero ? null : StringHelper.GetString(ptr.Offset(4), CharSet.Unicode, Marshal.ReadInt16(ptr));
}
}
}
}

View File

@ -1,10 +1,5 @@
using System;
using System.Collections.Generic;
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;
@ -21,12 +16,15 @@ namespace Vanara.PInvoke
public enum POLICY_DOMAIN_INFORMATION_CLASS
{
/// <summary/>
[CorrespondingType(typeof(POLICY_DOMAIN_QUALITY_OF_SERVICE_INFO), CorrespondingAction.Set)]
PolicyDomainQualityOfServiceInformation = 1,
/// <summary>The information is for Encrypting File System.</summary>
[CorrespondingType(typeof(POLICY_DOMAIN_EFS_INFO))]
PolicyDomainEfsInformation,
/// <summary>The information is for a Kerberos ticket.</summary>
[CorrespondingType(typeof(POLICY_DOMAIN_KERBEROS_TICKET_INFO))]
PolicyDomainKerberosTicketInformation,
}
@ -43,47 +41,59 @@ namespace Vanara.PInvoke
public enum POLICY_INFORMATION_CLASS
{
/// <summary>This value is obsolete.</summary>
[Obsolete]
PolicyAuditLogInformation = 1,
/// <summary>
/// Query or set the auditing rules of the system. You can enable or disable auditing and specify the types of events that are
/// audited. Use the POLICY_AUDIT_EVENTS_INFO structure.
/// </summary>
[CorrespondingType(typeof(POLICY_AUDIT_EVENTS_INFO))]
PolicyAuditEventsInformation,
/// <summary>This value is obsolete. Use the PolicyDnsDomainInformation value instead.</summary>
[Obsolete]
PolicyPrimaryDomainInformation,
/// <summary>This value is obsolete.</summary>
[Obsolete]
PolicyPdAccountInformation,
/// <summary>Query or set the name and SID of the account domain of the system. Use the POLICY_ACCOUNT_DOMAIN_INFO structure.</summary>
[CorrespondingType(typeof(POLICY_ACCOUNT_DOMAIN_INFO))]
PolicyAccountDomainInformation,
/// <summary>Query or set the role of an LSA server. Use the POLICY_LSA_SERVER_ROLE_INFO structure.</summary>
[CorrespondingType(typeof(POLICY_LSA_SERVER_ROLE_INFO))]
PolicyLsaServerRoleInformation,
/// <summary>This value is obsolete.</summary>
[Obsolete]
PolicyReplicaSourceInformation,
/// <summary>This value is obsolete.</summary>
[Obsolete]
PolicyDefaultQuotaInformation,
/// <summary>
/// Query or set information about the creation time and last modification of the LSA database. Use the POLICY_MODIFICATION_INFO structure.
/// </summary>
[CorrespondingType(typeof(POLICY_MODIFICATION_INFO))]
PolicyModificationInformation,
/// <summary>This value is obsolete.</summary>
[Obsolete]
PolicyAuditFullSetInformation,
/// <summary>This value is obsolete.</summary>
[Obsolete]
PolicyAuditFullQueryInformation,
/// <summary>
/// Query or set Domain Name System (DNS) information about the account domain associated with a Policy object. Use the
/// POLICY_DNS_DOMAIN_INFO structure.
/// </summary>
[CorrespondingType(typeof(POLICY_DNS_DOMAIN_INFO))]
PolicyDnsDomainInformation,
/// <summary/>
@ -96,6 +106,53 @@ namespace Vanara.PInvoke
PolicyMachineAccountInformation,
}
/// <summary>
/// The <c>POLICY_LSA_SERVER_ROLE</c> enumeration type defines values that indicate the role of an LSA server. The
/// LsaQueryInformationPolicy and LsaSetInformationPolicy functions use this enumeration type when their InformationClass parameters
/// are set to <c>PolicyLsaServerRoleInformation</c>.
/// </summary>
// https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/ne-ntsecapi-policy_lsa_server_role typedef enum
// _POLICY_LSA_SERVER_ROLE { PolicyServerRoleBackup, PolicyServerRolePrimary } POLICY_LSA_SERVER_ROLE, *PPOLICY_LSA_SERVER_ROLE;
[PInvokeData("ntsecapi.h", MSDNShortId = "a2bcc380-8873-436b-a0d6-e4deb23669bb")]
public enum POLICY_LSA_SERVER_ROLE
{
/// <summary>Indicates a backup LSA server.</summary>
PolicyServerRoleBackup = 2,
/// <summary>Indicates a primary LSA server, a workstation, or a standalone computer.</summary>
PolicyServerRolePrimary,
}
/// <summary>[Undocumented] Used by POLICY_DOMAIN_QUALITY_OF_SERVICE_INFO.</summary>
[PInvokeData("ntsecapi.h")]
public enum POLICY_QOS : uint
{
POLICY_QOS_SCHANNEL_REQUIRED = 0x00000001,
POLICY_QOS_OUTBOUND_INTEGRITY = 0x00000002,
POLICY_QOS_OUTBOUND_CONFIDENTIALITY = 0x00000004,
POLICY_QOS_INBOUND_INTEGRITY = 0x00000008,
POLICY_QOS_INBOUND_CONFIDENTIALITY = 0x00000010,
POLICY_QOS_ALLOW_LOCAL_ROOT_CERT_STORE = 0x00000020,
POLICY_QOS_RAS_SERVER_ALLOWED = 0x00000040,
POLICY_QOS_DHCP_SERVER_ALLOWED = 0x00000080,
}
/// <summary>
/// The <c>POLICY_SERVER_ENABLE_STATE</c> enumeration represents the state of the LSA server—that is, whether it is enabled or
/// disabled. Some operations may only be performed on an enabled LSA server.
/// </summary>
// https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/ne-ntsecapi-policy_server_enable_state typedef enum
// _POLICY_SERVER_ENABLE_STATE { PolicyServerEnabled, PolicyServerDisabled } POLICY_SERVER_ENABLE_STATE, *PPOLICY_SERVER_ENABLE_STATE;
[PInvokeData("ntsecapi.h", MSDNShortId = "aae5875e-ca55-4571-a9a4-684280ae8aa0")]
public enum POLICY_SERVER_ENABLE_STATE
{
/// <summary>The LSA server is enabled.</summary>
PolicyServerEnabled = 2,
/// <summary>The LSA server is disabled.</summary>
PolicyServerDisabled,
}
/// <summary>Indicates the attributes of a trust relationship.</summary>
[PInvokeData("ntsecapi.h", MSDNShortId = "acf9a2b5-f301-4e6a-a515-df338658ad56")]
[Flags]
@ -179,7 +236,7 @@ namespace Vanara.PInvoke
{
/// <summary>Query or set the name of a trusted domain. Use the TRUSTED_DOMAIN_NAME_INFO structure.</summary>
[CorrespondingType(typeof(TRUSTED_DOMAIN_NAME_INFO))]
TrustedDomainNameInformation,
TrustedDomainNameInformation = 1,
/// <summary>This value is obsolete.</summary>
TrustedControllersInformation,
@ -369,6 +426,237 @@ namespace Vanara.PInvoke
public IntPtr AuthInfo;
}
/// <summary>
/// The <c>POLICY_ACCOUNT_DOMAIN_INFO</c> structure is used to set and query the name and SID of the system's account domain. The
/// LsaQueryInformationPolicy and LsaSetInformationPolicy functions use this structure when their InformationClass parameters are set
/// to <c>PolicyAccountDomainInformation</c>.
/// </summary>
// https://docs.microsoft.com/en-us/windows/win32/api/lsalookup/ns-lsalookup-policy_account_domain_info typedef struct
// _POLICY_ACCOUNT_DOMAIN_INFO { LSA_UNICODE_STRING DomainName; PSID DomainSid; } POLICY_ACCOUNT_DOMAIN_INFO, *PPOLICY_ACCOUNT_DOMAIN_INFO;
[PInvokeData("lsalookup.h", MSDNShortId = "0e38ac5f-40db-405d-9394-b6bcb7c652b5")]
[StructLayout(LayoutKind.Sequential)]
public struct POLICY_ACCOUNT_DOMAIN_INFO
{
/// <summary>An LSA_UNICODE_STRING structure that specifies the name of the account domain.</summary>
public LSA_UNICODE_STRING DomainName;
/// <summary>Pointer to the SID of the account domain.</summary>
public PSID DomainSid;
}
/// <summary>
/// The <c>POLICY_AUDIT_EVENTS_INFO</c> structure is used to set and query the system's auditing rules. The LsaQueryInformationPolicy
/// and LsaSetInformationPolicy functions use this structure when their InformationClass parameters are set to <c>PolicyAuditEventsInformation</c>.
/// </summary>
/// <remarks>
/// LSA Policy defines a mask for the valid event auditing options. The POLICY_AUDIT_EVENT_MASK mask evaluates to <c>TRUE</c> if it
/// is set equal to any of the preceding event auditing options.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-policy_audit_events_info typedef struct
// _POLICY_AUDIT_EVENTS_INFO { BOOLEAN AuditingMode; PPOLICY_AUDIT_EVENT_OPTIONS EventAuditingOptions; ULONG MaximumAuditEventCount;
// } POLICY_AUDIT_EVENTS_INFO, *PPOLICY_AUDIT_EVENTS_INFO;
[PInvokeData("ntsecapi.h", MSDNShortId = "3442e5e5-78cf-4bda-ba11-0f51ee40df16")]
[StructLayout(LayoutKind.Sequential)]
public struct POLICY_AUDIT_EVENTS_INFO
{
/// <summary>
/// <para>Indicates whether auditing is enabled.</para>
/// <para>
/// If this flag is <c>TRUE</c>, the system generates audit records according to the event auditing options specified in the
/// <c>EventAuditingOptions</c> member.
/// </para>
/// <para>
/// If this flag is <c>FALSE</c>, the system does not generate audit records. However, note that set operations update the event
/// auditing options as specified in the <c>EventAuditingOptions</c> member even when <c>AuditingMode</c> is <c>FALSE</c>.
/// </para>
/// </summary>
[MarshalAs(UnmanagedType.U1)]
public bool AuditingMode;
/// <summary>
/// <para>
/// Pointer to an array of POLICY_AUDIT_EVENT_OPTIONS variables. Each element in this array specifies the auditing options for an
/// audit event type. The index of each array element corresponds to an audit event type value in the POLICY_AUDIT_EVENT_TYPE
/// enumeration type.
/// </para>
/// <para>
/// Each POLICY_AUDIT_EVENT_OPTIONS variable in the array can specify the following auditing options. You can also combine the
/// success and failure options, POLICY_AUDIT_EVENT_SUCCESS and POLICY_AUDIT_EVENT_FAILURE.
/// </para>
/// <para>
/// When LSASetInformationPolicy is called to change the audit policy, any new POLICY_AUDIT_EVENT_OPTIONS array elements are
/// added to any existing audit options. Adding a new POLICY_AUDIT_EVENT_OPTIONS element combined with the
/// POLICY_AUDIT_EVENT_NONE audit option cancels all previous audit options and begins a new set of options.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>POLICY_AUDIT_EVENT_UNCHANGED</term>
/// <term>
/// For set operations, specify this value to leave the current options unchanged. For read operations, this value means that no
/// audit records for this type are generated. This is the default.
/// </term>
/// </item>
/// <item>
/// <term>POLICY_AUDIT_EVENT_SUCCESS</term>
/// <term>Generate audit records for successful events of this type.</term>
/// </item>
/// <item>
/// <term>POLICY_AUDIT_EVENT_FAILURE</term>
/// <term>Generate audit records for failed attempts to cause an event of this type to occur.</term>
/// </item>
/// <item>
/// <term>POLICY_AUDIT_EVENT_NONE</term>
/// <term>Do not generate audit records for events of this type.</term>
/// </item>
/// </list>
/// </summary>
public IntPtr EventAuditingOptions;
/// <summary>
/// Specifies the number of elements in the <c>EventAuditingOptions</c> array. For set operations, if this value is less than the
/// number of audit event types supported by the system, the system does not change the auditing options for event types with
/// indexes equal to or higher than the value specified in <c>MaximumAuditEventCount</c>.
/// </summary>
public uint MaximumAuditEventCount;
}
/// <summary>
/// The <c>POLICY_DNS_DOMAIN_INFO</c> structure is used to set and query Domain Name System (DNS) information about the primary
/// domain associated with a Policy object. The LsaQueryInformationPolicy and LsaSetInformationPolicy functions use this structure
/// when their InformationClass parameters are set to <c>PolicyDnsDomainInformation</c>.
/// </summary>
/// <remarks>
/// <para>
/// The <c>POLICY_DNS_DOMAIN_INFO</c> structure is an extended version of the POLICY_PRIMARY_DOMAIN_INFO structure. Setting
/// <c>POLICY_DNS_DOMAIN_INFO</c> information will overwrite the corresponding values in the <c>POLICY_PRIMARY_DOMAIN_INFO</c> (name
/// and SID), and vice versa.
/// </para>
/// <para>
/// If the computer associated with the Policy object is not a member of a domain, all structure members except <c>Name</c> are
/// <c>NULL</c> or zero.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/lsalookup/ns-lsalookup-policy_dns_domain_info typedef struct
// _POLICY_DNS_DOMAIN_INFO { LSA_UNICODE_STRING Name; LSA_UNICODE_STRING DnsDomainName; LSA_UNICODE_STRING DnsForestName; GUID
// DomainGuid; PSID Sid; } POLICY_DNS_DOMAIN_INFO, *PPOLICY_DNS_DOMAIN_INFO;
[PInvokeData("lsalookup.h", MSDNShortId = "5b2879cf-e0dc-4844-bfe8-bf45460285f1")]
[StructLayout(LayoutKind.Sequential)]
public struct POLICY_DNS_DOMAIN_INFO
{
/// <summary>
/// An LSA_UNICODE_STRING structure that specifies the name of the primary domain. This is the same as the primary domain name in
/// the POLICY_PRIMARY_DOMAIN_INFO structure.
/// </summary>
public LSA_UNICODE_STRING Name;
/// <summary>An LSA_UNICODE_STRING structure that specifies the DNS name of the primary domain.</summary>
public LSA_UNICODE_STRING DnsDomainName;
/// <summary>
/// An LSA_UNICODE_STRING structure that specifies the DNS forest name of the primary domain. This is the DNS name of the domain
/// at the root of the enterprise.
/// </summary>
public LSA_UNICODE_STRING DnsForestName;
/// <summary>A GUID structure that contains the GUID of the primary domain.</summary>
public Guid DomainGuid;
/// <summary>
/// Pointer to the SID of the primary domain. This is the same as the primary domain SID in the POLICY_PRIMARY_DOMAIN_INFO structure.
/// </summary>
public PSID Sid;
}
/// <summary>[Undocumented] Used by <see cref="POLICY_DOMAIN_INFORMATION_CLASS.PolicyDomainEfsInformation"/>.</summary>
[PInvokeData("ntsecapi.h")]
[StructLayout(LayoutKind.Sequential)]
public struct POLICY_DOMAIN_EFS_INFO
{
/// <summary>Length of the EFS Information blob</summary>
public uint InfoLength;
/// <summary>Efs blob data</summary>
public IntPtr EfsBlob;
}
/// <summary>[Undocumented] Used by <see cref="POLICY_DOMAIN_INFORMATION_CLASS.PolicyDomainKerberosTicketInformation"/>.</summary>
[PInvokeData("ntsecapi.h")]
[StructLayout(LayoutKind.Sequential)]
public struct POLICY_DOMAIN_KERBEROS_TICKET_INFO
{
/// <summary>allowed ticket options (POLICY_KERBEROS_* flags )</summary>
public uint AuthenticationOptions;
/// <summary>Maximum lifetime for a service ticket</summary>
public FILETIME MaxServiceTicketAge;
/// <summary>Maximum lifetime for the initial ticket</summary>
public FILETIME MaxTicketAge;
/// <summary>Maximum cumulative age a renewable ticket can be with requring authentication</summary>
public FILETIME MaxRenewAge;
/// <summary>Maximum tolerance for synchronization of computer clocks</summary>
public FILETIME MaxClockSkew;
/// <summary>Reserved</summary>
public FILETIME Reserved;
}
/// <summary>[Undocumented] Used by <see cref="POLICY_DOMAIN_INFORMATION_CLASS.PolicyDomainQualityOfServiceInformation"/>.</summary>
[PInvokeData("ntsecapi.h")]
[StructLayout(LayoutKind.Sequential)]
public struct POLICY_DOMAIN_QUALITY_OF_SERVICE_INFO
{
/// <summary>Determines what specific QOS actions a machine should take</summary>
public POLICY_QOS QualityOfService;
}
/// <summary>
/// The <c>POLICY_LSA_SERVER_ROLE_INFO</c> structure is used to set and query the role of an LSA server. The
/// LsaQueryInformationPolicy and LsaSetInformationPolicy functions use this structure when their InformationClass parameters are set
/// to <c>PolicyLsaServerRoleInformation</c>.
/// </summary>
// https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-policy_lsa_server_role_info typedef struct
// _POLICY_LSA_SERVER_ROLE_INFO { POLICY_LSA_SERVER_ROLE LsaServerRole; } POLICY_LSA_SERVER_ROLE_INFO, *PPOLICY_LSA_SERVER_ROLE_INFO;
[PInvokeData("ntsecapi.h", MSDNShortId = "f66abe33-d8c8-45b8-9b94-d6890d786aaa")]
[StructLayout(LayoutKind.Sequential)]
public struct POLICY_LSA_SERVER_ROLE_INFO
{
/// <summary>
/// Specifies one of the values from the POLICY_LSA_SERVER_ROLE enumeration type to indicate a primary or backup LSA server.
/// </summary>
public POLICY_LSA_SERVER_ROLE LsaServerRole;
}
/// <summary>
/// The <c>POLICY_MODIFICATION_INFO</c> structure is used to query information about the creation time and last modification of the
/// LSA database. The LsaQueryInformationPolicy function uses this structure when its InformationClass parameter is set to PolicyModificationInformation.
/// </summary>
// https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-policy_modification_info typedef struct
// _POLICY_MODIFICATION_INFO { LARGE_INTEGER ModifiedId; LARGE_INTEGER DatabaseCreationTime; } POLICY_MODIFICATION_INFO, *PPOLICY_MODIFICATION_INFO;
[PInvokeData("ntsecapi.h", MSDNShortId = "ef4d1d1d-9b1b-4d67-80b8-2b548ec31a87")]
[StructLayout(LayoutKind.Sequential)]
public struct POLICY_MODIFICATION_INFO
{
/// <summary>
/// A LARGE_INTEGER structure containing a 64-bit unsigned integer that is incremented each time anything in the LSA database is
/// modified. This value is modified only on primary domain controllers.
/// </summary>
public long ModifiedId;
/// <summary>
/// A LARGE_INTEGER structure that indicates the date and time the LSA database was created. This is a UTC-based time that uses
/// the FILETIME format. On backup domain controllers, this value is replicated from the primary domain controller. For more
/// information about UTC-based time, see System Time.
/// </summary>
public FILETIME DatabaseCreationTime;
}
/// <summary>
/// <para>
/// The <c>TRUSTED_DOMAIN_AUTH_INFORMATION</c> structure is used to retrieve authentication information for a trusted domain. The
@ -500,7 +788,7 @@ namespace Vanara.PInvoke
/// Pointer to the security identifier (SID) of the trusted domain. For non-Microsoft trusted domains, this member can be <c>NULL</c>.
/// </para>
/// </summary>
public IntPtr Sid;
public PSID Sid;
/// <summary>
/// <para>A value that indicates the direction of the trust. This member can be one of the following values.</para>
@ -678,6 +966,5 @@ namespace Vanara.PInvoke
/// </summary>
public uint Offset;
}
}
}

View File

@ -11,94 +11,16 @@ namespace Vanara.PInvoke
{
public static partial class AdvApi32
{
/// <summary>Provides a <see cref="SafeHandle"/> for <see cref="PSID"/> that is disposed using <see cref="LocalFree"/>.</summary>
public class SafeLocalPSID : SafeHANDLE
{
/// <summary>Initializes a new instance of the <see cref="SafeLocalPSID"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeLocalPSID(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeLocalPSID"/> class.</summary>
private SafeLocalPSID() : base() { }
/// <summary>Performs an implicit conversion from <see cref="SafeLocalPSID"/> to <see cref="LocalPSID"/>.</summary>
/// <param name="h">The safe handle instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator PSID(SafeLocalPSID h) => h.handle;
/// <inheritdoc/>
protected override bool InternalReleaseHandle() => LocalFree(handle) == HLOCAL.NULL;
}
/// <summary>Provides an array of SID pointers whose memory is disposed after use.</summary>
/// <seealso cref="Vanara.PInvoke.SafeHANDLE"/>
/// <seealso cref="System.Collections.Generic.IEnumerable{Vanara.PInvoke.PSID}"/>
public class SafeLocalPSIDArray : SafeHANDLE, IEnumerable<PSID>
{
private List<SafeLocalPSID> items;
/// <summary>Initializes a new instance of the <see cref="SafeLocalPSID"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeLocalPSIDArray(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeLocalPSID"/> class.</summary>
private SafeLocalPSIDArray() : base() { }
/// <summary>Gets or sets the length of the array. This value must be set in order to interact with the elements.</summary>
/// <value>The length.</value>
public int Length
{
get => items?.Count ?? throw new InvalidOperationException("The length must be set before using this function.");
set
{
if (items != null) throw new InvalidOperationException("The length can only be set once.");
items = new List<SafeLocalPSID>(handle.ToIEnum<IntPtr>(value).Select(p => new SafeLocalPSID(p)));
}
}
/// <summary>Gets the <see cref="PSID"/> at the specified index.</summary>
/// <value>The <see cref="PSID"/>.</value>
/// <param name="index">The index.</param>
/// <returns>The PSID at the specified index.</returns>
/// <exception cref="InvalidOperationException">The length must be set before using this function.</exception>
public PSID this[int index] => items?[index] ?? throw new InvalidOperationException("The length must be set before using this function.");
/// <summary>Returns an enumerator that iterates through the collection.</summary>
/// <returns>A <see cref="IEnumerator{PSID}"/> that can be used to iterate through the collection.</returns>
public IEnumerator<PSID> GetEnumerator() => items.ConvertAll(p => (PSID)p).GetEnumerator();
/// <inheritdoc/>
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<SafeLocalPSID>)items).GetEnumerator();
/// <inheritdoc/>
protected override bool InternalReleaseHandle()
{
if (items != null)
foreach (var p in items)
p.Dispose();
return LocalFree(handle) == HLOCAL.NULL;
}
}
/// <summary>Class representation of the native SID structure.</summary>
/// <seealso cref="SafeHGlobalHandle"/>
public class SafePSID : SafeMemoryHandle<HeapMemoryMethods>, IEquatable<SafePSID>, IEquatable<PSID>, IEquatable<IntPtr>, ICloneable, ISecurityObject
public class SafePSID : SafeMemoryHandle<LocalMemoryMethods>, IEquatable<SafePSID>, IEquatable<PSID>, IEquatable<IntPtr>, ICloneable, ISecurityObject
{
/// <summary>Equivalent to a NULL pointer to a SID.</summary>
public static readonly SafePSID Null = new SafePSID(0);
/// <summary>A SID representing the Everyone Group (S-1-1-0).</summary>
public static readonly SafePSID Everyone = CreateWellKnown(WELL_KNOWN_SID_TYPE.WinWorldSid);
/// <summary>Initializes a new instance of the <see cref="SafePSID"/> class.</summary>
/// <param name="psid">The existing <see cref="SafePSID"/> instance to duplicate.</param>
public SafePSID(PSID psid) : base(GetLengthSid(psid)) => CopySid(Size, handle, psid);
public SafePSID(PSID psid) : base(psid.IsNull ? 0 : GetLengthSid(psid)) { if (!psid.IsNull) CopySid(Size, handle, psid); }
/// <summary>Initializes a new instance of the <see cref="SafePSID"/> class.</summary>
/// <param name="size">The size of memory to allocate, in bytes.</param>
@ -121,14 +43,20 @@ namespace Vanara.PInvoke
/// <see cref="System.Security.Principal.SecurityIdentifier"/> instance.
/// </summary>
/// <param name="si">The <see cref="System.Security.Principal.SecurityIdentifier"/> instance.</param>
public SafePSID(System.Security.Principal.SecurityIdentifier si) : this(GetBytes(si))
public SafePSID(System.Security.Principal.SecurityIdentifier si) : this(si is null ? null : GetBytes(si))
{
}
/// <summary>Initializes a new instance of the <see cref="SafePSID"/> class.</summary>
private SafePSID() : base() { }
/// <summary>Gets the SID for the current user</summary>
/// <value>The current user's SID.</value>
public static SafePSID Current => new SafePSID(System.Security.Principal.WindowsIdentity.GetCurrent().User);
/// <summary>A SID representing the Everyone Group (S-1-1-0).</summary>
public static SafePSID Everyone => CreateWellKnown(WELL_KNOWN_SID_TYPE.WinWorldSid);
/// <summary>
/// Verifies that the revision number is within a known range, and that the number of subauthorities is less than the maximum.
/// </summary>
@ -138,12 +66,7 @@ namespace Vanara.PInvoke
/// <summary>Copies the specified SID from a memory pointer to a <see cref="SafePSID"/> instance.</summary>
/// <param name="psid">The SID pointer. This value remains the responsibility of the caller to release.</param>
/// <returns>A <see cref="SafePSID"/> instance.</returns>
public static SafePSID CreateFromPtr(IntPtr psid)
{
var newSid = new SafePSID(GetLengthSid(psid));
CopySid(newSid.Size, newSid.handle, psid);
return newSid;
}
public static SafePSID CreateFromPtr(IntPtr psid) => new SafePSID(psid);
/// <summary>Creates a SID for predefined aliases.</summary>
/// <param name="WellKnownSidType">Member of the WELL_KNOWN_SID_TYPE enumeration that specifies what the SID will identify.</param>
@ -256,7 +179,7 @@ namespace Vanara.PInvoke
/// <summary>Gets the binary form of this SafePSID.</summary>
/// <returns>An array of bytes containing the Sid.</returns>
public byte[] GetBinaryForm() => base.GetBytes(0, Size);
public byte[] GetBinaryForm() => GetBytes(0, Size);
/// <summary>Returns a hash code for this instance.</summary>
/// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
@ -264,7 +187,11 @@ namespace Vanara.PInvoke
/// <summary>Returns a <see cref="string"/> that represents this instance.</summary>
/// <returns>A <see cref="string"/> that represents this instance.</returns>
public override string ToString() => ConvertSidToStringSid(this);
public override string ToString()
{
try { return ConvertSidToStringSid(this); }
catch { return !IsInvalid && !IsClosed ? "Invalid" : "0"; }
}
/// <summary>Creates a new object that is a copy of the current instance.</summary>
/// <returns>A new object that is a copy of this instance.</returns>
@ -277,5 +204,77 @@ namespace Vanara.PInvoke
return b;
}
}
/// <summary>Provides an array of SID pointers whose memory is disposed after use.</summary>
/// <seealso cref="Vanara.PInvoke.SafeHANDLE"/>
/// <seealso cref="System.Collections.Generic.IReadOnlyList{Vanara.PInvoke.PSID}"/>
public class SafePSIDArray : SafeHANDLE, IReadOnlyList<PSID>
{
private List<SafePSID> items;
/// <summary>Initializes a new instance of the <see cref="SafePSIDArray"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafePSIDArray(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafePSIDArray"/> class.</summary>
/// <param name="pSIDs">A list of <see cref="SafePSID"/> instances.</param>
public SafePSIDArray(IEnumerable<SafePSID> pSIDs) : this(pSIDs.Select(p => (PSID)p))
{
}
/// <summary>Initializes a new instance of the <see cref="SafePSIDArray"/> class.</summary>
/// <param name="pSIDs">A list of <see cref="SafePSID"/> instances.</param>
public SafePSIDArray(IEnumerable<PSID> pSIDs) : base()
{
items = pSIDs.Select(p => new SafePSID(p)).ToList();
SetHandle(items.Cast<IntPtr>().MarshalToPtr(i => LocalAlloc(LMEM.LPTR, i).DangerousGetHandle(), out _));
}
/// <summary>Initializes a new instance of the <see cref="SafePSIDArray"/> class.</summary>
private SafePSIDArray() : base() { }
/// <summary>Gets or sets the length of the array. This value must be set in order to interact with the elements.</summary>
/// <value>The length.</value>
public int Count
{
get => items?.Count ?? throw new InvalidOperationException("The length must be set before using this function.");
set
{
if (items != null) throw new InvalidOperationException("The length can only be set once.");
items = new List<SafePSID>(handle.ToIEnum<IntPtr>(value).Select(p => new SafePSID(p)));
}
}
/// <summary>Gets the <see cref="PSID"/> at the specified index.</summary>
/// <value>The <see cref="PSID"/>.</value>
/// <param name="index">The index.</param>
/// <returns>The PSID at the specified index.</returns>
/// <exception cref="InvalidOperationException">The length must be set before using this function.</exception>
public PSID this[int index] => items?[index] ?? throw new InvalidOperationException("The length must be set before using this function.");
/// <summary>Performs an implicit conversion from <see cref="SafePSIDArray"/> to <see cref="PSID[]"/>.</summary>
/// <param name="a">The <see cref="SafePSIDArray"/> instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator PSID[](SafePSIDArray a) => a.items.ConvertAll(p => (PSID)p).ToArray();
/// <summary>Returns an enumerator that iterates through the collection.</summary>
/// <returns>A <see cref="IEnumerator{PSID}"/> that can be used to iterate through the collection.</returns>
public IEnumerator<PSID> GetEnumerator() => items.ConvertAll(p => (PSID)p).GetEnumerator();
/// <inheritdoc/>
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<SafePSID>)items).GetEnumerator();
/// <inheritdoc/>
protected override bool InternalReleaseHandle()
{
if (items != null)
foreach (var p in items)
p.Dispose();
return LocalFree(handle) == HLOCAL.NULL;
}
}
}
}

View File

@ -3857,7 +3857,7 @@ namespace Vanara.PInvoke
[DllImport(Lib.Kernel32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("securitybaseapi.h", MSDNShortId = "1A911FCC-6D11-4185-B532-20FE6C7C4B0B")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeriveCapabilitySidsFromName([MarshalAs(UnmanagedType.LPWStr)] string CapName, out SafeLocalPSIDArray CapabilityGroupSids, out int CapabilityGroupSidCount, out SafeLocalPSIDArray CapabilitySids, out int CapabilitySidCount);
public static extern bool DeriveCapabilitySidsFromName([MarshalAs(UnmanagedType.LPWStr)] string CapName, out SafePSIDArray CapabilityGroupSids, out int CapabilityGroupSidCount, out SafePSIDArray CapabilitySids, out int CapabilitySidCount);
/// <summary>
/// The <c>DestroyPrivateObjectSecurity</c> function deletes a private object's security descriptor. For background information, see

View File

@ -0,0 +1,237 @@
using NUnit.Framework;
using System;
using System.Linq;
using Vanara.InteropServices;
using static Vanara.PInvoke.AdvApi32;
namespace Vanara.PInvoke.Tests
{
[TestFixture]
public class LsaTests
{
public SafeLSA_HANDLE hPol;
public SafePSID pSid;
[OneTimeSetUp]
public void _Setup()
{
hPol = LsaOpenPolicy(LsaPolicyRights.POLICY_ALL_ACCESS);
pSid = SafePSID.Current;
}
[OneTimeTearDown]
public void _TearDown()
{
hPol?.Dispose();
pSid?.Dispose();
}
[Test]
public void LsaAddEnumRemoveAccountRightsTest()
{
var rights = new[] { "SeBatchLogonRight", "SeRemoteInteractiveLogonRight" };
Assert.That(LsaAddAccountRights(hPol, pSid, rights, (uint)rights.Length), ResultIs.Successful);
string[] erights = null;
Assert.That(() => erights = LsaEnumerateAccountRights(hPol, pSid).ToArray(), Throws.Nothing);
Assert.That(erights, Is.EquivalentTo(rights));
Assert.That(LsaRemoveAccountRights(hPol, pSid, false, rights, (uint)rights.Length), ResultIs.Successful);
}
[Test]
public void LsaCreateAccountTest()
{
Assert.That(LsaCreateAccount(hPol, pSid, LsaAccountAccessMask.ACCOUNT_ALL_ACCESS, out var hAcct), ResultIs.Successful);
hAcct.Dispose();
}
[Test]
public void LsaCreateTrustedDomainExTest()
{
var tdi = new TRUSTED_DOMAIN_INFORMATION_EX
{
Name = new SafeLSA_UNICODE_STRING("MINE"),
Sid = pSid,
TrustType = TrustType.TRUST_TYPE_MIT,
TrustAttributes = TrustAttributes.TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL,
TrustDirection = TrustDirection.TRUST_DIRECTION_DISABLED
};
var tdai = new TRUSTED_DOMAIN_AUTH_INFORMATION { };
Assert.That(LsaCreateTrustedDomainEx(hPol, tdi, tdai, ACCESS_MASK.GENERIC_ALL, out var hDom), ResultIs.Failure);
}
[Test]
public void LsaDeleteTrustedDomainTest() => Assert.That(LsaDeleteTrustedDomain(hPol, pSid), ResultIs.Failure);
[Test]
public void LsaEnumerateAccountsWithUserRightTest()
{
PSID[] sids = null;
Assert.That(() => sids = LsaEnumerateAccountsWithUserRight(hPol).ToArray(), Throws.Nothing);
Assert.That(sids, Is.Not.Empty);
TestContext.Write(string.Join("\n", sids.Select(ConvertSidToStringSid)));
}
[Test]
public void LsaEnumerateTrustedDomainsTest()
{
LSA_TRUST_INFORMATION[] tis = null;
Assert.That(() => tis = LsaEnumerateTrustedDomains(hPol).ToArray(), Throws.Nothing);
tis.WriteValues();
}
[Test]
public void LsaGetAppliedCAPIDsTest() => Assert.That(() => LsaGetAppliedCAPIDs().WriteValues(), Throws.Nothing);
[Test]
public void LsaLookupNames2Test()
{
var names = new[] { Environment.UserDomainName, Environment.UserName };
Assert.That(LsaLookupNames2(hPol, LsaLookupNamesFlags.LSA_LOOKUP_ISOLATED_AS_LOCAL, (uint)names.Length, names,
out var memDoms, out var memSids), ResultIs.Successful);
using (memDoms)
using (memSids)
{
var doms = memDoms.ToStructure<LSA_REFERENCED_DOMAIN_LIST>().DomainList.ToArray();
var sids = memSids.ToArray<LSA_TRANSLATED_SID2>(names.Length);
for (var i = 0; i < names.Length; i++)
TestContext.WriteLine((names[i], sids[i].Use, (SafePSID)sids[i].Sid, sids[i].DomainIndex == -1 ? (string)null : doms[sids[i].DomainIndex].Name));
}
}
[Test]
public void LsaLookupNamesTest()
{
var names = new[] { Environment.UserDomainName, Environment.UserName };
Assert.That(LsaLookupNames(hPol, (uint)names.Length, names, out var memDoms, out var memSids), ResultIs.Successful);
using (memDoms)
using (memSids)
{
var doms = memDoms.ToStructure<LSA_REFERENCED_DOMAIN_LIST>().DomainList.ToArray();
var sids = memSids.ToArray<LSA_TRANSLATED_SID>(names.Length);
for (var i = 0; i < names.Length; i++)
TestContext.WriteLine((names[i], sids[i].Use, sids[i].RelativeId, doms[sids[i].DomainIndex].Name));
}
}
[Test]
public void LsaLookupPrivilegeValueTest() => Assert.That(LsaLookupPrivilegeValue(hPol, "SeSecurityPrivilege", out var luid), ResultIs.Successful);
[Test]
public void LsaLookupSids2Test()
{
var sids = new PSID[] { pSid };
Assert.That(LsaLookupSids2(hPol, LsaLookupSidsFlags.LSA_LOOKUP_PREFER_INTERNET_NAMES, (uint)sids.Length, sids, out var memDoms, out var memNames), ResultIs.Successful);
using (memDoms)
using (memNames)
{
var doms = memDoms.ToStructure<LSA_REFERENCED_DOMAIN_LIST>().DomainList.ToArray();
var names = memNames.ToArray<LSA_TRANSLATED_NAME>(sids.Length);
for (var i = 0; i < sids.Length; i++)
TestContext.WriteLine(((SafePSID)sids[i], names[i].Use, names[i].Name, names[i].DomainIndex == -1 ? (string)null : doms[names[i].DomainIndex].Name));
}
}
[Test]
public void LsaLookupSidsTest()
{
var sids = new PSID[] { pSid };
Assert.That(LsaLookupSids(hPol, (uint)sids.Length, sids, out var memDoms, out var memNames), ResultIs.Successful);
using (memDoms)
using (memNames)
{
var doms = memDoms.ToStructure<LSA_REFERENCED_DOMAIN_LIST>().DomainList.ToArray();
var names = memNames.ToArray<LSA_TRANSLATED_NAME>(sids.Length);
for (var i = 0; i < sids.Length; i++)
TestContext.WriteLine(((SafePSID)sids[i], names[i].Use, names[i].Name, names[i].DomainIndex == -1 ? (string)null : doms[names[i].DomainIndex].Name));
}
}
[Test]
public void LsaOpenGetSetSystemAccessAccountTest()
{
Assert.That(LsaOpenAccount(hPol, pSid, LsaAccountAccessMask.ACCOUNT_ALL_ACCESS, out var hAcct), ResultIs.Successful);
using (hAcct)
{
Assert.That(LsaGetSystemAccessAccount(hAcct, out var access), ResultIs.Successful);
access.WriteValues();
Assert.That(LsaSetSystemAccessAccount(hAcct, access), ResultIs.Successful);
}
}
[Test]
public void LsaOpenTrustedDomainByNameTest()
{
Assert.That(LsaOpenTrustedDomainByName(hPol, Environment.UserDomainName, ACCESS_MASK.GENERIC_READ, out var hTD), ResultIs.FailureCode((NTStatus)NTStatus.STATUS_OBJECT_NAME_NOT_FOUND));
}
[Test]
public void LsaQueryCAPsTest()
{
var ppsids = new PSID[] { pSid };
Assert.That(LsaQueryCAPs(ppsids, (uint)ppsids.Length, out var ptr, out var cnt), ResultIs.FailureCode((NTStatus)NTStatus.STATUS_INVALID_ID_AUTHORITY));
}
[Test]
public void LsaQuerySetDomainInformationPolicyTest()
{
Assert.That(LsaQueryDomainInformationPolicy(hPol, POLICY_DOMAIN_INFORMATION_CLASS.PolicyDomainEfsInformation, out var mem), ResultIs.FailureCode((NTStatus)NTStatus.STATUS_OBJECT_NAME_NOT_FOUND));
using (var input = SafeHGlobalHandle.CreateFromStructure(new POLICY_DOMAIN_QUALITY_OF_SERVICE_INFO { QualityOfService = POLICY_QOS.POLICY_QOS_DHCP_SERVER_ALLOWED }))
Assert.That(LsaSetDomainInformationPolicy(hPol, POLICY_DOMAIN_INFORMATION_CLASS.PolicyDomainQualityOfServiceInformation, input), ResultIs.FailureCode((NTStatus)NTStatus.RPC_NT_INVALID_TAG));
}
[Test]
public void LsaQuerySetForestTrustInformationTest()
{
Assert.That(LsaQueryForestTrustInformation(hPol, Environment.UserDomainName, out var mem), ResultIs.FailureCode((NTStatus)NTStatus.STATUS_INVALID_DOMAIN_STATE));
LSA_FOREST_TRUST_INFORMATION fti = default;
Assert.That(LsaSetForestTrustInformation(hPol, Environment.UserDomainName, fti, false, out var ci), ResultIs.FailureCode((NTStatus)NTStatus.STATUS_INVALID_DOMAIN_STATE));
}
[Test]
public void LsaQuerySetInformationPolicyTest()
{
Assert.That(LsaQueryInformationPolicy(hPol, POLICY_INFORMATION_CLASS.PolicyDnsDomainInformation, out var mem), ResultIs.Successful);
mem.ToStructure<POLICY_DNS_DOMAIN_INFO>().WriteValues();
Assert.That(LsaSetInformationPolicy(hPol, POLICY_INFORMATION_CLASS.PolicyDnsDomainInformation, mem.DangerousGetHandle()), ResultIs.Successful);
}
[Test]
public void LsaQuerySetTrustedDomainInfoByNameTest()
{
Assert.That(LsaQueryTrustedDomainInfoByName(hPol, Environment.UserDomainName, TRUSTED_INFORMATION_CLASS.TrustedDomainNameInformation, out var mem), ResultIs.FailureCode((NTStatus)NTStatus.STATUS_OBJECT_NAME_NOT_FOUND));
using (var hGl = SafeHGlobalHandle.CreateFromStructure<TRUSTED_DOMAIN_NAME_INFO>())
Assert.That(LsaSetTrustedDomainInfoByName(hPol, Environment.UserDomainName, TRUSTED_INFORMATION_CLASS.TrustedDomainNameInformation, hGl), ResultIs.FailureCode((NTStatus)NTStatus.STATUS_INVALID_INFO_CLASS));
}
[Test]
public void LsaQuerySetTrustedDomainInfoTest()
{
var dsid = GetDomainSid();
Assert.That(LsaQueryTrustedDomainInfo(hPol, dsid, TRUSTED_INFORMATION_CLASS.TrustedDomainNameInformation, out var mem), ResultIs.FailureCode((NTStatus)NTStatus.STATUS_INVALID_HANDLE));
using (var hGl = SafeHGlobalHandle.CreateFromStructure<TRUSTED_DOMAIN_NAME_INFO>())
Assert.That(LsaSetTrustedDomainInformation(hPol, dsid, TRUSTED_INFORMATION_CLASS.TrustedDomainNameInformation, hGl), ResultIs.Failure);
}
[Test]
public void LsaStoreRetrievePrivateDataTest()
{
const string keyName = "Random";
Assert.That(LsaStorePrivateData(hPol, keyName, keyName), ResultIs.Successful);
Assert.That(LsaRetrievePrivateData(hPol, keyName, out var privData), ResultIs.Successful); //FailureCode((NTStatus)NTStatus.STATUS_OBJECT_NAME_NOT_FOUND));
Assert.That(privData.ToStructure<LSA_UNICODE_STRING>().ToString(), Is.EqualTo(keyName));
}
private SafePSID GetDomainSid(string name = null)
{
var names = new[] { name ?? System.Environment.UserDomainName };
Assert.That(LsaLookupNames2(hPol, LsaLookupNamesFlags.LSA_LOOKUP_ISOLATED_AS_LOCAL, (uint)names.Length, names,
out var memDoms, out var memSids), ResultIs.Successful);
using (memDoms)
using (memSids)
{
var doms = memDoms.ToStructure<LSA_REFERENCED_DOMAIN_LIST>().DomainList.ToArray();
return doms.Length == 0 ? SafePSID.Null : new SafePSID(doms[0].Sid);
}
}
}
}

View File

@ -55,8 +55,8 @@ namespace Vanara.PInvoke.Tests
public void DeriveCapabilitySidsFromNameTest()
{
Assert.That(DeriveCapabilitySidsFromName("microsoft.hsaTestCustomCapability_q536wpkpf5cy2", out var grpsids, out var grpcnt, out var sids, out var cnt), ResultIs.Successful);
grpsids.Length = grpcnt; sids.Length = cnt;
Assert.That(grpsids.Length, Is.EqualTo(grpcnt));
grpsids.Count = grpcnt; sids.Count = cnt;
Assert.That(grpsids.Count, Is.EqualTo(grpcnt));
Assert.That(grpsids, Is.Not.Empty);
Assert.That(sids, Is.Not.Empty);
}

View File

@ -49,6 +49,7 @@
<Compile Include="AdvApi32\AuditTests.cs" />
<Compile Include="AdvApi32\AppMgmtTests.cs" />
<Compile Include="AdvApi32\ProviderInfo.cs" />
<Compile Include="AdvApi32\LsaTests.cs" />
<Compile Include="AdvApi32\SecurityBaseApiTests.cs" />
<Compile Include="AdvApi32\ServiceTests.cs" />
<Compile Include="AdvApi32\PSIDTests.cs" />

View File

@ -14,31 +14,5 @@ namespace Vanara.PInvoke.Tests
[TestFixture()]
public class SecurityTests
{
[Test]
public void StructMarshalTest()
{
bool allGood = true;
using (var mem = new SafeHGlobalHandle(4096))
{
//foreach (var asm in Assembly.GetExecutingAssembly().GetReferencedAssemblies().Where(n => n.Name.StartsWith("Vanara")).Select(n => Assembly.Load(n)))
//{
var asm = typeof(Vanara.PInvoke.AdvApi32).Assembly;
foreach (var tstr in asm.GetTypes().Where(t => t.IsValueType && !t.IsPrimitive && !t.IsEnum && !t.IsGenericType))
{
if (tstr.Name.StartsWith("<>")) continue;
try
{
Marshal.PtrToStructure(mem.DangerousGetHandle(), tstr);
}
catch (Exception e)
{
TestContext.WriteLine(e);
allGood = false;
}
}
//}
}
Assert.That(allGood);
}
}
}