I am trying to obtain a privilege in my .NET 4 C# application. This code works and the privilege is obtained successfully, but only on 64bit systems. When the same code is run on a 32bit system, the code fails at AdjustTokenPrivileges with this exception:
Invalid access to memory location. (Exception from HRESULT: 0x800703E6)
I've tried modifying the code to fix the issue, but nothing has been working and I am pretty stumped.
Any ideas on why this fails on 32bit systems? It fails on both Windows Vista and 7 32bit, so it is a 32bit specific problem.
Updated with correct code in 2022. The below code is now correct and can be used in your application.
The method:
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();
}
Implementation:
EnableDisablePrivilege("SeManageVolumePrivilege", true);
PInvoke declarations:
[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);
Fixed, just had to put a ref before NewState:
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, bool DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState, uint Bufferlength, IntPtr PreviousState, IntPtr ReturnLength);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With