internal static extern bool AdjustTokenPrivileges( [In] SafeTokenHandle TokenHandle, [In] bool DisableAllPrivileges, [In] ref TOKEN_PRIVILEGE NewState, [In] uint BufferLength, [In, Out] ref TOKEN_PRIVILEGE PreviousState, [In, Out] ref uint ReturnLength);
public void Revert() { var error = 0; // // All privilege operations must take place on the same thread // if (!this.currentThread.Equals(Thread.CurrentThread)) { throw new InvalidOperationException("Operation must take place on the thread that created the object"); } if (!this.NeedToRevert) { return; } // // This code must be eagerly prepared and non-interruptible. // RuntimeHelpers.PrepareConstrainedRegions(); try { // // The payload is entirely in the finally block // This is how we ensure that the code will not be // interrupted by catastrophic exceptions // } finally { var success = true; try { // // Only call AdjustTokenPrivileges if we're not going to be reverting to self, // on this Revert, since doing the latter obliterates the thread token anyway // if (this.stateWasChanged && (this.tlsContents.ReferenceCountValue > 1 || !this.tlsContents.IsImpersonating)) { var newState = new TOKEN_PRIVILEGE { PrivilegeCount = 1, Privilege = { Luid = this.luid, Attributes = this.initialState ? NativeMethods.SE_PRIVILEGE_ENABLED : NativeMethods.SE_PRIVILEGE_DISABLED } }; var previousState = new TOKEN_PRIVILEGE(); UInt32 previousSize = 0; if (!NativeMethods.AdjustTokenPrivileges(this.tlsContents.ThreadHandle, false, ref newState, ( UInt32 )Marshal.SizeOf(previousState), ref previousState, ref previousSize)) { error = Marshal.GetLastWin32Error(); success = false; } } } finally { if (success) { this.Reset(); } } } switch (error) { case NativeMethods.ERROR_NOT_ENOUGH_MEMORY: throw new OutOfMemoryException(); case NativeMethods.ERROR_ACCESS_DENIED: throw new UnauthorizedAccessException("Caller does not have the permission to change the privilege"); } if (error != 0) { throw new Win32Exception(error); } }
public static extern Boolean AdjustTokenPrivileges([In] SafeTokenHandle TokenHandle, [In] Boolean DisableAllPrivileges, [In] ref TOKEN_PRIVILEGE NewState, [In] DWORD BufferLength, [In][Out] ref TOKEN_PRIVILEGE PreviousState, [In][Out] ref DWORD ReturnLength);
private void ToggleState(Boolean enable) { var error = 0; // // All privilege operations must take place on the same thread // if (!this.currentThread.Equals(Thread.CurrentThread)) { throw new InvalidOperationException("Operation must take place on the thread that created the object"); } // // This privilege was already altered and needs to be reverted before it can be altered again // if (this.NeedToRevert) { throw new InvalidOperationException("Must revert the privilege prior to attempting this operation"); } // // Need to make this block of code non-interruptible so that it would preserve // consistency of thread oken state even in the face of catastrophic exceptions // RuntimeHelpers.PrepareConstrainedRegions(); try { // // The payload is entirely in the finally block // This is how we ensure that the code will not be // interrupted by catastrophic exceptions // } finally { try { // // Retrieve TLS state // this.tlsContents = Thread.GetData(tlsSlot) as TlsContents; if (this.tlsContents == null) { this.tlsContents = new TlsContents(); Thread.SetData(tlsSlot, this.tlsContents); } else { this.tlsContents.IncrementReferenceCount(); } var newState = new TOKEN_PRIVILEGE { PrivilegeCount = 1, Privilege = { Luid = this.luid, Attributes = enable ? NativeMethods.SE_PRIVILEGE_ENABLED : NativeMethods.SE_PRIVILEGE_DISABLED } }; var previousState = new TOKEN_PRIVILEGE(); UInt32 previousSize = 0; // // Place the new privilege on the thread token and remember the previous state. // if (!NativeMethods.AdjustTokenPrivileges(this.tlsContents.ThreadHandle, false, ref newState, ( UInt32 )Marshal.SizeOf(previousState), ref previousState, ref previousSize)) { error = Marshal.GetLastWin32Error(); } else if (NativeMethods.ERROR_NOT_ALL_ASSIGNED == Marshal.GetLastWin32Error()) { error = NativeMethods.ERROR_NOT_ALL_ASSIGNED; } else { // // This is the initial state that revert will have to go back to // this.initialState = (previousState.Privilege.Attributes & NativeMethods.SE_PRIVILEGE_ENABLED) != 0; // // Remember whether state has changed at all // this.stateWasChanged = this.initialState != enable; // // If we had to impersonate, or if the privilege state changed we'll need to revert // this.NeedToRevert = this.tlsContents.IsImpersonating || this.stateWasChanged; } } finally { if (!this.NeedToRevert) { this.Reset(); } } } switch (error) { case NativeMethods.ERROR_NOT_ALL_ASSIGNED: throw new PrivilegeNotHeldException(privileges[this.luid] as String); case NativeMethods.ERROR_NOT_ENOUGH_MEMORY: throw new OutOfMemoryException(); case NativeMethods.ERROR_ACCESS_DENIED: case NativeMethods.ERROR_CANT_OPEN_ANONYMOUS: throw new UnauthorizedAccessException("The caller does not have the right to change the privilege"); } if (error != 0) { throw new Win32Exception(error); } }