首页 > 解决方案 > 从 LUID 检索权限名称

问题描述

我正在编写一种方法来找出与给定 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, 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();
}

作为参考,我的 LUID 结构如下所示

[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
    public UInt32 LowPart;
    public Int32 HighPart;
}

在执行此代码时,我得到一个 ERROR_INSUFFICIENT_BUFFER (122) 而不是与 LUID 关联的权限名称。

有人可以帮助我解决上述代码中缺少的阻止我检索特权名称的内容吗?

标签: c#winapipinvoke

解决方案


书面“更好”的 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 luid, sbuilder, ref nameLength))
    {
        Console.WriteLine("Unable to lookup value.");
        Console.WriteLine(Marshal.GetLastWin32Error());
        return null;
    }

    return sbuilder.ToString();
}

推荐阅读