I am writing a method for finding out the privilege name associated with a given LUID. The following is the code for the same :
private string PrivilegeName(LUID luid)
{
StringBuilder sbuilder = new StringBuilder();
int nameLength = 0;
IntPtr ptrToLuid = Marshal.AllocHGlobal(Marshal.SizeOf(luid));
Marshal.StructureToPtr(luid, ptrToLuid, true);
if(!InvokeAPI.LookupPrivilegeName(null, ptrToLuid, null, ref nameLength))
{
Console.WriteLine("Unable to lookup value.");
Console.WriteLine(Marshal.GetLastWin32Error());
Marshal.FreeHGlobal(ptrToLuid);
return null;
}
sbuilder.EnsureCapacity(nameLength + 1);
InvokeAPI.LookupPrivilegeName(null, ptrToLuid, sbuilder, ref nameLength);
Marshal.FreeHGlobal(ptrToLuid);
return sbuilder.ToString();
}
For reference my LUID structure looks like this
[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
public UInt32 LowPart;
public Int32 HighPart;
}
While executing this code I get a ERROR_INSUFFICIENT_BUFFER (122) instead of the privilege name associated with the LUID.
Could someone help me out on what I am missing in the above code that prevents me from retrieving the privilege name ?
Written "better" pinvoke, written inside a comment an explanation of the error. Written inside comments the funny handling of lengths of LookupPrivilegeName
.
// https://www.pinvoke.net/default.aspx/advapi32.lookupprivilegename
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool LookupPrivilegeName(
string lpSystemName,
ref LUID lpLuid,
StringBuilder lpName,
ref int cchName);
private static string PrivilegeName(LUID luid)
{
StringBuilder sbuilder = new StringBuilder();
int nameLength = 0;
LookupPrivilegeName(null, ref luid, sbuilder, ref nameLength);
// Will always fail with nameLength == 0. We simply check that nameLength != 0
if (nameLength == 0)
{
Console.WriteLine("Unable to lookup value.");
Console.WriteLine(Marshal.GetLastWin32Error());
return null;
}
// On "failure" (that is really a success, only we get
// just the length), nameLength is the length required
// for the buffer, including the \0
sbuilder.EnsureCapacity(nameLength);
// On a success of this second call, nameLength is the
// "real" length of the name, excluding the \0
// so on a success, now nameLength = oldNameLength - 1
// Don't ask, it is absurd... Classical case where the
// Windows API are quite random in their handling of
// buffer lengths
if (!LookupPrivilegeName(null, ref luid, sbuilder, ref nameLength))
{
Console.WriteLine("Unable to lookup value.");
Console.WriteLine(Marshal.GetLastWin32Error());
return null;
}
return sbuilder.ToString();
}