问题描述
我正在编写一种方法来找出与给定 LUID 关联的权限名称。以下是相同的代码:
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,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,sbuilder,ref nameLength);
Marshal.FreeHGlobal(ptrToLuid);
return sbuilder.ToString();
}
作为参考,我的 LUID 结构如下
[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
public UInt32 LowPart;
public Int32 HighPart;
}
在执行此代码时,我得到一个 ERROR_INSUFFICIENT_BUFFER (122) 而不是与 LUID 关联的权限名称。
有人能帮我解决上面代码中我缺少的阻止我检索权限名称的内容吗?
解决方法
写“更好”的pinvoke,在评论中写下对错误的解释。写在内部评论 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 nameLength))
{
Console.WriteLine("Unable to lookup value.");
Console.WriteLine(Marshal.GetLastWin32Error());
return null;
}
return sbuilder.ToString();
}