Skip to content

Instantly share code, notes, and snippets.

@AlphaModder
Last active December 23, 2021 02:49
Show Gist options
  • Save AlphaModder/be65deb4af490051b7c1b1c573ba9916 to your computer and use it in GitHub Desktop.
Save AlphaModder/be65deb4af490051b7c1b1c573ba9916 to your computer and use it in GitHub Desktop.
P/Invoke definitions for PTOKEN_PRIVILEGES, for use in GetTokenInformation or AdjustTokenPrivileges
[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
public int LowPart;
public int HighPart;
}
[StructLayout(LayoutKind.Sequential)]
public struct LUID_AND_ATTRIBUTES
{
public LUID Luid;
public int Attr;
}
[StructLayout(LayoutKind.Sequential)]
public struct PTOKEN_PRIVILEGES : IDisposable, IEnumerable<LUID_AND_ATTRIBUTES>
{
IntPtr value;
public PTOKEN_PRIVILEGES(IntPtr value)
{
this.value = value;
}
public int Count
{
get => this.value == IntPtr.Zero ? 0 : Marshal.ReadInt32(this.value);
private set => Marshal.WriteInt32(this.value, value);
}
private IntPtr GetIndexPtr(int index)
{
if (index < 0 || index >= this.Count) throw new IndexOutOfRangeException($"Index {index} out of range for Privileges with Count = {this.Count}!");
return this.value + 4 + Marshal.SizeOf<LUID_AND_ATTRIBUTES>() * index;
}
public LUID_AND_ATTRIBUTES this[int index]
{
get => Marshal.PtrToStructure<LUID_AND_ATTRIBUTES>(this.GetIndexPtr(index));
set => Marshal.StructureToPtr(value, this.GetIndexPtr(index), false);
}
public PTOKEN_PRIVILEGES(int count)
{
this.value = Marshal.AllocHGlobal(4 + count * Marshal.SizeOf<LUID_AND_ATTRIBUTES>());
this.Count = count;
}
public PTOKEN_PRIVILEGES(LUID_AND_ATTRIBUTES[] data) : this(data.Length)
{
for (int i = 0; i < this.Count; ++i) this[i] = data[i];
}
private struct Enumerator : IEnumerator<LUID_AND_ATTRIBUTES>
{
public PTOKEN_PRIVILEGES privileges;
public int index;
public LUID_AND_ATTRIBUTES Current => privileges[index];
object System.Collections.IEnumerator.Current => this.Current;
public bool MoveNext()
{
if (this.index + 1 >= privileges.Count) { return false; }
this.index += 1;
return true;
}
public void Reset()
{
this.index = -1;
}
public void Dispose()
{
this.privileges = default;
}
}
public IEnumerator<LUID_AND_ATTRIBUTES> GetEnumerator() => new Enumerator { privileges = this, index = -1 };
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
public void Dispose()
{
Marshal.FreeHGlobal(this.value);
this.value = IntPtr.Zero;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment