我正在尝试在我的 .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/