C# - AdjustTokenPrivileges 不适用于 32 位

标签 c# .net pinvoke 32bit-64bit privileges

我正在尝试在我的 .NET 4 C# 应用程序中获取权限。此代码有效并且成功获得了权限,但仅限于 64 位系统。当相同的代码在 32 位系统上运行时,代码在 AdjustTokenPrivileges 失败,出现以下异常:

对内存位置的访问无效。 (HRESULT 异常:0x800703E6)

我已经尝试修改代码来解决这个问题,但没有任何效果,我很困惑。

关于为什么这在 32 位系统上失败的任何想法?它在 Windows Vista 和 7 32 位上均失败,因此这是一个特定于 32 位的问题。

在 2022 年更新了正确的代码。下面的代码现在是正确的,可以在您的应用程序中使用。

方法:

public static void EnableDisablePrivilege(string PrivilegeName, bool EnableDisable)
{
    if (!LookupPrivilegeValue(null, PrivilegeName, out var luid)) throw new Exception($"EnableDisablePrivilege: LookupPrivilegeValue failed: {Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()).Message}");

    if (!OpenProcessToken(Process.GetCurrentProcess().SafeHandle, TokenAccessLevels.AdjustPrivileges, out var tokenHandle)) throw new Exception($"EnableDisablePrivilege: OpenProcessToken failed: {Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()).Message}");

    var tokenPrivileges = new TOKEN_PRIVILEGES { PrivilegeCount = 1, Privileges = new[] { new LUID_AND_ATTRIBUTES { LUID = luid, Attributes = (uint)(EnableDisable ? 2 : 4) } } };
    if (!AdjustTokenPrivileges(tokenHandle, false, ref tokenPrivileges, 0, IntPtr.Zero, out _))
    {
        tokenHandle.Dispose();
        throw new Exception($"EnableDisablePrivilege: AdjustTokenPrivileges failed: {Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()).Message}");
    }
    else tokenHandle.Dispose();
}

实现:

EnableDisablePrivilege("SeManageVolumePrivilege", true);

PInvoke 声明:

[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
    private uint lowPart;
    private int highPart;

    public uint LowPart { get => lowPart; set => lowPart = value; }

    public int HighPart { get => highPart; set => highPart = value; }
}

[StructLayout(LayoutKind.Sequential)]
public struct LUID_AND_ATTRIBUTES
{
    private LUID luid;
    private uint attributes;

    public LUID LUID { get => luid; set => luid = value; }

    public uint Attributes { get => attributes; set => attributes = value; }
}

[StructLayout(LayoutKind.Sequential)]
public struct TOKEN_PRIVILEGES
{
    private uint privilegeCount;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
    private LUID_AND_ATTRIBUTES[] privileges;

    public uint PrivilegeCount { get => privilegeCount; set => privilegeCount = value; }

    public LUID_AND_ATTRIBUTES[] Privileges { get => privileges; set => privileges = value; }
}

[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool OpenProcessToken(SafeProcessHandle ProcessHandle, TokenAccessLevels DesiredAccess, out SafeAccessTokenHandle TokenHandle);

[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool AdjustTokenPrivileges(SafeAccessTokenHandle TokenHandle, bool DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState, uint BufferLength, IntPtr PreviousState, out uint ReturnLength);

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, out LUID lpLuid);

最佳答案

已修复,只需在 NewState 之前放置一个 ref:

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, bool DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState, uint Bufferlength, IntPtr PreviousState, IntPtr ReturnLength);

关于C# - AdjustTokenPrivileges 不适用于 32 位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13616330/

相关文章:

c# - convert to auto-property 是什么意思?

c# - 文件映射架构

c# - 理论上是否可以从 C# 访问任何库(又名 PInvoke 在幕后做什么)?

c# - 调用 'ShutdownBlockReasonCreate'函数不能阻止用户关闭系统

c# - 循环浏览 chrome 选项卡并根据网址关闭页面

c++ - 分析动态 pinvoke

c# - MVVM-处理后备数据

c# - 如何在 C# 中获取整个请求的 url?

c# - 在复杂/单窗口 WPF 应用程序中使用 Thread 的最佳方式

.net - 为什么我不应该使用 Process.GetCurrentProcess().Kill() 退出我的 WinForm 应用程序?