Vanara/PInvoke/Security/AdvApi32/LsaLookup.cs

209 lines
8.3 KiB
C#

using System;
using System.Runtime.InteropServices;
using Vanara.Extensions;
namespace Vanara.PInvoke
{
public static partial class AdvApi32
{
/// <summary>
/// <para>
/// The <c>LSA_OBJECT_ATTRIBUTES</c> structure is used with the LsaOpenPolicy function to specify the attributes of the connection to
/// the Policy object.
/// </para>
/// <para>
/// When you call LsaOpenPolicy, initialize the members of this structure to <c>NULL</c> or zero because the function does not use
/// the information.
/// </para>
/// </summary>
/// <remarks>
/// <para>The <c>LSA_OBJECT_ATTRIBUTES</c> structure is defined in the LsaLookup.h header file.</para>
/// <para>
/// <c>Windows Server 2008 with SP2 and earlier, Windows Vista with SP2 and earlier, Windows Server 2003, Windows XP/2000:</c> The
/// <c>LSA_OBJECT_ATTRIBUTES</c> structure is defined in the NTSecAPI.h header file.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/lsalookup/ns-lsalookup-_lsa_object_attributes typedef struct
// _LSA_OBJECT_ATTRIBUTES { ULONG Length; HANDLE RootDirectory; PLSA_UNICODE_STRING ObjectName; ULONG Attributes; PVOID
// SecurityDescriptor; PVOID SecurityQualityOfService; } LSA_OBJECT_ATTRIBUTES, *PLSA_OBJECT_ATTRIBUTES;
[PInvokeData("lsalookup.h", MSDNShortId = "ad05cb52-8e58-46a9-b3e8-0c9c2a24a997")]
[StructLayout(LayoutKind.Sequential)]
public struct LSA_OBJECT_ATTRIBUTES
{
/// <summary>Specifies the size, in bytes, of the LSA_OBJECT_ATTRIBUTES structure.</summary>
public int Length;
/// <summary>Should be <c>NULL</c>.</summary>
public IntPtr RootDirectory;
/// <summary>Should be <c>NULL</c>.</summary>
public IntPtr ObjectName;
/// <summary>Should be zero.</summary>
public int Attributes;
/// <summary>Should be <c>NULL</c>.</summary>
public IntPtr SecurityDescriptor;
/// <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, in 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();
}
/// <summary>
/// The LSA_STRING structure is used by various Local Security Authority (LSA) functions to specify a string. Also an example of
/// unnecessary over-engineering and re-engineering.
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Size = 8)]
[PInvokeData("LsaLookup.h", MSDNShortId = "aa378522")]
public struct LSA_STRING
{
/// <summary>
/// Specifies the length, in bytes, of the string pointed to by the Buffer member, not including the terminating null character,
/// if any.
/// </summary>
public ushort length;
/// <summary>
/// Specifies the total size, in bytes, of the memory allocated for Buffer. Up to MaximumLength bytes can be written into the
/// buffer without trampling memory.
/// </summary>
public ushort MaximumLength;
/// <summary>Pointer to a string. Note that the strings returned by the various LSA functions might not be null-terminated.</summary>
public string Buffer;
/// <summary>Initializes a new instance of the <see cref="LSA_STRING"/> struct from a string.</summary>
/// <param name="s">The string value.</param>
/// <exception cref="ArgumentException">String exceeds 32Kb of data.</exception>
public LSA_STRING(string s)
{
if (s == null)
{
length = MaximumLength = 0;
Buffer = null;
}
else
{
var l = s.Length;
if (l >= ushort.MaxValue)
throw new ArgumentException("String too long");
Buffer = s;
length = (ushort)l;
MaximumLength = (ushort)(l + 1);
}
}
/// <summary>Gets the number of characters in the string.</summary>
public int Length => length;
/// <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() => Buffer.Substring(0, Length);
/// <summary>Performs an implicit conversion from <see cref="LSA_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_STRING value) => value.ToString();
}
/// <summary>
/// <para>
/// The <c>LSA_TRANSLATED_NAME</c> structure is used with the LsaLookupSids function to return information about the account
/// identified by a SID.
/// </para>
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/lsalookup/ns-lsalookup-_lsa_translated_name typedef struct
// _LSA_TRANSLATED_NAME { SID_NAME_USE Use; LSA_UNICODE_STRING Name; LONG DomainIndex; } LSA_TRANSLATED_NAME, *PLSA_TRANSLATED_NAME;
[PInvokeData("lsalookup.h", MSDNShortId = "edea8317-5cdf-4d1e-9e6d-fcf17b91adb7")]
[StructLayout(LayoutKind.Sequential)]
public struct LSA_TRANSLATED_NAME
{
/// <summary>An SID_NAME_USE enumeration value that identifies the type of SID.</summary>
public SID_NAME_USE Use;
/// <summary>
/// An LSA_UNICODE_STRING structure that contains the isolated name of the translated SID. An isolated name is a user, group, or
/// local group account name without the domain name (for example, user_name, rather than Acctg\user_name).
/// </summary>
public LSA_UNICODE_STRING Name;
/// <summary>
/// The index of an entry in a related LSA_REFERENCED_DOMAIN_LIST data structure which describes the domain that owns the
/// account. If there is no corresponding reference domain for an entry, then DomainIndex will contain a negative value.
/// </summary>
public int DomainIndex;
}
/// <summary>
/// <para>
/// The <c>LSA_TRANSLATED_SID2</c> structure contains SIDs that are retrieved based on account names. This structure is used by the
/// LsaLookupNames2 function.
/// </para>
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/lsalookup/ns-lsalookup-_lsa_translated_sid2 typedef struct
// _LSA_TRANSLATED_SID2 { SID_NAME_USE Use; PSID Sid; LONG DomainIndex; ULONG Flags; } LSA_TRANSLATED_SID2, *PLSA_TRANSLATED_SID2;
[PInvokeData("lsalookup.h", MSDNShortId = "792de958-8e24-46d8-b484-159435bc96e3")]
[StructLayout(LayoutKind.Sequential)]
public struct LSA_TRANSLATED_SID2
{
/// <summary>
/// An SID_NAME_USE enumeration value that identifies the use of the SID. If this value is SidTypeUnknown or SidTypeInvalid, the
/// rest of the information in the structure is not valid and should be ignored.
/// </summary>
public SID_NAME_USE Use;
/// <summary>The complete SID of the account.</summary>
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
/// account. If there is no corresponding reference domain for an entry, then DomainIndex will contain a negative value.
/// </summary>
public int DomainIndex;
/// <summary>Not used.</summary>
public uint Flags;
}
/// <summary>A custom marshaler for functions using LSA_STRING so that managed strings can be used.</summary>
/// <seealso cref="ICustomMarshaler"/>
internal class LsaStringMarshaler : ICustomMarshaler
{
public static ICustomMarshaler GetInstance(string cookie) => new LsaStringMarshaler();
public void CleanUpManagedData(object ManagedObj)
{
}
public void CleanUpNativeData(IntPtr pNativeData)
{
if (pNativeData == IntPtr.Zero) return;
Marshal.FreeCoTaskMem(pNativeData);
pNativeData = IntPtr.Zero;
}
public int GetNativeDataSize() => Marshal.SizeOf(typeof(LSA_STRING));
public IntPtr MarshalManagedToNative(object ManagedObj)
{
var s = ManagedObj as string;
if (s == null) return IntPtr.Zero;
var str = new LSA_STRING(s);
return str.MarshalToPtr(Marshal.AllocCoTaskMem, out var _);
}
public object MarshalNativeToManaged(IntPtr pNativeData)
{
if (pNativeData == IntPtr.Zero) return null;
var ret = pNativeData.ToStructure<LSA_STRING>();
var s = (string)ret.ToString().Clone();
//LsaFreeMemory(pNativeData);
return s;
}
}
}
}